Skip to content

Instantly share code, notes, and snippets.

@gotev
Created April 7, 2016 10:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gotev/f4799cc340c07c33d8071bef87e96563 to your computer and use it in GitHub Desktop.
Save gotev/f4799cc340c07c33d8071bef87e96563 to your computer and use it in GitHub Desktop.
Android Media Button Detect
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.view.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
/**
* Broadcast receiver which receives headset action button events.
* For this to work, you need to add the following in your manifest,
* by replacing .receivers.HeadsetActionButtonReceiver with the relative
* class path of where you will put this file:
* <receiver android:name=".receivers.HeadsetActionButtonReceiver" >
* <intent-filter android:priority="10000" >
* <action android:name="android.intent.action.MEDIA_BUTTON" />
* </intent-filter>
* </receiver>
*
* Then, in the activity in which you are going to use it:
* - implement HeadsetActionButtonReceiver.Delegate methods
* - in the onResume add:
* HeadsetActionButtonReceiver.delegate = this;
* HeadsetActionButtonReceiver.register(this);
* - in the onPause add:
* HeadsetActionButtonReceiver.unregister(this);
* And that's all.
* @author gotev Aleksandar Gotev
*/
public class HeadsetActionButtonReceiver extends BroadcastReceiver {
public static Delegate delegate;
private static AudioManager mAudioManager;
private static ComponentName mRemoteControlResponder;
private static int doublePressSpeed = 300; // double keypressed in ms
private static Timer doublePressTimer;
private static int counter;
public interface Delegate {
void onMediaButtonSingleClick();
void onMediaButtonDoubleClick();
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || delegate == null || !Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction()))
return;
KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
if (keyEvent == null || keyEvent.getAction() != KeyEvent.ACTION_DOWN) return;
counter++;
if (doublePressTimer != null) {
doublePressTimer.cancel();
}
doublePressTimer = new Timer();
doublePressTimer.schedule(new TimerTask() {
@Override
public void run() {
if (counter == 1) {
delegate.onMediaButtonSingleClick();
} else {
delegate.onMediaButtonDoubleClick();
}
counter = 0;
}
}, doublePressSpeed);
}
public static void register(final Context context) {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mRemoteControlResponder = new ComponentName(context, HeadsetActionButtonReceiver.class);
mAudioManager.registerMediaButtonEventReceiver(mRemoteControlResponder);
}
public static void unregister(final Context context) {
mAudioManager.unregisterMediaButtonEventReceiver(mRemoteControlResponder);
if (doublePressTimer != null) {
doublePressTimer.cancel();
doublePressTimer = null;
}
}
}
@McCannDahl
Copy link

Can you show me how to implement HeadsetActionButtonReceiver.Delegate methods? Thanks

@arivatibm
Copy link

I've implemented it but I do not see that it works - it does not give any feedback when pressing the play/pause button on my bluetooth headset
do I need to enable any permissions?

@Abdelalim-dev
Copy link

@arivatibm did you add the following to your manifest inside the application tag?

<receiver android:name="net.work.box.controller.receivers.RemoteControlReceiver" >
    <intent-filter android:priority="1000000000000000" >
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

@tavisaman
Copy link

tavisaman commented May 30, 2021

Thanx a lot Aleksandar!
It works fine with a subtle change: I had to replace doublePressTimer to a Handler/Runnable combo.

@gotev
Copy link
Author

gotev commented May 30, 2021

@tavisaman you're welcome! By looking at the code now, I wouldn't write it like that anymore. Delegate methods are getting called inside TimerTask thread and the whole broadcast receiver could be made lifecycle-aware by using LifecycleObserver.

Google's recommended way at the time of this comment is:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment