Edit May 8, 2016
I found the reason for my troubles receiving media button events in my app. See the answer below. I editid the title of this question to make finding the issue easier. The original title was "What can possibly block media buttons on Android Lollipop".
Original question, April 2015:
Scratching my head and staring at all the code for 2 days to no avail... My Android app is supposed to react to media buttons (e.g. from a headset, test it with a Bluetooth headset), like play/pause, next, rewind. Works fine on KitKat and below. I swear it even worked on Lollipop as well up until a few days ago. Now nothing, no trace that it hears media button presses. Would anyone have a quick suggestion where to look for the trouble? Tested with two Lollipop phones, same Bluetooth headset, and the same headset works fine for lower versions of Android. Also the same headset works fine, media buttons presses heard in other apps. What possibly could I break???
I now tested both old and new ways of listening to media buttons. In AndroidManifest.xml:
<receiver android:name=".MediaButtonIntentReceiver" android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
The fact that it says enabled="false" is OK - I enable and disable the receiver as needed, and the MediaButtonIntentReceiver.java gets the events fine on KitKat and lower, complete silence on Lollipop.
I next switched to the latest appcompat (v22.1) and tried using MediaSessionCompat object and related code as follows. This worked great in a small test app, just one activity that I wrote - got my Logcat messages confirming that it hears media keys pressed on Lollipop. But when inserted into my app, again does not work on Lollipop. What the heck???
private MediaSessionCompat _mediaSession;
final String MEDIA_SESSION_TAG = "some_tag";
void initMediaSessions(Context context) {
// Start a new MediaSession
if (context == null)
return;
Lt.d("initMediaSession()...");
ComponentName eventReceiver = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName());
PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(
context,
0,
new Intent(Intent.ACTION_MEDIA_BUTTON),
PendingIntent.FLAG_UPDATE_CURRENT
);
// Parameters for new MediaSessionCompat():
// context The context.
// tag A short name for debugging purposes.
// mediaButtonEventReceiver The component name for your receiver. This must be non-null to support platform
// versions earlier than LOLLIPOP. May not be null below Lollipop.
// mbrIntent The PendingIntent for your receiver component that handles media button events. This is optional
// and will be used on JELLY_BEAN_MR2 and later instead of the component name.
_mediaSession = new MediaSessionCompat(context, MEDIA_SESSION_TAG, eventReceiver, buttonReceiverIntent);
_mediaSession.setCallback(new MediaSessionCallback());
_mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
_mediaSession.setActive(true);
PlaybackStateCompat state = new PlaybackStateCompat.Builder()
.setActions(
PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE |
PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
.setState(PlaybackStateCompat.STATE_STOPPED, 0, 1, SystemClock.elapsedRealtime())
.build();
_mediaSession.setPlaybackState(state);
}
final class MediaSessionCallback extends MediaSessionCompat.Callback {
@Override
public void onPlay() {
Lt.d("play");
}
@Override
public void onPause() {
Lt.d("pause");
}
@Override
public void onStop() {
Lt.d("stop.");
}
@Override
public void onSkipToNext() {
Lt.d("skipToNext");
}
@Override
public void onSkipToPrevious() {
Lt.d("skipToPrevious");
}
@Override
public boolean onMediaButtonEvent(final Intent mediaButtonIntent) {
Lt.d("GOT MediaButton EVENT");
KeyEvent keyEvent = (KeyEvent) mediaButtonIntent.getExtras().get(Intent.EXTRA_KEY_EVENT);
// ...do something with keyEvent, super... does nothing.
return super.onMediaButtonEvent(mediaButtonIntent);
}
}
May 8, 2016: Solved for sure I finally found the reason why media buttons did not work with my app, when the main screen was on. I later noticed that they worked if any other app was on active, or screen turned off etc. - but not when my main activity was up. Turns out that in Android 5 at least, the WebView control I use on my main screen blocks the media buttons, if it has focus. Calling:
webView.setFocusable(false);
or
webView.setFocusableInTouchMode(false);
or setting the same attribute in the layout, solves the problem. With Android 6 the focusable setting of WebView did not matter for receiving media button events.
Apr. 24, 2015: Solved? - not quite... From the comment to this post: Handling media buttons in Android 5.0 Lollipop by @mangini:
To receive media button events while your activity is in foreground, call setMediaController() on your activity with a MediaController instance connected to your active MediaSession. – mangini Jan 23 at 18:35
I was testing all the time with screen on and my activity opened on it, as it always worked that way under older versions of Android too... As soon as I pressed the home button, or turned off the screen, my old MediaButtonIntentReceiver started working normally.
Update Media button events come to my app only if my lock screen manager, using the depreciated RemoteControlClient is enabled, and of course my activity is not in foreground. If I disable the lock screen manager (which is an option in my app) and delete RemoteControlClient, again, I can't get any media events.
This issue under Lollipop is a complete mess. Or at least a complete mess about it exists in my mind right now. Wish someone posted a clear code sample for handling media buttons, that would work under older versions of Android, and Lollipop...
Greg
Pls override the function return false.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return false;
}
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