using altbeacon library on android 8(oreo), background beacon scan not working

android background bluetooth scanning
android beacon library example
android beacon library ibeacon example
beacon library js
android beacon app
beacon monitoring android
altbeacon ranging
beacon detector

My app using Altbeacon library for beacon scanning.

my code working well to api level 24(android 7) but doesn't not working on oreo(8.0.0)

at first, my gradle setting compileSdkVersion and targetSdkVersion is 26, i thought it was because of this.

so, i reference this**https://developer.android.com/about/versions/oreo/background.html#services**, fix my gradle setting(compileSdkVersion 25, targetSdkVersion 25).

and install this app on device (apilevel 24, 26) on 24 level device working well, but 26 is not.

that's my code.

In Activity.onCreate

    Intent intent = new Intent(this, BeaconService.class);
    startService(intent);

in BeaconService(Altbeacon Library)

@Override
public void onBeaconServiceConnect()
{
    final Handler h = new Handler(getApplicationContext().getMainLooper());
    Beacon[] tempBeacon = new Beacon[2];

    bm.addRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(final Collection beacons, final Region region) {

            if (beacons.size() > 0) {

                //call method this context

            }
            Log.d("beacon", "detect");
        }
    });

    try
    {
            bm.startRangingBeaconsInRegion(new Region("test", Identifier.parse("A1200001-EABC-9876-D001-E00000000001"), Identifier.parse("32001"), null));
    } catch (RemoteException e) {
    }
}

EDIT: beacon is detected, but it takes a very long time.

And i saw log below

03-15 18:25:02.639 2419-2419/app.eco.inulibrary D/ScanJobScheduler: Scheduling ScanJob (job:208352940/app.eco.inulibrary/org.altbeacon.beacon.service.ScanJob) to run every 310000 millis 03-15 18:25:02.917 2419-2419/app.eco.inulibrary D/ScanJobScheduler: Scheduling ScanJob (job:208352940/app.eco.inulibrary/org.altbeacon.beacon.service.ScanJob) to run every 300000 millis 03-15 18:36:00.176 2419-2419/app.eco.inulibrary I/ScanJob: Running periodic scan job: instance is org.altbeacon.beacon.service.ScanJob@a6ca148 03-15 18:36:01.751 2419-3951/app.eco.inulibrary D/RangeState: adding id1: a1200001-eabc-9876-d001-e00000000001 id2: 32001 id3: 2001 to existing range for: org.altbeacon.beacon.service.RangedBeacon@bf2cb74 03-15 18:36:01.968 2419-2419/app.eco.inulibrary D/Callback: attempting callback via local broadcast intent: org.altbeacon.beacon.range_notification

how to solve this problem?

Android O introduces new limits on Background services. Services like the BeaconService shown in the code will be killed by the operating system shortly after the app switches to background mode.

The AndroidBeaconLibrary has been updated to account for this by using the Android job scheduler to handle beacon scanning on Android 8+. But for this to work, you must use the BeaconManager or RegionBootsrap classes to start scanning, rather than starting the BeaconService directly with an Intent. This way, the library will know to use the job scheduler on Android 8+ and the BeaconService on earlier versions.

Further, you will need to move your code that starts scanning and initializes ranging out of an Activity and into a custom android.app.Application class. This is because Android 8 will kill your Activity along with the app when it is in the background, and you will need to have your ranging set up in an Android component that is created automatically when the app is re-launched in the background for periodic scanning.

I recommend you rework your setup be as described in Starting an App in the Background in the sample code here. That sample only sets up monitoring, but you can start ranging in the didDetermineStateForRegion callback shown.

Finally, make sure you have library version 2.13+ which has full support for changes in Android 8.1.

To understand more about how background beacon detection has changed in Android 8, see my blog post here.

Oreo: App never wakes up · Issue #707 · AltBeacon/android-beacon , In oder to simulate the iBeacon, i use another android phone and an GitHub is home to over 50 million developers working together to host and is the default on Android 8+), and can be turned off with beaconManager. Between these background runs, the library will use intent-based delivery of scan  Android versions 8+ restrict services from running in the background to only 10 minutes after an app leaves the foreground. This blocks background beacon detections. By default on Android 8+, the library will use the JobScheduler to run scans, but these are limited to at most every 15 minutes. For use cases where apps need frequent beacon scanning in the background, a foreground service is a viable alternative.

AltBeacon/android-beacon-library, GitHub is home to over 50 million developers working together to host and Android O 8.1 - Avoid 15 minute background limit #642 Scan for beacons with the screen off and the phone not powered externally. This has nothing to do with the library, but is an Android 8 restriction on your custom service. You are correct that Android 8 does not let you do more than scanning for ~10 minutes every ~15 minutes when your app is in the background and beacons are present. When beacons are not present, you can scan indefinitely for them until one appears.

