androidbackground-processandroid-bluetoothandroid-workmanagerandroid-jobscheduler

Android Background Bluetooth Processing: What's the best approach?


I've just develop an Android app (minSdkVersion 23/ targetSdkVersion 29) that can connect to a BluetoothLE device to obtain data periodically.

Now, in the MainActivity (not the first activity), I do the following registering the broadcastReciever:

public class StatusActivity extends AppCompatActivity {    
    BleService mBleService;
    BleScanCallback mScanCallback;
    BroadcastReceiver mBroadcastReceiver;    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mBroadcastReceiver = new LibBleBroadcastReceiver(this);
        IntentFilter intentFilter = new IntentFilter()    
        intentFilter.addAction(BleService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BleService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BleService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BleService.ACTION_DATA_AVAILABLE);
        intentFilter.addAction(BleService.ACTION_DID_WRITE_CHARACTERISTIC);
        intentFilter.addAction(BleService.ACTION_DID_FAIL);
        registerReceiver(mBroadcastReceiver, intentFilter);
    
        mScanCallback = new LibBleScanCallback(this);
        intent = new Intent(this, BleService.class);
        connection = new LibBleServiceConnection(this);
    
        startService(intent);
        if (!bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
            throw new IllegalStateException("bindService not successful");
        }
    }
    ...
    public void onDeviceDiscovered(String device_address){
        device_connected.activateNotifications(mBleService, connected_device);
        scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
            public void run() {
                device_connected.requestTemperature(mBleService, connected_device);
            }
        }, 0, 30, TimeUnit.MINUTES);
    }
    ...
}

In the AndroidManifest.xml it's declared the BleService:

<service android:name=".bluetooth.BleService" android:enabled="true" />

And then, the user select a device (from a bluetooth scan) and connect to it to obtain data from BLE device.

Once is connected and discovered (services and characteristics), I schedule a task every 30 minutes to obtain data from the device.

All the callbacks that are executed when the device is connected/discovered/dataRecieved are in the StatusActivity not in the BleService (intent) to make changes in the UI (although in the background it would not be necessary).

In the other hand, I have to mantain always a bakground process too, because my app, starts a BLE Advertising to make the phone an LE Device, so always have to be "powered on" to make others devices find the phone.

The problem is that when I put the app in Background or I kill the app this schedule doesn't execute or execute a few times until the process is killed by android.

What would be the best approach to execute this service in background mode? Considering that if the app is killed, the device (I think) will be disconnected so I should connect another time to the device (I save the MAC address to reconnect so it's not a problem) and execute the requestData method? WorkManager/JobScheduler/AlarmManager/ForegroundService?

Could someone help me to know how to implement and understand the Background lifecycle and how to access all data I need to manage in background?

Thank you!


Solution

  • The only working solution for working in Background is ForegroundService, other ones will be destroyed when your device will enter Doze mode. You can find more detailed information in this article, it describes all the obstacles in background working while scanning BLE devices.