Search code examples
androidbluetoothbroadcastreceiver

Trying to receive bluetooth connection broadcasts in an activity - works in Android version 10, not working in Android version 14


I wrote an MP3 player for my phone. I wanted it to automatically start playing when certain bluetooth devices connect - like in my car, for instance. And stop playing when they disconnect. It works on my old Samsung Galaxy S9 (Android ver. 10), but not in my new Samsung Galaxy S24 (Android ver. 14). I assume something changed in the operating system between version 10 and version 14. I can't find anything in the android documents about this.

The manifest looks like this:

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH" />
...
<application
...
        tools:targetApi="31">
...
<activity
            android:name=".MainActivity"
            android:exported="true"

In MainActivity, it asks for bluetooth permission and gets it:

ActivityCompat.requestPermissions(getMainActivity(),
                                        new String[]{Manifest.permission.BLUETOOTH},
                                        MY_BLUETOOTH_PERMISSION);

The code in MainActivity looks like this:

mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT,BLUETOOTH_PERMISSION);

                    Toast.makeText(mainActivity, "Bluetooth device " + device.getName(), Toast.LENGTH_LONG).show();
                    addBluetoothDevice(device);
                } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                    bluetoothConnected = addBluetoothDevice(device);
                    if (bluetoothConnected != null && bluetoothConnected.isPlayOnConnect()) {
                        mediaService.resume();
                    }
                    Toast.makeText(mainActivity, "Bluetooth device connected " + device.getName(), Toast.LENGTH_LONG).show();
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    addBluetoothDevice(device);
                    Toast.makeText(mainActivity, "Bluetooth device discovery finished  " + device.getName(), Toast.LENGTH_LONG).show();
                } else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
                    addBluetoothDevice(device);
                    Toast.makeText(mainActivity, "Bluetooth device disconnect requested  " + device.getName(), Toast.LENGTH_LONG).show();
                } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                    bluetoothDisconnected = addBluetoothDevice(device);
                    if (bluetoothDisconnected != null && bluetoothDisconnected.isPauseOnDisconnect()) {
                        mediaService.pause();
                    }
                    Toast.makeText(mainActivity, "Bluetooth device disconnected  " + device.getName(), Toast.LENGTH_LONG).show();
                } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                    final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
                    switch (state) {
                        case BluetoothAdapter.STATE_OFF:
                            System.out.println("STATE_OFF");
                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:

                            break;
                        case BluetoothAdapter.STATE_ON:

                            break;
                        case BluetoothAdapter.STATE_TURNING_ON:

                            break;
                    }
                }
            }
        };
IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);type here

int receiverFlags = 0;
        this.registerReceiver(mReceiver, filter, receiverFlags);

I tried also listening for ACTION_STATE_CHANGED (see above code), although I don't need that. I do receive broadcasts for ACTION_STATE_CHANGED on the S24 when I turn bluetooth on and off, however. What I need are ACTION_ACL_CONNECTED and ACTION_ACL_DISCONNECTED, which I don't get when the S24 phone connects to a bluetooth speaker. Again, it does work on my S9 phone. Clearly something changed between Android version 10 and 14. Anyone know what it is?


Solution

  • You need to request the BLUETOOTH_CONNECT permission, both in the manifest and at runtime, in order to receive those broadcasts, per the documentation.

    Clearly something changed between Android version 10 and 14.

    The permission requirement was added in Android 11 for apps targeting Android 11 or higher.