Here's my effort to make a working code to handle a headset button event the best way. I read the Android developer guide, but it is obviously wrong because they ask to start listening registering a class name.
am.registerMediaButtonEventReceiver(RemoteControlReceiver); // Wrong
So I check out other examples to correct the code. For example many secret suggestions have been published in this question, I also tried other code such as this, and another solution with MediaSession, and cleaning the unneeded I wrote this code:
I implemented the class RemoteControlReceiver. Apparently there is no need for a static inner class, in fact, see this comment:
public class RemoteControlReceiver extends BroadcastReceiver {
public RemoteControlReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "EVENT!!", Toast.LENGTH_SHORT).show();
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
Toast.makeText(context, "EVENT!!", Toast.LENGTH_SHORT).show();
}
}
}
}
Then I registered the intent inside the MainActivity onCreate(){...
AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
ComponentName mReceiverComponent = new ComponentName(this, RemoteControlReceiver.class);
am.registerMediaButtonEventReceiver(mReceiverComponent);
The registerMediaButtonEventReceiver is deprecated by the way...
Inside the manifest I recorder the filter, after the activity tag:
<activity>
...
</activity>
<receiver android:name=".RemoteControlReceiver" android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Note: with a static inner class would be, e.g., ".MainActivity$RemoteControlReceiver".
I am working on
compileSdkVersion 24
buildToolsVersion "24.0.0"
...
minSdkVersion 21
targetSdkVersion 24
Here my questions:
API 21 changed the entire media app APIs, now centering entirely around MediaSession. Instead of registering a BroadcastReceiver
(as was needed prior to API 18) or a PendingIntent
(via registerMediaButtonEventReceiver(PendingIntent)), you can receive callbacks directly in the MediaSession.Callback.
You can set up a MediaSession
via the following code:
MediaSession.Callback callback = new MediaSession.Callback() {
@Override
public void onPlay() {
// Handle the play button
}
};
MediaSession mediaSession = new MediaSession(context,
TAG); // Debugging tag, any string
mediaSession.setFlags(
MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
mediaSession.setCallback(callback);
// Set up what actions you support and the state of your player
mediaSession.setState(
new PlaybackState.Builder()
.setActions(PlaybackState.ACTION_PLAY |
PlaybackState.ACTION_PAUSE |
PlaybackState.ACTION_PLAY_PAUSE);
.setState(PlaybackState.STATE_PLAYING,
0, // playback position in milliseconds
1.0); // playback speed
// Call this when you start playback after receiving audio focus
mediaSession.setActive(true);
If you only want to handle media buttons while your activity is visible, you can just have your MediaSession
handled by the Activity itself (this would allow your Callback
to just be a variable in your Activity).
The Best practices in media playback talk from I/O 2016 goes through all of the details and other APIs required to build a great media app, although note that it uses MediaSessionCompat and the other Support Library classes as detailed in the Media playback and the Support Library blog post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With