I read the discussion in the following link, but my application is different so I want to ask for advice on how to proceed.
I am making a wearable device that is encapsulated in silicone, there is no way to charge or replace the battery. It only needs to update the android (and ios) phone once every 2 minutes but the phone needs to hear all the updates even when the screen is off. A cloud service will update other phones that are out of reach.
I've got a prototype on an nrf52840 dongle. I also have an android app which was modified from the blinky example to only scan and do android notifications by reading the values advertised by the device. I calculated that I would get 3+ years from a single CR2032 assuming I use an insight ISP1807 chip and advertise with +8 TX for a full second, only every 2 minutes. Meaning 10 adverts repeated with a 100ms duration to give a 1 second advertising burst. The device then sleeps for 119 seconds and the process repeats.
My problem is with the behaviour of android since it seems to reduce scanning on background tasks. This seems to make either beacon devices and connection-less devices, or android, a poor choice since I believe they will stop communicating effectively.
To get background scanning to work at all, I created an IntentService that looks like this. I am not an android expert but I have a broad programming background (20+ years)
public class MyScanningIntentService extends IntentService { // public static final String EXTRA_PARAM2 = "no.nordicsemi.android.blinky.extra.PARAM2"; Context mContext; public MyScanningIntentService() { super("MyScanningIntentService"); } @Override protected void onHandleIntent(Intent intent) { mContext = this; if (intent != null) { final ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)// SCAN_MODE_BALANCED .setReportDelay(500) .setUseHardwareBatchingIfSupported(false) .build(); final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner(); final List<ScanFilter> scanFilters = new ArrayList<>(); // My manufacturer id is 0xFFFF during dev. // This seems necessary or the background scan doesn't work at all on my samsung s5 ScanFilter scanFilter = new ScanFilter.Builder() .setManufacturerData(0xFFFF, null) .build(); scanFilters.add(scanFilter); scanner.startScan(scanFilters , settings, scanCallback); } } private final ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(final int callbackType, @NonNull final ScanResult result) { CheckScanDevice(result); } @Override public void onBatchScanResults(@NonNull final List<ScanResult> results) { for (int zzz = 0; zzz < results.size(); zzz++) { ScanResult result = results.get(zzz); CheckScanDevice(result); } } @Override public void onScanFailed(final int errorCode) { // TODO This should be handled } } private void CheckScanDevice(ScanResult scanResult) { //Read advert data using scanRecord.getManufacturerSpecificData(0xFFFF) // Raise notification when necessary } };
In order to reduce battery usage on the android (and iOS) I was going to use a timer to start and stop scanning because I know that each device will advertise every 2 minutes. So I only need to scan again for each device during its advertising period which is every 2 minutes. I wanted to support many devices on each phone so I planned to do a continuous foreground scan for 2 minutes to learn the timing of each of the devices and then to only scan to coincide with each devices advert time. (I hope you understand my clumsy wording!)
I do not have an android 8 device to test on.
- I am not sure what SDK version to target. I want to support as many android phones as possible.
- Will I have fewer problems if I establish a connection to the phones? It seems like scannign is the problem but I am not 100% confident about this.
- I think this will increase battery usage on the device.
- It might reduce the number of phones I support
- Does my scanning code look appropriate? I think I already see reduced scanning behaviour on my android Samsung S5.
- Should I make my app replace the wallpaper or something more drastic to ensure the phone keeps scanning?
Any advice is appreciated