Oreo, BLE scanner startScan with PendingIntent not working on Samsung device

做~自己de王妃 提交于 2019-12-21 03:01:40

问题


I am trying to scan for beacons using startScan(filters, settings, callbackIntent). I have an implementation that works fine for Sony Xperia XZ, and Nexus 5X. The only other device with Android O I have available is a Samsung Galaxy S8, and what works for the other devices produce nothing on the Samsung. (The bluetooth scan is really imbedded in a library module, but even when creating a dummy app the samsung fails, so I'll use that in this example). I have removed the filter and the settings used for startScan since the scan doesn't work without them anyway and these are optional.

MainActivity
- checks and asks for permissions (ACCESS_COARSE_LOCATION)
- simplified onStart

override fun onStart() {
    super.onStart()
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val startScan = bleScanner.startScan(null, null, getPendingIntent())
        Log.d("testApp", "Start scan! ${startScan == 0}")
    }
}

PendingIntent:

private fun getPendingIntent(): PendingIntent {
    return PendingIntent.getBroadcast(
            this, REQ_CODE,
            Intent(this.applicationContext, BleReceiver::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT)
}

Manifest

Permissions:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Receiver:

    <receiver android:name="com.testapp.samsungoscan.BleReceiver" >
        <intent-filter>
             <action android:name="BluetoothDevice.ACTION_FOUND" />
            <action android:name="BluetoothDevice.EXTRA_UUID" />
            <action android:name="BluetoothDevice.EXTRA_RSSI" />
        </intent-filter>
    </receiver>

Receiver implementation:

class BleReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.e("testApp", "On Receive!")
    }
}

So! Why is this not working for Samsung, while it works for Sony and Nexus? Note: If I change the receivers android:name to a relative path .BleReceiver instead of com.testapp.samsungoscan.BleReceiver, then the Nexus stops working, but Sony still works!

By work I mean all classes gets used and the logs are triggered. What is wrong?


回答1:


You have registered the broadcast receiver in the AndroidManifest.xml with an Intent Filter name

<action android:name="BluetoothDevice.ACTION_FOUND" />

First of all, you may provide there any String. Above suggest that you are using this constant, but in fact you are just using the String as is (BluetoothDevice.ACTION_FOUND). I would recommend changing it to some com.testapp.samsungoscan.ACTION_FOUND. The Extras are not needed and they suggest they are in fact extras, but they are just another action names with name "extra".

I recommend changing to:

<receiver android:name="com.testapp.samsungoscan.BleReceiver">
    <intent-filter>
         <action android:name="com.testapp.samsungoscan.ACTION_FOUND" />
    </intent-filter>
</receiver>

Secondly, you have to create the PendingIntent with this action name:

private fun getPendingIntent(): PendingIntent {
    return PendingIntent.getBroadcast(
            this, REQ_CODE,
            Intent(this.applicationContext, BleReceiver::class.java).setAction("com.testapp.samsungoscan.ACTION_FOUND"),
            PendingIntent.FLAG_UPDATE_CURRENT)
}

Creating an intent with providing Component name is required since Oreo to be able to get any broadcasts. I'm not sure, however, will it work after your app has been killed by the system.

Lastly, I recommend requesting FINE_LOCATION, as this: https://android-review.googlesource.com/c/platform/packages/apps/Bluetooth/+/848935 change may in the future require fine location permission to scan for Bluetooth devices.




回答2:


You need to pass an empty filters list to the startScan() call instead of null

List<ScanFilter> listOfFiters = new ArrayList<>();
ScanFilter.Builder builder = new ScanFilter.Builder();
ScanFilter filter = builder.build();
listOfFiters.add(filter);

bleScanner.startScan(listOfFilters, null, getPendingIntent())



回答3:


Ah, and in addition to passing empty filter to the startScan you will also need ACCESS_FINE_LOCATION permission on latest Android versions.



来源:https://stackoverflow.com/questions/50248178/oreo-ble-scanner-startscan-with-pendingintent-not-working-on-samsung-device

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!