Skip to content Skip to sidebar Skip to footer

Register Broadcast Receiver Dynamically Does Not Work - Bluetoothdevice.action_found

Using Log class to track Runtime show that onReceive() methode does not called,why ? Register broadcast receiver dynamically private void discoverDevices () { Log.e('MOHAB','B

Solution 1:

Apart from the fact that starting with Android 6.0 you have to have the ACCESS_COARSE_LOCATION permission to receive ACTION_FOUND (as @siniux already mentioned), there's another related thing:

ACCESS_COARSE_LOCATION is among dangerous permissions that you have to explicitly request from user at run time (another security improvement that came in 6.0).

To diagnose, you can run adb logcat | grep BroadcastQueue, and see something like this:

W/BroadcastQueue: Permission Denial:receivingIntent { 
    act=android.bluetooth.device.action.FOUNDflg=0x10(hasextras) } 
    toProcessRecord{9007:com.examplepackage}(pid=9007,uid=10492)requiresandroid.permission.ACCESS_COARSE_LOCATIONduetosendercom.android.bluetooth(uid1002)

So, the correct procedure for BT device discovery on Marshmallow is as follows:

  1. Have ACCESS_COARSE_LOCATION permission requirement in manifest along with usual bluetooth permissions:

    <uses-permissionandroid:name="android.permission.BLUETOOTH" /><uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" /><uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION" />
  2. Ensure you have run-time permission for ACCESS_COARSE_LOCATION

    protectedvoidcheckLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
    
            ActivityCompat.requestPermissions(this,
                    newString[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    REQUEST_COARSE_LOCATION);
        }
    }
    
    @OverridepublicvoidonRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
        switch (requestCode) {
        caseREQUEST_COARSE_LOCATION: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                proceedDiscovery(); // --->
            } else {
                //TODO re-request
            }
            break;
        }
    }
    

    }

  3. Register a broadcast receiver for ACTION_FOUND and call BluetoothAdapter.startDiscovery()

    protectedvoidproceedDiscovery() {
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
        registerReceiver(mReceiver, filter);
    
        mBluetoothAdapter.startDiscovery();
    }
    

Funny thing about ACTION_NAME_CHANGED. Although 6.0 won't deliver you ACTION_FOUND without the permission for coarse location, you'll still get ACTION_NAME_CHANGED events, which are usually teamed up with ACTION_FOUND when devices are discovered. I.e. you get both events, so without the permission, you can still handle ACTION_NAME_CHANGED for pretty much the same behavior. (Gurus, correct me if I'm wrong)

Solution 2:

I was having a similar problem with a Broadcast Receiver. Then I found this: https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id

Basically, on 6.0 you must use the location permission to scan for Bluetooth devices.

Solution 3:

What you missed is that you need to start a device discovery

First, get the bluetooth adapter

BluetoothAdapteradapter= BluetoothAdapter.getDefaultAdapter();

After that, you start the discovery by calling

mBtAdapter.startDiscovery();

You should read the details here as well, e.g. about cancelDiscovery()http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29

P.S. Also, it is suggested to use context.getSystemService(Context.BLUETOOTH_SERVICE) to get the BluetoothAdapter on API 18+, according to official doc.

To get a BluetoothAdapter representing the local Bluetooth adapter, when running on JELLY_BEAN_MR1 and below, call the static getDefaultAdapter() method; when running on JELLY_BEAN_MR2 and higher, retrieve it through getSystemService(Class) with BLUETOOTH_SERVICE.

Edit: Be reminded that you need BLUETOOTH_ADMIN permission to startDiscovery()

Solution 4:

As replied by experts, you may please check the following points to get ACTION_FOUND work in Android 6 and above, 1. In addition to setting permissions of BLUETOOTH and BLUETOOTH_ADMIN, try

<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION" />

Sometimes these two may not be needed, but it worked for me. Also you have to seek user permissions dynamically using the codes

int MY_PERMISSIONS_REQUEST = 200;
int permissions=ContextCompat.checkSelfPermission (this,Manifest.permission.ACCESS_FINE_LOCATION);
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                MY_PERMISSIONS_REQUEST);

Now write your codes for performing the required operation. I have added one startDiscovery() method just after this. Surely, this will work for you... Happy coding...

Solution 5:

i dont know if your code is correct in getting bluetooth device. here is what i feel about your code is. intialising and registering BroadcastReceiver inside a function is a bad idea. you should do it outside onCreate() method. here's the thing you need to do in your code

as about registering Reciver that has to be done in onCreate() like this

registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));

following with initializing or reciever

privatefinalBroadcastReceivermReceiver=newBroadcastReceiver() {
        @OverridepublicvoidonReceive(Context context, Intent intent) {
            Log.e("MOHAB","ON RECEIVE");
            Stringaction= intent.getAction();
            // When discovery finds a deviceif (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the IntentBluetoothDevicedevice= intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // Add the name and address to an array adapter to show in a ListViewBluetoothb=newBluetooth(device.getName(),device.getAddress());
                list.add(b);
            }
        }
    };

unregister reciver in onPause() do not forget that

and in your discoverDevices() just return the list of devices added by reciver for every call of that fumction;

Post a Comment for "Register Broadcast Receiver Dynamically Does Not Work - Bluetoothdevice.action_found"