Я пытаюсь создать приложение, которое позволяет пользователям регистрировать маршруты (местоположения /GPS). Для обеспечения регистрации местоположений, даже когда экран выключен, я создал foreground service
для регистрации местоположений. Я храню местоположения в Room Database
, который вводится в мой сервис с использованием Dagger2
.
Однако этот сервис убит Android, что, конечно, нехорошо. Я мог бы подписаться на предупреждения о нехватке памяти, но это не решает основную проблему, из-за которой мой сервис погибает через ~ 30 минут на современном высококачественном телефоне с Android 8.0
Я создал минимальный проект только с действием "Hello world" и сервисом: https://github.com/RandomStuffAndCode/AndroidForegroundService
Служба запущена в моем классе Application
, а запись маршрута запущена через Binder
:
// Application
@Override
public void onCreate() {
super.onCreate();
mComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
Intent startBackgroundIntent = new Intent();
startBackgroundIntent.setClass(this, LocationService.class);
startService(startBackgroundIntent);
}
// Binding activity
bindService(new Intent(this, LocationService.class), mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
// mConnection starts the route logging through 'Binder' once connected. The binder calls startForeground()
Мне, вероятно, не нужен флаг BIND_AUTO_CREATE
, я тестировал разные флаги, пытаясь не убить мой сервис - пока не повезло.
При использовании профилировщика не возникает утечек памяти, использование памяти стабильно составляет ~ 35 МБ:
Используя adb shell dumpsys activity processes > tmp.txt
, я могу подтвердить, что foregroundServices=true
и мой сервис заняли 8-е место в списке LRU:
Proc # 3: prcp F/S/FGS trm: 0 31592:com.example.foregroundserviceexample/u0a93 (fg-service)
Кажется, что невозможно создать приоритетный сервис, которому можно доверять, чтобы не быть убитым. Так что мы можем сделать? Ну...
- Поместите службу в отдельный процесс, пытаясь позволить Android убить пользовательский интерфейс/действия, оставив службу в покое. Возможно, поможет, но не кажется гарантией
- Сохраняйте все на службе, например, Комната базы данных. Каждая переменная, каждый пользовательский класс, каждый раз, когда любое из изменений, а затем запустить службу с
START_STICKY
. Это кажется расточительным и не приводит к очень красивому коду, но это, вероятно, сработает... несколько. В зависимости от того, сколько времени потребуется Android для повторного создания службы после ее уничтожения, большая часть местоположений может быть потеряна.
Это действительно текущее состояние дел в фоновом режиме на Android? Разве нет лучшего способа?
ОБНОВЛЕНИЕ: внесение в белый список приложения для оптимизации заряда аккумулятора (его отключение) не останавливает работу моего сервиса
ОБНОВЛЕНИЕ: Использование Context.startForegroundService()
для запуска службы не улучшает ситуацию
ОБНОВЛЕНИЕ: Таким образом, это действительно происходит только на некоторых устройствах, но это происходит последовательно на них. Я думаю, вам придется сделать выбор: либо не поддерживать огромное количество пользователей, либо написать действительно некрасивый код. Потрясающие.