Covellite++  Version: 2.3.0 Revision: 2580 Platform: x64 Build: 15:23 16.10.2020
Кроссплатформенный фреймворк для разработки приложений на С++
Фоновое выполнение задач в коде С++

Проблема

Если из кода С++ запустить дополнительный поток (boost::thread), то при деактивации программы возможна одна из двух ситуаций (причем заранее предсказать это невозможно):

  • Полная и окончательная остановка работы этого потока через несколько секунд работы (вероятно, из-за выгрузки главного .so файла).
  • Переход потока в режим работы, при котором ему передается управление очень редко (раз в 20-30 минут, даже если выставлена задержка в 1 сек., видимо, понижается приоритет потока).

Решение

Для гарантированной работы фонового потока С++ с указанным интервалом времени при неактивном приложении, необходимо:

  • Добавить в проект Packaging класс сервиса, который при старте будет загружать главный .so файл С++ программы и выполнять в фоновом потоке любое тривиальное действие (этот фоновый поток необходим, чтобы система не 'убивала' сервис):

BackgroundService.java

package com.Simple;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.os.SystemClock;
public class BackgroundService extends Service
{
@Override
public void onCreate()
{
System.loadLibrary("Simple");
Thread BackgroundThread = new Thread(new Runnable()
{
@Override
public void run()
{
int Index = 0;
while(true)
{
Log.v("Service", "Index: " + Index);
Index++;
SystemClock.sleep(1000);
}
}
});
BackgroundThread.setPriority(Thread.MAX_PRIORITY);
BackgroundThread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
}
  • Зарегистрировать в AndroidManifest.xml созданный класс как сервис:
<application ...>
<service android:name="com.Simple.BackgroundService" android:exported="false"/>
...
  • В классе, наследуемом от NativeActivity, добавить запуск сервиса (будет запущен при первой активации программы):
import android.os.Bundle;
import android.content.Intent;
public class Simple extends NativeActivity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
startService(new Intent(this, BackgroundService.class));
}
  • В коде С++ добавить функцию, которая будет вызываться при загрузке .so файла при старте сервиса и в ней запустить рабочий фоновый поток:
extern "C"
{
jint JNI_OnLoad(JavaVM *, void *)
{
// Здесь можно запустить поток
return JNI_VERSION_1_6;
}
} // extern "C"
Заметки
Важно понимать, что сервис может быть остановлен и перезапущен в любой момент времени (.so файл будет выгружен и рабочий поток прекратит работу), поэтому следует озаботиться сохранением данных, полученных через параметр (ANativeActivity *) при активации программы.