MediaButtonIntentReceiver not working in Android 4.0+
Asked Answered
I

2

11

The goal is to intercept broadcasts from the headset, as well as bluetooth eventually, to respond to different types of clicks from the headset to alter the mediaplayer. This solution works fine for all versions prior to ICS. Here is some of the code and things I have tried:

....
private BroadcastReceiver mediaButtonReceiver = new MediaButtonIntentReceiver();
....
public void onCreate() {
    ...
    IntentFilter mediaFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
    mediaFilter.setPriority(2147483647); // this is bad...I know
    this.registerReceiver(mediaButtonReceiver, mediaFilter);
    ...
}

public class MediaButtonIntentReceiver extends BroadcastReceiver {

    private KeyEvent event;

    public MediaButtonIntentReceiver() {
        super();
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
            return;
        }
        event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
        if (event == null) {
            return;
        }
        try {
            int action = event.getAction();

            switch(action) {

                case KeyEvent.ACTION_UP :
                    Log.d("TEST", "BUTTON UP");
                    break;
                case KeyEvent.ACTION_DOWN :
                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE :
                    Log.d("TEST", "BUTTON DOWN");
                    break;
            }
        } catch (Exception e) {
            Log.d("TEST", "THIS IS NOT GOOD");
        }
        abortBroadcast();
    }
}

To try to make this work, it sounds like 4.0+ requires something like this which didnt work:

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

I even tried to add it to the manifest, in addition to the above:

    <receiver android:name=".MediaButtonIntentReceiver" android:enabled="true">
        <intent-filter android:priority="2147483647" >
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
    </receiver>

Still no luck. What am I missing here? It's certainly a 4.0+/ICS/JellyBean issue... This is being done in a service, not an activity.

Intinction answered 6/11, 2012 at 19:28 Comment(1)
I also found this being the reason in Android core, but no solution to getting around it: code.google.com/p/media-button-router/issues/detail?id=10#c4Intinction
C
10

It looks like your broadcast receiver is an inner class to your service? If so, make your broadcast receiver static and in the manifest do this:

<receiver android:name="MyOuterClass$MediaButtonIntentReceiver" android:enabled="true">
    <intent-filter android:priority="2147483647" >
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

In Android 3.0+ you must use registerMediaButtonEventReceiver to register the receiver. This uses the AndroidManifest for the IntentFilter. The reason it works in 2.x is because you were registering it with this.registerReceiver() which registered the receiver without the AndroidManifest.

Cotter answered 27/11, 2012 at 1:34 Comment(2)
The only justification for me to use an inner class is to be able to access methods of the outer class, but if the inner class is made static, I won't be able to access these methods. Catch 22. Suggestion?Alan
@Alan We use Greenrobot's EventBus as a simple way to communicate between components (greenrobot.org/eventbus/documentation). E.g. static BroadcastReceiver posts an event that the activity subscribes to. Great for decouplingEthbun
B
1

Just try on jelly on this is working for me :

             broadcastReceiver = new BroadcastReceiver() {//global BroadcastReceiver
            @Override
            public void onReceive(Context context, Intent intent) {

                String action = intent.getAction();
                if(action.equals("android.intent.action.MEDIA_BUTTON")){
                    Log.e("test", "ok");
                }
            };

Intent :

        IntentFilter intentfilterTime = null;
        intentfilterTime = new IntentFilter();  
        intentfilterTime.addAction("android.intent.action.MEDIA_BUTTON");
        registerReceiver(broadcastReceiver, intentfilterTime);

Test from service with media button of Widgetsoid (who emulate BT media buttons). All is working.

Blubberhead answered 25/11, 2012 at 18:8 Comment(7)
When I press and hold the media button Google apps still takes it over. I even added the max priority to the intent. I added your snippit of code in the onCreate function. Are there any other places I need to define, like in the manifest about the intent? Like I said, this is working fine on pre-4.0 AndroidIntinction
Did you test on real device ? or emulator ? My code don't work for you ? Cause work for me on galaxy nexus with android 4.2. Normally intent is on manifest or in code like i give you but there is not other places.Blubberhead
Tested on Galaxy S3 with 4.1.1. I have tried all of the above. Your code does work on 2.3.6Intinction
Maybe you have another application with hight priority (more than yours) who get event so you will never have it. Cause this code is working for me on android 4. I see only this possibility...Blubberhead
I have tried on 3 devices, all similar apps. I just dont think the register is working. Check this out: #10537684Intinction
Why it's working for me ? On your link it said on accepted answer "On Android 4.0 and higher, it appears that you also need to call registerMediaButtonEventReceiver() on AudioManager in order to receive the events." Try this maybeBlubberhead
I have tried that as well. I mentioned that in the post. I tried a few variations, esp with the manifest.Intinction

© 2022 - 2024 — McMap. All rights reserved.