34

How can I determine whether a headset is plugged into an Android device or not?

gonzobrains
  • 7,856
  • 14
  • 81
  • 132
coderslay
  • 13,960
  • 31
  • 73
  • 121

7 Answers7

50

You can use the broadcast receiver.

So, You might write this code in "AndroidManifest.xml"

<receiver android:name="com.juno.brheadset.HeadsetStateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.HEADSET_PLUG"/>
    </intent-filter>
</receiver>-->

But, This doesn't work. When OS send this "HEADSET_PLUG" intent, OS set the flag "Intent.FLAG_RECEIVER_REGISTERED_ONLY" So, You should write the code like below in Activity or Service class instead of "AndroidManifest" things.

public class BRHeadsetActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    HeadsetStateReceiver receiver = new HeadsetStateReceiver();
    registerReceiver( receiver, receiverFilter );


}

I hope this article help you. Bye!

This is the part of "HeadsetObserver.java", Android SDK Source.

private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
    if ((headsetState & headset) != (prevHeadsetState & headset)) {
        //  Pack up the values and broadcast them to everyone
        Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);

        **intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);**

        int state = 0;
        int microphone = 0;

        if ((headset & HEADSETS_WITH_MIC) != 0) {
            microphone = 1;
        }
        if ((headsetState & headset) != 0) {
            state = 1;
        }
        intent.putExtra("state", state);
        intent.putExtra("name", headsetName);
        intent.putExtra("microphone", microphone);

        if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
        // TODO: Should we require a permission?
        ActivityManagerNative.broadcastStickyIntent(intent, null);
    }
}
cmcromance
  • 2,289
  • 1
  • 25
  • 26
  • @Sumit So sorry. I saw your replay now. What about my code can I explain for you? :) – cmcromance Oct 08 '12 at 00:43
  • @Sumit Ok. I think you don't understand this. If you add "FLAG_RECEIVER_REGISTERED_ONLY" to intent for broadcasting, I can receive your broadcasting when only I do "registerReceiver(...)" on code not on 'AndroidManifest.xml'. – cmcromance Oct 08 '12 at 00:57
  • 3
    What is "HeadsetStateReceiver" is that an SDK class or a custom class? – shim Oct 19 '12 at 05:10
  • 3
    @shim it's a custom class and it extends BroadcastReceiver and have a method onReceive – AndrewS Jan 28 '14 at 13:19
  • 1
    Curious, why do you have to say bye? – Neon Warge Dec 03 '19 at 09:25
32

When you say "headset", do you mean "wired headset"? If so, there's an intent to detect whether or not one is being plugged or unplugged: ACTION_HEADSET_PLUG.

To check the status, you can use AudioManager.isWiredHeadsetOn(), although that may return false if there is also a bluetooth headset, and audio is routed to that instead.

Chankey Pathak
  • 21,187
  • 12
  • 85
  • 133
EboMike
  • 76,846
  • 14
  • 164
  • 167
  • 5
    Hello Mike, What should i do if some one use a Blutooth headset? – coderslay Jun 06 '11 at 08:00
  • AudioManager.isWiredHeadsetOn() always seems to return false (tested on several Gingerbread devices), whether or not a headset is plugged in. If you can provide a working code example, that would be great. – Chad Schultz May 01 '12 at 18:39
  • 5
    @ChadSchultz You need to add permission MODIFY_AUDIO_SETTINGS in manifest..then only it will return correct status. – Ayush Goyal Feb 13 '14 at 13:56
  • 2
    is deprecated function API21 – Codelaby May 15 '17 at 13:21
  • 1
    For Bluetooth headsets see jobbert's answer here: https://stackoverflow.com/questions/4715865/how-to-programmatically-tell-if-a-bluetooth-device-is-connected-android-2-2 – juanlugm Aug 11 '17 at 22:03
17

AudioManager.isWiredHeadsetOn() always return false because it requires user-permission MODIFY_AUDIO_SETTINGS.

I spent several days while found answer. There are no info about this in official documentation. And this bug already registered in BugTracker.

Prasad Jadhav
  • 5,090
  • 16
  • 62
  • 80
user1777060
  • 263
  • 4
  • 8
4

This should help you : http://developer.android.com/reference/android/content/Intent.html#ACTION_HEADSET_PLUG

Ravi Vyas
  • 12,212
  • 6
  • 31
  • 47
2

You can create this kind of receiver class (Kotlin with Flow) in your project:

class HeadsetPlugReceiver : BroadcastReceiver() {

    private val _isPlugged = MutableStateFlow<Boolean>(false)
    val isPlugged: StateFlow<Boolean> = _isPlugged.asStateFlow()

