How to detect that the headset has been plugged in?

7

I've been noticing that every time I "plug in" the headset into my smarphone, a Deezer notification (music stream application) appears.

) already telling you to click and to open the application.

According to the documentation that talks about the ACTION_HEADSET_PLUG , they recommend use the AudioManager if the minimum version of the SDK is Lollipop .

Do I need to create a <receiver> to perform this procedure? How do I check the status of the headset or detect if it has been "plugged in"?

    
asked by anonymous 27.09.2017 / 16:14

2 answers

5

Yes, you need to create a BroadcastReceiver but it must be explicitly registered, via Context.registerReceiver() , and not just declared in AndroidManifest.xml .

Regarding ACTION_HEADSET_PLUG , what the documentation mentions is that if the minimum version of the SDK is Lollipop, you should use the AudioManager.ACTION_HEADSET_PLUG instead of Intent.ACTION_HEADSET_PLUG (1)

To know the status of the headset, in the onReceive() of BroadcastReceiver method, check the% key of Intent Extra%.

@Override
public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
        int state = intent.getIntExtra("state", -1);
        switch(state) {
            case(0):
                Log.d(TAG, "Headset unplugged");
                break;
            case(1):
                Log.d(TAG, "Headset plugged");
                break;
            default:
                Log.d(TAG, "Headset state invalid");
        }
    }
}
I do not understand why, since in both it is said that its value is state .

    
27.09.2017 / 16:24
1

Just for the sake of curiosity and to complement the ramaral's response, it is excellent.

You can use the Awareness API to detect when the headset is plugged in and at the same time know if it is currently current has a plugged headset.

To get the headset status snapshot (only by placing the important part):

Awareness.SnapshotApi.getHeadphoneState(mGoogleApiClient)
                .setResultCallback(new ResultCallback<HeadphoneStateResult>() {
                    @Override
                    public void onResult(@NonNull HeadphoneStateResult headphoneStateResult) {
                        if (!headphoneStateResult.getStatus().isSuccess()) {
                            Log.e(TAG, "Could not get headphone state.");
                            return;
                        }
                        HeadphoneState headphoneState = headphoneStateResult.getHeadphoneState();
                        if (headphoneState.getState() == HeadphoneState.PLUGGED_IN) {
                            Log.i(TAG, "Headphones are plugged in.\n");
                        } else {
                            Log.i(TAG, "Headphones are NOT plugged in.\n");
                        }
                    }
                });

This example is in the documentation itself: Get headphone state

And to be notified, using Fences API :

// Declare variables for pending intent and fence receiver.
private PendingIntent myPendingIntent;
private MyFenceReceiver myFenceReceiver;

// Initialize myPendingIntent and fence receiver in onCreate().
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    Intent intent = new Intent(FENCE_RECEIVER_ACTION);
    myPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
    MyFenceReceiver = new myFenceReceiver();
    registerReceiver(myFenceReceiver, new IntentFilter(FENCE_RECEIVER_ACTION));
    ...
}

// Create a fence.
AwarenessFence headphoneFence = HeadphoneFence.during(HeadphoneState.PLUGGED_IN);

// Register the fence to receive callbacks.
// The fence key uniquely identifies the fence.
Awareness.FenceApi.updateFences(
        mGoogleApiClient,
        new FenceUpdateRequest.Builder()
            .addFence("headphoneFenceKey", headphoneFence, myPendingIntent)
            .build())
        .setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status status) {
                if (status.isSuccess()) {
                    Log.i(TAG, "Fence was successfully registered.");
                } else {
                    Log.e(TAG, "Fence could not be registered: " + status);
                }
            }
        });

// Handle the callback on the Intent.
public class MyFenceReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        FenceState fenceState = FenceState.extract(intent);

        if (TextUtils.equals(fenceState.getFenceKey(), "headphoneFenceKey")) {
            switch(fenceState.getCurrentState()) {
                case FenceState.TRUE:
                    Log.i(TAG, "Headphones are plugged in.");
                    break;
                case FenceState.FALSE:
                    Log.i(TAG, "Headphones are NOT plugged in.");
                    break;
                case FenceState.UNKNOWN:
                    Log.i(TAG, "The headphone fence is in an unknown state.");
                    break;
            }
        }
    }
}

As I said, they are different ways of solving the same problem. But in fact Fences API requires a little more boilerplate. But you have the possibility to consult Snapshot in a simple way.

The big advantage in my opinion is the possibility to combine states.

  • I want to be notified when the user has the phone and also with the mobile phone, so I can suggest an X action.

  • I want to be notified when the user has the headset plugged in and is running, so I can suggest his racing playlist.

Doing this using only the framework's APIs is much more difficult.

    
30.09.2017 / 19:38