Как предотвратить, чтобы приложение / служба FireMonkey перестало работать в фоновом режиме? - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь написать приложение FireMonkey, которое должно выполнять некоторую работу в фоновом режиме (не очень интенсивная задача), даже если пользователь устройства переключается на другое приложение или дисплей отключается.В этой задаче я периодически отправляю HTTP-запрос (с TIdHTTP) на сервер, чтобы получить небольшой фрагмент данных и проверить, работает ли приложение.

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

  1. Добавление приложения через пользовательский интерфейс Android в список «защищенных приложений» (отключение оптимизации энергопотребления для приложения / «продолжать работать во время экрана»выключен ").

  2. Я создал локальный сервис (TAndroidService) с флажком закрепления (START_STICKY) через мастер проекта и переместил туда код задачи.

Запуск службы из хост-приложения:

// LIntent and LServiceName are stored in TForm1
procedure TForm1.StartMyService();
begin
  LIntent := TJIntent.Create();
  LServiceName := 'com.embarcadero.services.MyService';
  LIntent.setClassName(TAndroidHelper.Context.getPackageName(), TAndroidHelper.StringToJString(LServiceName));
  TAndroidHelper.Activity.startService(LIntent);
end;

Событие OnStartCommand в службе выглядит следующим образом:

function TMyServiceDM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
  Result := TJService.JavaClass.START_STICKY;

  LThread := TThread.CreateAnonymousThread(procedure
    begin

      while True do
      begin
        // ... Task performed here periodically and exits loop when needed ...

        // Sleep for 1 minute
        LThread.Sleep(60000);
      end;

      // Before thread stops, also stop the Java service
      JavaService.stopSelf(StartId);
    end);

  LThread.FreeOnTerminate := False;
  LThread.Start();
end;

Приложение продолжает работать в фоновом режиме и даже при отображениивыключен НО только тогда, когда устройство подключено через кабель к источнику питания (например, через USB-кабель с моей машиной).Если кабель питания отключен, приложение, кажется, мгновенно останавливается при выключении экрана, даже если приложение остается на переднем плане.

Я что-то не так делаю?Как я могу сохранить свой сервис в фоновом режиме (например, приложения для обмена сообщениями, которые делают что-то подобное)?Я знаю, что в Android 6.0 (уровень API 23) и выше используется функция «Doze», и Google хочет, чтобы их разработчики использовали FCM (Firebase Cloud Messaging).Я читал об этом только недавно и надеялся, что хотя бы отключение оптимизации питания для приложения решит эту проблему, но нет.

1 Ответ

0 голосов
/ 26 сентября 2018

Например, для Android pre-oreo вы можете сделать это, выполнив:

в AndroidManifest.xml

  <receiver android:name="com.myapp.StartServiceBroadcastReceiver">  
    <intent-filter>  
      <action android:name="android.intent.action.BOOT_COMPLETED" />  
    </intent-filter>  
  </receiver> 

в StartServiceBroadcastReceiver, который я делаю:

  @Override
  public void onReceive(Context context, Intent intent) {

    try {

        /* start the location service */  
        Intent startServiceIntent = new Intent(context, LocationService.class);
        context.startService(startServiceIntent);

    } catch (Throwable e){ Log.e(TAG, "Exception", e); }  

  }

но это больше не работает на Android Oreo +!теперь startservice return

Запрещено запускать службу. Intent

, вместо этого необходимо вызвать startForegroundService, но у этого есть огромный недостаток, чтобы показать значок уведомления конечному пользователю:(

...