Solution for BLE scan's SCAN_FAILED_APPLICATIO

2019-01-25 08:02发布

问题:

My Android app scans BLE devices, and from a certain point it start to fails with error code 2 (ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED). I'm using Nexus 9, 5.0.1 Lollipop.

This problem continued even after I relaunched the app, and when I restarted the Bluetooth service from Settings, I could finally get rid of the problem. But this problem is recurring, and I think I'm coding in a wrong way; BLE related APIs are new and there is few information.

Does anyone know a general solution for this error, preferably not requiring restart of the Bluetooth service? Even though this error code is documented in Android API reference, I don't know how to handle it properly.

回答1:

When you got the error

SCAN_FAILED_APPLICATION_REGISTRATION_FAILED

You should disable the BluetoothAdapter

BluetoothAdapter.getDefaultAdapter().disable();

Disabling BluetoothAdapter, the event STATE_TURNING_OFF is fired. Once this event is fired, try to reconnect to the BluetoothAdapter:

case BluetoothAdapter.STATE_OFF:
  Log.d(TAG, "bluetooth adapter turned off");
  handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        Log.d(TAG, "bluetooth adapter try to enable");
        BluetoothAdapter.getDefaultAdapter().enable();
    }}, 500);
  break;


回答2:

You should perform operations only success initialization of BT adapter. To be sure that it is ready create intent filter:

val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)

and broadcast receiver(you will perform action only if adapter is ready):

val broadcastReceiver = object: BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent?) {
                val action = intent?.action
                if (action != null && action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                    val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
                    when (state) {
                        BluetoothAdapter.STATE_ON -> {
                            if (bluetoothAdapter.isEnabled) {
                               //perform your task here
                            }
                        }
                        BluetoothAdapter.STATE_OFF -> {}
                    }
                }
            }
        }

then register receiver:

registerReceiver(broadcastReceiver, filter)

and relaunch adapter(this part can be replaces with check):

bluetoothAdapter.disable()
bluetoothAdapter.enable()

DONE!



回答3:

It turns out that Bluetooth LE requires the following Android application permissions in AndroidManifest.xml:

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

<!--BLE scanning is commonly used to determine a user's location with Bluetooth LE beacons. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- if your app targets API level 21 or higher. -->
<uses-feature android:name="android.hardware.location.gps" />

<!--app is available to BLE-capable devices only. -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

Besides on main activity:

// onResume()
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
        android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
} else {
    ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
            REQUEST_LOCATION_ENABLE_CODE);
}