The results of my tests:

  1. Android Oreo (API >= 26) For Oreo i best solution call method startScan() with PendingIntent (BroadcastReceiver) . Small example:

    ...
    val bluetoothManager = applicationContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager 
    val bluetoothAdapter = bluetoothManager.adapter
    bleScanner = bluetoothAdapter.getBluetoothLeScanner()
    val listOfFiters = ArrayList<ScanFilter>()
    val builder = ScanFilter.Builder()
    val filter = builder.build()
    listOfFiters.add(filter)
    
    val startScan = bleScanner?.startScan(listOfFiters, null, getPendingIntent())
    
    ...
    
    private fun getPendingIntent(): PendingIntent {
    return PendingIntent.getBroadcast(
        this, REQ_CODE,
        Intent(this.applicationContext, BeaconBLEReceiver::class.java),
        PendingIntent.FLAG_UPDATE_CURRENT)
    }
    

    Manifest:

    <receiver android:name=".BeaconBLEReceiver" >
        <intent-filter>
            <action android:name="BluetoothDevice.ACTION_FOUND" />
            <action android:name="BluetoothDevice.EXTRA_UUID" />
            <action android:name="BluetoothDevice.EXTRA_RSSI" />
        </intent-filter>
    </receiver>
    

This implicit (is not on the list of exceptions, but it works?) Broadcast works for at least several hours (Huawei Y6, Mate10). Restart can be solved by WorkManager.

  1. Api <= 26 startScan() does not support PendingIntent - BroadcastReceiver can not be started. startScan() is only started once with callback. Here is probably the best solution android-beacon-library or custom implementation background service with startScan().
  2. Only warnings. Android Nearby Notifications ends December 6th, 2018 (google block)

Android Oreo Background Service Limitations - Proximity, In my application i have a service that run in background and start a beacon scan​… So I want that continuously scan for beacons (for 8 hours). when i close the app, after a while, the service in background don't work anymore. Yes, with Android O and later, background services are not really a good fit  Using a long-running scanning service. This is the default on Android 4.3-7.x, and will NOT use intent-based delivery of scan results. It delivers results directly to the long-running scanning service via a callback. If you want to use this mechanism on Android 8+, you must do two things.

Using a foreground service, Android versions 8+ restrict services from running in the background to only 10 does not use more battery, but if you use it to schedule more frequent scans  I try to develop an service using altBeacon library version 2.15.2 at android 8.1. Looking at the comments above, I expected that ranging would work well even with the screen off. However, size of the beacon list is always 0 at 'didRangeBeaconsInRegion' callback, even though there are active beacons around with the screen off.

How does BLE scanning work for altbeacon library on Oreo?, Before Android L Android Altbeacon library used background running /2017/08​/07/beacon-detection-with-android-8 and it did clear something but I am still not  Allows Android apps to interact with BLE beacons. Contribute to AltBeacon/android-beacon-library development by creating an account on GitHub.

Beacon Detection With Android 8, If your app is running when this happens, this is no problem. Android Beacon Library with the default backgroundScanPeriod of 300 seconds. But after that initial background detection, finding a second beacon can be much slower Running periodic scan job: instance is org.altbeacon.beacon.service. The ScanJob class is designed to be an internal component of the library that you don't have to worry about. If you are running the library in an app on Android 8.0, the library will use it by default to schedule scans for beacons.

Comments
  • i use dependencies 'implementation 'org.altbeacon:android-beacon-library:2.+' maybe it downloads latest library version. thanks. i'll try your answer
  • I figured something out that you might also be interested in @davidyoung, put as an alternative answer below:
  • Clever solution! On Android 8, if the user leaves the screen on (without your app in the foreground) for over 10 minutes the background scanning service will get killed, yes? This may be rare and acceptable, but it can happen. While technically legal, this does seem to go against the intent of Android 8's restrictions, so I would not be surprised if a future Android release blocks this. Still cool though.
  • by the way, the scan on screen on feature is something I have wanted to add to the library for awhile. if you can figure out a good way to make it integrated I'd welcome a pull request.
  • That is a good point on the background process @davidyoung, but you are probably right on that one. I wonder if you can programmatically bring it to the foreground and send it back to the background to reset the 10 minutes? Probably not worth the effort, but an interesting experiment. I definitely don't mind showing you how I put it together, but I am pretty new and haven't worked too much with github yet... I'm also pretty disorganized (bad fundamentals and etiquette) since I am the only person working on my projects lol, but I will email a copy over!
  • But what would be really useful down the road might be a way to schedule a single scan to happen on ScreenOn from a service