Проблемы с тарифом обратного вызова служб определения местоположения, когда телефон заблокирован - PullRequest
0 голосов
/ 19 мая 2019

Я создаю код для непрерывного отслеживания местоположения на устройствах Android, который должен продолжать работать, даже когда телефон заблокирован. Я реализовал сервис переднего плана для этого, основываясь на примерах Google. Несмотря на то, что он продолжает работать, когда телефон заблокирован, я заметил значительно более длительные интервалы между обратными вызовами и регистрацией местоположения, которые, кажется, происходят, когда телефон заблокирован с выключенным экраном. Есть ли какой-то способ предотвратить это / я все еще что-то упускаю, чтобы предотвратить включение фоновых сервисных ограничений?

Мой код в настоящее время запускается как привязанный сервис из приложения, затем он преобразуется в фоновый сервис, как только приложение заказывает его для отслеживания местоположения. Как только приложение выходит на передний план, служба перестает быть привязанной и превращается в службу переднего плана. Все мои тесты проводились на Nokia 2.1 под управлением Android 9 Go Edition.

Для запроса местоположения я настраиваюсь с интервалом в 1 минуту и ​​максимальным временем ожидания 5 минут. Однако в заблокированном состоянии я заметил, что между точками задержка достигает целых 20 минут.

Я пробовал с более жесткими границами с интервалом 10 секунд, максимальное время ожидания 1 минута. Похоже, что между исправлениями местоположения производительность по-прежнему падает до порядка 60-80 секунд, хотя, похоже, это происходит реже.

(Я думаю) важные части службы определения местоположения ниже. Если требуется больше деталей, просто спросите, код не является секретным.

//Snip: preamble

public class LocationTracker extends Service {
    private final String TAG = LocationTracker.class.getSimpleName();

    private final String NOTIFICATION_CHANNEL = "LocationTrackerChannel";
    private int NOTIFICATION_ID = 12345678;

    private FusedLocationProviderClient locationClient;
    private LocationRequest locationRequest;
    private Looper eventLooper;

    private Boolean running = false;

    // Snip: processing related definitions/variables

    public class LocalBinder extends Binder {
        LocationTracker getService() {
            return LocationTracker.this;
        }
    }
    private IBinder binder = new LocalBinder();

    LocationCallback locationResultHandler = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult result) {
            super.onLocationResult(result);
            Log.i(TAG,"New location: " + result.getLastLocation() + " " + result.getLocations().size());
            for (Location loc : result.getLocations()) {
                // Snip: process results
            }

            if (unsent >= 5) {
                // send result over network
            }
        }
    };

    public LocationTracker() {
    }

    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate!");
        locationClient = LocationServices.getFusedLocationProviderClient(this);

        HandlerThread eventHandlerThread = new HandlerThread(TAG);
        eventHandlerThread.start();
        eventLooper = eventHandlerThread.getLooper();

        locationRequest = new LocationRequest();
        locationRequest.setInterval(60*1000);
        locationRequest.setMaxWaitTime(5*60*1000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL,
                getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.createNotificationChannel(channel);
    }

    @Override
    public IBinder onBind(Intent intent) {
        stopForeground(true);
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        if (running)
            startForeground(NOTIFICATION_ID, BuildNotification());
        return true;
    }

    @Override
    public void onRebind(Intent intent) {
        stopForeground(true);
        super.onRebind(intent);
    }

    public boolean startLocationTracking(double latOffset, double lonOffset, long timeOffset, String host, int port) {
        Log.i(TAG, "Starting tracking");
        if (running) stopLocationTracking();
        try {
            // Snip: setup processing parameters

            // Setup actual geolocation updates
            locationClient.requestLocationUpdates(locationRequest, locationResultHandler, eventLooper);

            // Setup service to run in background
            startService(new Intent(getApplicationContext(), LocationTracker.class));

            running = true;

            return true;
        } catch (SecurityException unlikely) {
            Log.w(TAG, unlikely.toString());
            locationTransmitter = null;
            return false; // report failure
        }
    }

    public void stopLocationTracking() {
        Log.i(TAG, "Stopping tracking");
        if (!running) return;
        try {
            locationClient.removeLocationUpdates(locationResultHandler);
        } catch (SecurityException unlikely) {
            //ignore
        }
        stopSelf();
        locationTransmitter = null;
        running = false;
    }

    private Notification BuildNotification() {
        PendingIntent openAppIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MainActivity.class), 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setContentIntent(openAppIntent)
                .setContentTitle("WALKINTRACKER")
                .setContentText("Recording location")
                .setSmallIcon(R.drawable.common_full_open_on_phone)
                .setTicker("Recording location")
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setChannelId(NOTIFICATION_CHANNEL);

        return builder.build();
    }
}
...