    override fun onReceive(context: Context, intent: Intent) {
        context.appComponent.inject(this)
        val action = intent.action
        Log.i(TAG, "onReceive: $action")
        when (action) {
            Intent.ACTION_HEADSET_PLUG -> sendEvent(intent)
            else -> checkStateOff(intent)
        }
    }

    private fun checkStateOff(intent: Intent) {
       Log.i(TAG, "onReceive: the local Bluetooth adapter is off")
    }

    private fun sendEvent(intent: Intent) {
        val isPlugged = intent.getIntExtra(HEADSET_STATE, 0) == 1
        Log.i(TAG, "sendEvent: $isPlugged")
        _isPlugged.value = isPlugged
    }

    private companion object {

       private const val TAG = "HeadsetPlugReceiver"
       // Headset constant
       private const val HEADSET_STATE = "state"
    }
}

then register this receiver in some class with context:

val headsetReceiver = HeadsetPlugReceiver()
val headsetFilter = IntentFilter(Intent.ACTION_HEADSET_PLUG)
    context.registerReceiver(headsetReceiver, headsetFilter)

then collect isPlugged and you get the state of your wire headset connecting state

PS: don't forget to unregister your receiver when it no needs context.unregisterReceiver(headsetReceiver)

Aliaksei
  • 3,542
  • 1
  • 16
  • 21
1

First , create receiver in your manifest:

    <receiver android:name="com.yourapplication.BroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.HEADSET_PLUG"/>
        </intent-filter>
    </receiver>

don't forget to change com.yourapplication according to your project name

Create two variables in the head of your activity :

private  BroadcastReceiver mReceiver  ;
boolean Microphone_Plugged_in = false;

Define your receiver inside onCreate of your activity :

        mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            int iii=2;
            if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
                iii=intent.getIntExtra("state", -1);
                if(Integer.valueOf(iii)==0){
                    Microphone_Plugged_in = false;
                    Toast.makeText(getApplicationContext(),"microphone not plugged in",Toast.LENGTH_LONG).show();
                }if(Integer.valueOf(iii)==1){
                    Microphone_Plugged_in = true;
                    Toast.makeText(getApplicationContext(),"microphone plugged in",Toast.LENGTH_LONG).show();
                }
            }
        }};
        IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
        registerReceiver( mReceiver, receiverFilter );

add onResume and onStope :

@Override
  protected void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    getApplicationContext().registerReceiver(mReceiver, filter);
}

@Override
protected void onStop() {
    super.onStop();
    getApplicationContext().unregisterReceiver(mReceiver);
}
yacine
  • 147
  • 1
  • 6
0

To add to the other answers, from Android documentation:

Warning: Limit how many broadcast receivers you set in your app. Having too many broadcast receivers can affect your app's performance and the battery life of users' devices. For more information about APIs you can use instead of the BroadcastReceiver class for scheduling background work, see Background Optimizations.

https://developer.android.com/guide/topics/manifest/receiver-element

Which means that you should create a small number of broadcast receivers as possible, to prevent memory issues with your app.

I will suggest using a singleton class with this receiver. In Kotlin:

class HeadsetReceiver private constructor(): BroadcastReceiver() {

    // instances
    var callback: HeadsetReceiverCallback? = null

    //region singleton
    private object HOLDER {
        val INSTANCE = HeadsetReceiver()
    }

    companion object {
        val instance: HeadsetReceiver by lazy { HOLDER.INSTANCE }
    }
    //endregion

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_HEADSET_PLUG) {
            if(intent.getIntExtra("state", -1) == 0) {
                callback?.onHeadsetDisconnected()
            } else {
                callback?.onHeadsetConnected()
            }
        }
    }

    fun register(context: Context) {
        val receiverFilter = IntentFilter(Intent.ACTION_HEADSET_PLUG)
        context.registerReceiver(this, receiverFilter)
    }

    fun unregister(context: Context) {
        context.unregisterReceiver(this)
        callback = null
    }

    interface HeadsetReceiverCallback {
        fun onHeadsetConnected()
        fun onHeadsetDisconnected()
    }
}

Register:

HeadsetReceiver.instance.register(context)
        HeadsetReceiver.instance.callback = object : HeadsetReceiver.HeadsetReceiverCallback {
            override fun onHeadsetConnected() {
                println("connected!")
            }

            override fun onHeadsetDisconnected() {
                println("disonnected!")
            }
        }

Unregister:

HeadsetReceiver.instance.unregister(context)
Oz Shabat
  • 1,434
  • 17
  • 16