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?
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.
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())
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