Capture media button on Android >=4.0 (works on 2.3)

20,229

Solution 1

Make sure that you have an activity in your app, and that the user runs this activity before attempting to press that button. Until then, your <receiver> will not receive any broadcasts.


UPDATE

On Android 4.0 and higher, it appears that you also need to call registerMediaButtonEventReceiver() on AudioManager in order to receive the events. That state will hold until something else calls registerMediaButtonEventReceiver() or until you call unregisterMediaButtonEventReceiver().

For example, an activity like this:

public class MediaButtonActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ((AudioManager)getSystemService(AUDIO_SERVICE)).registerMediaButtonEventReceiver(new ComponentName(
                                                                                                       this,
                                                                                                       MediaButtonReceiver.class));
  }
}

will enable a manifest-registered MediaButtonReceiver to get ACTION_MEDIA_BUTTON events.

Solution 2

If you just want your app to be the default but don't need to do anything with the button presses you can use the following method.

Add this to the manifest file (in the "Application" node):

    <receiver android:name="BroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
</receiver>

Add this to onCreate() in the main activity or anywhere you want that is called when the app is run. Could be useful in the onResume() event too:

    mAudioManager =  (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
    mRemoteControlResponder = new ComponentName(getActivity().getPackageName(), BroadcastReceiver.class.getCanonicalName());

    mAudioManager.registerMediaButtonEventReceiver(mRemoteControlResponder);
Share:
20,229
Marek R
Author by

Marek R

Updated on November 21, 2020

Comments

  • Marek R
    Marek R over 3 years

    I wrote some service which uses BroadcastReceiver to capture one of media buttons ("play button" from a headset), and it works perfectly on android 2.3.x (HTC Nexus One or HTC Desire)

    When I tried to run in on Android 4.0.3 (Samsung Nexus S) it doesn't work (my application doesn't receive intent "android.intent.action.MEDIA_BUTTON" and "play" button behaves as usual: stops/starts music).

    Content of manifest:

    ...
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <receiver android:name=".buttonreceiver.MediaButtonIntentReceiver" >
            <intent-filter android:priority="10000" >
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>
    ...
    

    Is there way to make it work on android 4.0.3


    edit: I've try proposed solution, I've added action and run it, but my receiver still doesn't receive intent. What is more strange registering receiver by code also doesn't work:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.about_and_activation_view);
    
        Log.d("MR", "onCreate - " + getIntent().getAction());
    
        mReceiver = new MediaButtonIntentReceiver();
        registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_MEDIA_BUTTON));
    }
    

    Now I'm totally confused.

  • Marek R
    Marek R almost 12 years
    I've got only the service which runs speech recognition and sends some other intets. This works nicely on Android 2.3.x. Is this only possible fix? Running activity requires active screen to receive intents and this is not acceptable for me..
  • CommonsWare
    CommonsWare almost 12 years
    @MarekR: "Is this only possible fix?" -- yes, though I suspect that you did not understand the fix. They do not have to leave the activity running. They just have to manually launch an activity of yours once, to move your app out of this stopped state. Please read the linked-to blog post in my answer.
  • Marek R
    Marek R almost 12 years
    It didn't work.I mean I've added Activity and run it, but still I'm unable to capture "android.intent.action.MEDIA_BUTTON", even when Activity is running my receiver doest get this intent.
  • Marek R
    Marek R almost 12 years
    For some reason on Samsung Nexus S key mapping is different and in addition it works only when activity is on. Should I feed different context to make it work always (I mean after activity was launched at least once)?
  • CommonsWare
    CommonsWare almost 12 years
    @MarekR: "For some reason on Samsung Nexus S key mapping is different and in addition it works only when activity is on." -- my test app successfully received the events even if I used DDMS to forcibly terminate the process.
  • Marek R
    Marek R almost 12 years
    Ok it turns out that key mapping has changed a bit in android 3.0: was KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE is KeyEvent.KEYCODE_MEDIA_PAUSE and KeyEvent.KEYCODE_MEDIA_PLAY. In addition now there can be only one broadcast receiver for this intent, I mean when I'm not interested in specific key it doesn't fall back to another receiver. Also calling abortBroadcast(); now has different behaviour (receiver now is getting unregistered). I don't see another solution but limit my app to android 2.x. Thanks for help.
  • CommonsWare
    CommonsWare almost 12 years
    @MarekR: BTW, I just tried my sample code on a couple of devices, and on a Nexus One running 2.3.6, I needed to use registerMediaButtonEventReceiver() in order to receive ACTION_MEDIA_BUTTON events.
  • Marek R
    Marek R almost 12 years
    As I wrote at beginning It works for me on android 2.3.x with use of entry in manifest only.
  • Du3
    Du3 over 11 years
    I cannot get this to work on 3.0+, only 2.3.7 and below. Its when I try to use registerMediaButtonEventReceiver() that it doesnt work. I have accidentally posted similar with a bounty here stackoverflow.com/questions/13257982/…
  • nmr
    nmr over 9 years
    DING, API MUSICAL CHAIRS. NEW ROUND BEGINS ... NOW developer.android.com/reference/android/media/session/…
  • Admin
    Admin about 9 years
    The line stating that "manifest-registed MediaButtonReceiver" gave a cure to my headache.