I have an application scanning BluetoothLE devices (temperature). The application is whitelisted in the list for battery optimizations and uses a PARTIAL_WAKE_LOCK.
It works like a charm with a Zebra TC25 Android 7.1.2 using a thread scanning BLE devices every 10 minutes independently of the android device state.
However the same application does not work at all with a samsung galaxy S10+ Android 10 when the screen is off (it works when screen is on). I know that the simple thread method will not work because of doze mode. So I also tried these ways :
setExactAndAllowWhileIdle(TJAlarmManager.JavaClass.RTC_WAKEUP, time,PendingIntent) and firebase cloud messaging sending high priority message. Alarm method has limitations but fcm has not as far as I know.
These 2 ways also failed. The fcm message is received and the alarm triggers, both run the BLEDiscover procedure below to run a bluetooth scan, but no bluetooth device are discovered.
Here is what happens in two situations. In the fisrt one, the screen is on, it always works :
12-08 12:39:58.994: D/BluetoothAdapter(30351): STATE_ON
12-08 12:39:58.994: D/BluetoothLeScanner(30351): could not find callback wrapper
12-08 12:39:58.995: D/BluetoothAdapter(30351): STATE_ON
12-08 12:39:58.997: D/BluetoothAdapter(30351): STATE_ON
12-08 12:39:58.997: D/BluetoothLeScanner(30351): Start Scan with callback
12-08 12:39:59.001: D/BluetoothLeScanner(30351): onScannerRegistered() - status=0 scannerId=14 mScannerId=0
12-08 12:39:59.965: I/info(30351): FMX: tags (Nil): 4154326484 - BLEDiscoverLEDevice - device touvé : C_T_801362
12-08 12:39:59.977: I/info(30351): FMX: tags (Nil): 4154326484 - BLEDiscoverLEDevice - TAG touvé : C_T_801362
12-08 12:39:59.977: I/info(30351): FMX: tags (Nil): 4154326484 - Trame 6E2A7207 - T° 19,06
12-08 12:39:59.983: I/info(30351): FMX: alerte (Nil): 4154326484 - BLEAlerte
12-08 12:40:04.928: I/info(30351): FMX: tags (Nil): 4154326484 - BLEDiscoverLEDevice - device touvé : P_T_8038DB
12-08 12:40:04.948: I/info(30351): FMX: tags (Nil): 4154326484 - BLEDiscoverLEDevice - TAG touvé : P_T_8038DB
12-08 12:40:04.948: I/info(30351): FMX: tags (Nil): 4154326484 - Trame 6E2A6C07 - T° 19,00
12-08 12:40:04.955: I/info(30351): FMX: alerte (Nil): 4154326484 - BLEAlerte
12-08 12:40:19.038: D/BluetoothAdapter(30351): STATE_ON
12-08 12:40:19.038: D/BluetoothLeScanner(30351): Stop Scan with callback
As soon as the screen is off, it never works:
12-08 12:44:02.094: D/BluetoothAdapter(30351): STATE_ON
12-08 12:44:02.094: D/BluetoothLeScanner(30351): could not find callback wrapper
12-08 12:44:02.096: D/BluetoothAdapter(30351): STATE_ON
12-08 12:44:02.098: D/BluetoothAdapter(30351): STATE_ON
12-08 12:44:02.098: D/BluetoothLeScanner(30351): Start Scan with callback
12-08 12:44:02.101: D/BluetoothLeScanner(30351): onScannerRegistered() - status=0 scannerId=10 mScannerId=0
12-08 12:44:23.110: D/BluetoothAdapter(30351): STATE_ON
12-08 12:44:23.110: D/BluetoothLeScanner(30351): Stop Scan with callback
So thread, alarm and fcm lead to the same result, that is when screen is off, no BLE devices are discoverd.
Here is the code :
// Discovering BLE devices
procedure TfData.BLEDiscover();
begin
FBluetoothManagerLE := TBluetoothLEManager.Current;
FBluetoothManagerLE.OnDiscoverLEDevice := BLEDiscoverLEDevice;
FBluetoothManagerLE.StartDiscovery(10000);
end;
procedure TfData.BLEDiscoverLEDevice(const Sender: TObject; const ADevice: TBluetoothLEDevice; Rssi: Integer; const ScanResponse: TScanResponse);
var tag, i: Integer;
vals : TArray<Byte>;
trame : string;
temperature : single;
begin
log('tags', 'BLEDiscoverLEDevice - device touvé : ' + ADevice.DeviceName);
lockTags.Acquire;
if ADevice.DeviceName <> '' then begin
for tag := Low(Tags) to High(Tags) do begin
if (ADevice.DeviceName = Tags[tag].K_TAG) then begin
log('tags', 'BLEDiscoverLEDevice - TAG touvé : ' + ADevice.DeviceName);
trame := '';
vals := ADevice.AdvertisedData.ExtractPair(TScanResponseKey.ServiceData).Value;
for i := 0 to length(vals) - 1 do begin
trame := trame + IntToHex(vals[i]);
end;
temperature:=BLEReadTrame(trame);
log('tags', 'Trame '+trame + ' - T° '+ formatFloat('0.00',temperature));
if (temperature <> tagNullTemp) then begin
Tags[tag].T_LAST := temperature;
Tags[tag].DtLastTemp := now;
end;
end;
break;
end;
end;
end;
lockTags.Release;
end;
Edit : Please note I use fcm method to get real time gps position, so the device gets GPS and sends it to server over Internet, it always works , even screen off.