Detect headphones Android

本小妞迷上赌 提交于 2021-02-04 16:39:25

问题


I program in recent years to Android and I wonder something:

How to detect the presence of headphones?
There is a method: isWiredHeadsetOn() but it doesn't work.

I've tried that but it doesn't work:

AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
Log.i("am.isWiredHeadsetOn()", am.isWiredHeadsetOn() + "");

if (am.isWiredHeadsetOn()) {
   //code
}

Thank you (and sorry if I made spelling mistakes, I am French)


回答1:


@Phil answer at https://stackoverflow.com/a/19102661/4758255 is a good implementation to detect the headphone.

Here I'm quoting from his answer. Please upvoted his answer not this!

Upvote the answer: https://stackoverflow.com/a/19102661/4758255


I've had an app in the store for three years that monitors both the wired headset and bluetooth state and nobody has ever complained about battery drain. But that is because I am successfully using a single service and broadcast receiver for detecting events from both. Here's the two key classes:

public class HeadsetStateBroadcastReceiver extends BroadcastReceiver {

    public static final String[] HEADPHONE_ACTIONS = {
        Intent.ACTION_HEADSET_PLUG,
        "android.bluetooth.headset.action.STATE_CHANGED",
        "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"
    };

    @Override
    public void onReceive(final Context context, final Intent intent) {

        boolean broadcast = false;

        // Wired headset monitoring
        if (intent.getAction().equals(HEADPHONE_ACTIONS[0]) {
            final int state = intent.getIntExtra("state", 0);
            AudioPreferences.setWiredHeadphoneState(context, state > 0);
            broadcast = true;
        }

        // Bluetooth monitoring
        // Works up to and including Honeycomb
        if (intent.getAction().equals(HEADPHONE_ACTIONS[1])) {
            int state = intent.getIntExtra("android.bluetooth.headset.extra.STATE", 0);
            AudioPreferences.setBluetoothHeadsetState(context, state == 2);
            broadcast = true;
        }

        // Works for Ice Cream Sandwich
        if (intent.getAction().equals(HEADPHONE_ACTIONS[2])) {
            int state = intent.getIntExtra("android.bluetooth.profile.extra.STATE", 0);
            AudioPreferences.setBluetoothHeadsetState(context, state == 2);
            broadcast = true;
        }

        // Used to inform interested activities that the headset state has changed
        if (broadcast) {
            LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("headsetStateChange"));
        }

    }

}

Here is the service I use to register the broadcast receiver:

public class HeadsetMonitoringService extends Service {

    HeadsetStateBroadcastReceiver headsetStateReceiver;

    @Override
    public void onCreate() {

        headsetStateReceiver = new HeadsetStateBroadcastReceiver();
        final IntentFilter filter = new IntentFilter();
        for (String action: HeadsetStateBroadcastReceiver.HEADPHONE_ACTIONS) {
            filter.addAction(action);
        }

        registerReceiver(headsetStateReceiver, filter);

    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(headsetStateReceiver);
    }

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

}

And here is my manifest entry:

    <service
        android:name=".services.HeadsetMonitoringService"
        android:enabled="true"
        android:exported="false" >
        <intent-filter>
            <action android:name="initialiseHeadsetService" />
        </intent-filter>
    </service>

How it works is as follows:

I use an on boot broadcast receiver to send a start service message to the HeadsetMonitoringService (you don't have to do it this way, you could just do this when your application starts instead). The HeadsetMonitoringService in turn registers an instance of a broadcast listener that listens to all the headset events I am interested in - they are held in the HEADPHONE_ACTIONS array. Because the service is sticky it hangs around - and therefore so does the broadcast listener. But because both the service and the broadcast listener are event driven they do not consume any power until a headset state change occurs. Additionally, because the service is sticky, it will be restarted by the OS if it dies unexpectedly.
Whenever I receive a headset state change event I also fire a local broadcast so that interested activities can check the new state and take action if required.

For completeness, I should point out that I use another class (not shown here), AudioPreferences, to store as preferences both the Bluetooth and wired headset state, which can then be accessed whenever I need to know the headset state.

Your application will need the android.permission.BLUETOOTH permission if you are interested in the state of a Bluetooth headset. If not, just take out the Bluetooth related actions from the HEADPHONE_ACTIONS array and delete the associated if blocks from the onReceive method.




回答2:


If you are OK with Marshmallow and up the AudioDeviceCallback might be what you are looking for. It works with an AudioManager and tells you when anything connects and disconnects.




回答3:


AudioManager.isWiredHeadsetOn() appeared to be the right thing to do. According to the Android developer doc :

Checks whether a wired headset is connected or not.

This is not a valid indication that audio playback is actually over the wired headset as audio routing depends on other conditions.

Returns
true if a wired headset is connected. false if otherwise

But :

  • you have to add the associated permission to your manifest (MODIFY_AUDIO_SETTINGS)
  • according to this post, it doesn't work well with Bluetooth headset.


来源:https://stackoverflow.com/questions/29333340/detect-headphones-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!