Получать обновления местоположения, даже когда телефон заблокирован?

Я пытаюсь получать обновления местоположения, когда мой телефон заблокирован. Я использую службу, которая запускается моей основной деятельностью. Я получаю обновления местоположения, когда приложение открыто, просто отлично, но при блокировке телефона служба продолжает работать, но сохраняемое местоположение всегда одно и то же.

import static com.example.kromby.mapsapplication.featureOptions.date;


public class BackgroundLocationUpdate extends Service implements GoogleApiClient.ConnectionCallbacks, LocationListener {

// I've removed code that does not relate to the question so please ignore most imports. 

    private GoogleApiClient mClient;

    private boolean connected = false;

    private LocationRequest mLocationRequest;

    public static List<LatLng> globalLatLng = Collections.synchronizedList(new ArrayList<LatLng>());

    public static GoogleMap mMap;

    Location mLastLocation;

    private static double latitude;

    private static double longitude;

    public LatLng mLatLng = new LatLng(latitude, longitude);

    private static final String TAG = "MapActivity";

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @TargetApi(Build.VERSION_CODES.O)
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Runnable r = new Runnable() {

            @Override
            public void run() {
                buildGoogleApiClient();
            }
        };

        Runnable q = new Runnable() {

            @Override
            public void run() {

                long p = System.currentTimeMillis() + 4000;

                boolean continueLooping = true;

                while (continueLooping) {

                    if (System.currentTimeMillis() >= p) {

                        locationUpdates();

                        continueLooping = false;
                    }
                }
            }
        };

        Thread mThread = new Thread(r);

        Thread mThreadTwo = new Thread(q);

        mThread.start();

        mThreadTwo.start();

        return Service.START_STICKY;
    }

    public void locationUpdates() {

        long i = System.currentTimeMillis();

        while (true) {

              if (System.currentTimeMillis() == i) {

                  i = System.currentTimeMillis() + 3000;

                  // Checks that the application has user permissions to location.

                  if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED 
                      && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                      return;
                  }

                  mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mClient);

                  // Once the phone is locked this will return the same location each time and not change.

                  Log.d(TAG, "Client is working " + mClient.isConnected() + "\n Current mLastLocation LatLng " + mLastLocation.getLatitude() + "," + mLastLocation.getLatitude());

                  latitude = mLastLocation.getLatitude();

                  longitude = mLastLocation.getLongitude();

                  Log.d(TAG, "latitude = " + String.valueOf(latitude) );

                  mLatLng = new LatLng(latitude, longitude);

                  globalLatLng.add(mLatLng);

                  Log.d(TAG, "Global List = " + globalLatLng);

            }
        }
    }

    protected synchronized void buildGoogleApiClient() {

        mClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API).build();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        mClient.connect();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

        connected = true;

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(3000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }

        LocationServices.FusedLocationApi.requestLocationUpdates(mClient, mLocationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {

        mClient.connect();
    }

    @Override
    public void onDestroy() {

        Log.i(TAG, "OnDestroy method called");
    }
}

Моя цель - получить местоположение, сохранить его в списке Latlng и сохранить его в текстовом файле, который можно прочитать и показать на карте в виде полилинии. Я запускаю их в двух отдельных потоках, потому что клиенты Google API не заканчиваются, поэтому он не достигнет какого-либо другого кода.


person Ricky    schedule 04.04.2018    source источник
comment
Почему вы решили создать собственный поток вместо реализации LocationListener?   -  person M. Prokhorov    schedule 04.04.2018
comment
Из того, что я пробовал, прослушиватель местоположения вообще не работал в фоновом режиме.   -  person Ricky    schedule 04.04.2018
comment
Сомневаюсь, что использование первоклассного способа получения обновлений лучше, чем накатывание вручную. Что конкретно представляет собой эта услуга? Вы читали эту статью?   -  person M. Prokhorov    schedule 04.04.2018
comment
Я думаю, вам понадобится PowerManager.WakeLock, чтобы процессор не спал, когда экран выключен.   -  person user221256    schedule 04.04.2018
comment
@ user221256, нет, не совсем так. Ему нужно, чтобы приложение работало даже при выключенном экране, а не мешало телефону выключиться.   -  person M. Prokhorov    schedule 04.04.2018
comment
@M.Porkhorov Я думаю, это намеренная услуга?   -  person Ricky    schedule 04.04.2018
comment
Просто странно, как это работает, он получает местоположение, но местоположение остается неизменным каждый раз после блокировки телефона.   -  person Ricky    schedule 04.04.2018
comment
@M.Prokhorov М.Прохоров Отключение экрана через некоторое время приведет к тому, что процессор перейдет в спящий режим. Обычный WakeLock предотвращает выключение экрана и переход процессора в спящий режим. Частичный WakeLock позволяет выключать экран, не позволяя процессору спать.   -  person user221256    schedule 04.04.2018
comment
@ Рики, нет, я имею в виду, это служба переднего или заднего плана? Между ними есть большая разница в более поздних версиях Android. Обратитесь к статье, которую я связал. Поведение не является странным, ваше приложение просто не получает обновления, но вы вызываете метод для получения последнего известного местоположения. Без обновлений последнее известное местоположение не изменится.   -  person M. Prokhorov    schedule 04.04.2018
comment
@ user221256, если бы процессор спал, он бы вообще не писал в список. Я все еще не думаю, что это проблема, которую можно решить с помощью wake-locks.   -  person M. Prokhorov    schedule 04.04.2018
comment
@ М.Прохоров Есть ли способ проверить, какой из них я использую? Я не совсем уверен.   -  person Ricky    schedule 04.04.2018
comment
@user221256 user221256 Если бы я должен был реализовать блокировку пробуждения, где бы я ее поместил?   -  person Ricky    schedule 04.04.2018
comment
@Ricky, это зависит от кода, который вы используете для запуска службы. Служба переднего плана использует startForeground. Я снова советую прочитать статью, в которой рассказывается об изменениях в фоновых процессах в Android О   -  person M. Prokhorov    schedule 04.04.2018
comment
@Ricky Это зависит от дизайна вашего сервиса, но, вероятно, объявите его как поле в вашем сервисе. Позвоните WakeLock.acquire(), когда начнете прослушивать обновления, и WakeLock.release(), когда прекратите. Не держите WakeLock без необходимости, так как это может привести к повышенному расходу заряда аккумулятора. Я настоятельно рекомендую вам прочитать документы: developer.android.com/reference /андроид/ОС/. Если вы собираетесь попробовать это.   -  person user221256    schedule 04.04.2018
comment
@M.Prokhorov служба запущена в основном приложении на переднем плане   -  person Ricky    schedule 04.04.2018
comment
вы можете проверить мой ответ здесь: stackoverflow.com/a/50245508/6033946   -  person iDeveloper    schedule 09.05.2018