在android 8(oreo)上使用altbeacon库,后台信标扫描无法正常工作

时间:2018-03-15 09:43:10

标签: android bluetooth-lowenergy altbeacon android-8.0-oreo android-ibeacon

我的应用程序使用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

如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

Android O对后台服务引入了新的限制。在应用切换到后台模式后不久,操作系统就会杀死代码中显示的BeaconService等服务。

AndroidBeaconLibrary已经更新以解决此问题,方法是使用Android作业调度程序处理Android 8+上的信标扫描。但为了实现这一点,您必须使用BeaconManagerRegionBootsrap类开始扫描,而不是直接使用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通知惹恼用户。到目前为止,这是我发现的:

  • 在前景中运行 :显然,我们需要在前景中运行扫描才能到达任何地方。因此,我使用了@davidyoung的一些代码片段,并构建了一个信标扫描程序以在后台服务中运行。我曾经在后台设置上运行beaconManager,但Android 8却使它变得困难,因此我切换到在前台运行
  • 愚蠢的通知 :在切换到在前台运行扫描仪后,我意识到,前台服务通知是多么令人讨厌。我试图做出一个自定义通知,至少看起来很酷,因为我的用户无论如何都会被它吸引住,但是它仍然很烦人。然后它突然出现在我身上... 在屏幕关闭时在前景中运行扫描仪,然后在屏幕打开时切换到后台扫描!

屏幕驱动扫描

考虑了一段时间后,我想到了附近对“ ScreenOn”事件进行了快速扫描,终于得出了这个结论。我曾想做类似的事情,但认为最好是运行前台服务而不是希望我的扫描作业按时计划。

一般结构包括以下内容:

  • 一个{em> BroadcastReceiver类和一个 Service类,位于here
  • 2个通知电话
  • PostDelayed处理程序

结果

我的服务在MainActivity上启动,该服务启动了ScannerService。我将其设置为从MainActivity在前台onStartCommand上运行(当用户打开应用程序时),并保持运行状态,直到他们锁定屏幕为止。屏幕锁定后,应用程序将根据屏幕活动进入循环。

当用户解锁手机(在Android 7-上)时,随着服务切换到后台服务,前台通知会立即清除。在Android 8上,向启动前台BeaconManager服务所用的ID发送通知,然后在切换到后台设置的2.5秒后在处理程序上取消通知。该通知阻止用户获得“后台服务正在使用电池”通知,但足够短,足以在解锁屏幕之前消失。

答案 2 :(得分:0)

我的测试结果:

  1. 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解决。

  1. Api <= 26 startScan()不支持PendingIntent-无法启动BroadcastReceiver。 startScan()仅使用回调启动一次。这可能是最好的解决方案android-beacon-library或使用 startScan()的自定义实现后台服务。
  2. 仅警告。 Android附近的通知将于2018年12月6日(google block)结束