问题
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?
回答1:
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.
回答2:
So I have been playing with this for a long time, trying to figure out the best way to scan for beacons in the background without annoying users with Foreground Service notifications. Here is what I have figured out so far:
- Running in the Foreground: Obviously we need to run scanning in the foreground to get anywhere. So I have used some snippets from @davidyoung and built a beacon scanner to run in a background service. I used to run beaconManager on the background settings, but Android 8 makes that difficult so I switched to running it in the foreground
- Stupid Notification: After switching to running the scanner in the foreground, I realized just how annoying that Foreground Service notification was. I tried to make a custom notification that at least looked cool, since my users would be stuck with it anyway, but it is still annoying. Then it dawned on me... Run the scanner in the Foreground when the screen is off, then switch to background scanning when the screen is on!
Screen Driven Scanning:
After thinking about this for a while, I finally came to this conclusion after remembering that Nearby does a quick scan on 'ScreenOn' events. I thought about doing something similar, but figured it was better to just run a Foreground Service instead of hoping my scanning jobs got scheduled in time.
The general structure included the following:
- A BroadcastReceiver class and a Service class as found here.
- 2 Notification calls
- A PostDelayed Handler
Results:
My service is started on the MainActivity, which starts my ScannerService. I have it set to run in the foreground onStartCommand from the MainActivity (when the user opens the app) and stay running until they lock their screen. Once the screen locks, the app enters a loop based on screen activity.
When the user unlocks their phone (on Android 7-), the foreground notification clears immediately as the service switches to a background service. On Android 8, send a notification to the same ID used to start the foreground BeaconManager service, then cancel the notification on a handler after 2.5 seconds while switching to background settings. The notification prevents the user from getting the "Background Services are Using Battery" notification, but is short enough to disappear before they unlock the screen.
回答3:
The results of my tests:
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.
- 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().
- Only warnings. Android Nearby Notifications ends December 6th, 2018 (google block)
来源:https://stackoverflow.com/questions/49295996/using-altbeacon-library-on-android-8oreo-background-beacon-scan-not-working