我的应用程序使用Altbeacon库进行信标扫描。
我的代码适用于api level 24(android 7)但不适用于oreo(8.0.0)
首先,我的gradle设置compileSdkVersion和targetSdkVersion是26,我认为是因为这个。
所以,我引用了这个** https://developer.android.com/about/versions/oreo/background.html#services **, 修复我的gradle设置(compileSdkVersion 25,targetSdkVersion 25)。
并在设备上安装此应用程序(apilevel 24,26) 在24级设备上运行良好,但26不是。
这是我的代码。
在 Activity.onCreate
中 Intent intent = new Intent(this, BeaconService.class);
startService(intent);
BeaconService (Altbeacon图书馆)
@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) {
}
}
编辑: 检测到信标,但需要很长时间。
我看到下面的日志
03-15 18:25:02.639 2419-2419 / app.eco.inulibrary D / ScanJobScheduler:安排ScanJob(作业:208352940 / app.eco.inulibrary / org.altbeacon.beacon.service.ScanJob)运行每一个310000毫升 03-15 18:25:02.917 2419-2419 / app.eco.inulibrary D / ScanJobScheduler:调度ScanJob(作业:208352940 / app.eco.inulibrary / org.altbeacon.beacon.service.ScanJob)每300000毫秒运行一次 03-15 18:36:00.176 2419-2419 / app.eco.inulibrary I / ScanJob:运行定期扫描作业:实例是org.altbeacon.beacon.service.ScanJob@a6ca148 03-15 18:36:01.751 2419-3951 / app.eco.inulibrary D / RangeState:将id1:a1200001-eabc-9876-d001-e00000000001 id2:32001 id3:2001添加到现有范围:org.altbeacon.beacon。 service.RangedBeacon@bf2cb74 03-15 18:36:01.968 2419-2419 / app.eco.inulibrary D / Callback:尝试通过本地广播意图回调:org.altbeacon.beacon.range_notification
如何解决这个问题?
答案 0 :(得分:1)
Android O对后台服务引入了新的限制。在应用切换到后台模式后不久,操作系统就会杀死代码中显示的BeaconService
等服务。
AndroidBeaconLibrary已经更新以解决此问题,方法是使用Android作业调度程序处理Android 8+上的信标扫描。但为了实现这一点,您必须使用BeaconManager
或RegionBootsrap
类开始扫描,而不是直接使用BeaconService
启动Intent
。这样,图书馆就会知道在Android 8+上使用作业调度程序,在早期版本中使用BeaconService
。
此外,您需要移动开始扫描并初始化范围的代码Activity
并进入自定义android.app.Application
类。这是因为Android 8会在应用程序处于后台时将您的活动与应用程序一起终止,并且您需要在Android组件中设置您的范围,该组件是在后台重新启动应用程序时自动创建的扫描。
我建议您按照示例代码here中在后台启动应用中的说明重新设置您的设置。该示例仅设置监控,但您可以在显示的didDetermineStateForRegion
回调中开始测距。
最后,请确保您拥有2.13+的库版本,该版本完全支持Android 8.1中的更改。
要详细了解Android 8中背景信标检测的变化情况,请参阅我的博文here.
答案 1 :(得分:0)
因此,我已经使用了很长一段时间,试图找出在后台扫描信标的最佳方法,而又不会用Foreground Service通知惹恼用户。到目前为止,这是我发现的:
屏幕驱动扫描 :
考虑了一段时间后,我想到了附近对“ ScreenOn”事件进行了快速扫描,终于得出了这个结论。我曾想做类似的事情,但认为最好是运行前台服务而不是希望我的扫描作业按时计划。
一般结构包括以下内容:
结果 :
我的服务在MainActivity上启动,该服务启动了ScannerService。我将其设置为从MainActivity在前台onStartCommand上运行(当用户打开应用程序时),并保持运行状态,直到他们锁定屏幕为止。屏幕锁定后,应用程序将根据屏幕活动进入循环。
当用户解锁手机(在Android 7-上)时,随着服务切换到后台服务,前台通知会立即清除。在Android 8上,向启动前台BeaconManager服务所用的ID发送通知,然后在切换到后台设置的2.5秒后在处理程序上取消通知。该通知阻止用户获得“后台服务正在使用电池”通知,但足够短,足以在解锁屏幕之前消失。
答案 2 :(得分:0)
我的测试结果:
Android Oreo(API> = 26) 对于奥利奥,我最好的解决方案是使用P endingIntent(BroadcastReceiver)调用方法 startScan()。小例子:
...
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)
}
清单:
<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>
此隐式广播(不在list of exceptions上,但是有效吗?)广播至少可以工作几个小时(Huawei Y6,Mate10)。重新启动可以通过WorkManager解决。