问题
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