7

Working on a VOIP application, in silent mode an alert tone or ringtone should play on bluetooth headset only. Able to play it on headphone if connected but if the headset is not connected the tone plays on the speaker though the mobile is in silent mode.

Someone please explain if there is a way to detect that a bluetooth headset is connected.

Jitu
  • 349
  • 1
  • 3
  • 16

3 Answers3

6

For a simple check, use the following. Remember to add BLUETOOTH permission to your manifest (Non Dangerous permission)

val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
return (bluetoothAdapter != null && BluetoothProfile.STATE_CONNECTED == bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET))
Codelicious
  • 604
  • 10
  • 12
4

Here is my code:

/** */
class BluetoothStateMonitor(private val appContext: Context): BroadcastReceiver(), MonitorInterface {
    var isHeadsetConnected = false
    @Synchronized
    get
    @Synchronized
    private set

    /** Start monitoring */
    override fun start() {
        val bluetoothManager = appContext.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
        bluetoothManager.adapter.getProfileProxy(appContext, object:BluetoothProfile.ServiceListener {
            /** */
            override fun onServiceDisconnected(profile: Int) {
                isHeadsetConnected = false
            }

            /** */
            override fun onServiceConnected(profile: Int, proxy: BluetoothProfile?) {
                isHeadsetConnected = proxy!!.connectedDevices.size > 0
            }

        }, BluetoothProfile.HEADSET)

        appContext.registerReceiver(this, IntentFilter(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED))
    }

    /** Stop monitoring */
    override fun stop() {
        appContext.unregisterReceiver(this)
    }

    /** For broadcast receiver */
    override fun onReceive(context: Context?, intent: Intent?) {
        val connectionState = intent!!.extras!!.getInt(BluetoothAdapter.EXTRA_CONNECTION_STATE)
        when(connectionState) {
            BluetoothAdapter.STATE_CONNECTED -> isHeadsetConnected = true
            BluetoothAdapter.STATE_DISCONNECTED -> isHeadsetConnected = false
            else -> {}
        }
    }
}

Let me explain one moment. You should use ProfileProxy and BroadcastReceiver both. ProfileProxy lets you detect the case when the headset was connected before the app was run. BroadcastReceiver, in turn, lets you detect when the headset is connected/disconnected while your app is being executed.

Alex Shevelev
  • 681
  • 7
  • 14
2

Thanks for the answer @cristallo

This is the way I handled it.

Connect to proxy

bluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET);

Created a listener

private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener()
{

    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy)
    {
        if (profile == BluetoothProfile.HEADSET)
        {
            mBluetoothHeadset = (BluetoothHeadset) proxy;
            if(mBluetoothHeadset.getConnectedDevices().size()>0) {
                IS_BLUETOOTH_CONNECTED = true;
                Logs.d(TAG,"Bluetooth device is connected");
            }
            
        }
    }

    @Override
    public void onServiceDisconnected(int profile)
    {
         if (profile == BluetoothProfile.HEADSET)
         {
             mBluetoothHeadset = null;
             IS_BLUETOOTH_CONNECTED = false;
             Logs.d(TAG,"Bluetooth device is disconnected");
         }
    }
};

Referred from Detect programatically if headphone or bluetooth headset attached with android phone

The blogger Vipul had created a BluetoothHeadsetManager class, which handles getting the headset profile, handling the listener, checking if the bluetooth is enabled or not.I haven't utilized the Broadcast Receiver.

switch (audioMgr.getRingerMode()) {
        case AudioManager.RINGER_MODE_SILENT:
            if(BluetoothHeadsetManager.IS_BLUETOOTH_CONNECTED) {
                //play notification
            }
            break;
        case AudioManager.RINGER_MODE_VIBRATE:
            if(BluetoothHeadsetManager.IS_BLUETOOTH_CONNECTED) {
                //play notification
            }
            break;
        case AudioManager.RINGER_MODE_NORMAL:
            //play ringtone
            break;
        default:
            break;
        }}
fdermishin
  • 3,519
  • 3
  • 24
  • 45
Jitu
  • 349
  • 1
  • 3
  • 16
  • Link for Detect programatically if headphone or bluetooth headset attached with android phone is dead. – MoDu May 20 '20 at 16:13
  • can u provide other link? – famfamfam May 10 '21 at 19:13
  • 1
    The ServiceListener approach is correct. If anyone is curious, I answered a similar question with using a ServiceListener but also used a CallbackFlow to make it a bit easier to consume: https://stackoverflow.com/a/71259149/597587 – notmystyle Feb 24 '22 at 23:04