Search code examples
javaandroidandroid-bluetoothmedia-buttonsbluetoothheadset

Fail to catch android.intent.action.MEDIA_BUTTON


My app that uses TextToSpeech to read some text is 90% finishes but has been stuck at this part for a few days. All I want is have the play/pause button of my bluetooth headset (Xiaomi's Mi Sports Bluetooth Earphones) to play/pause the TextToSpeech. I think it is the android.intent.action.MEDIA_BUTTON I need to catch, so I added these:

In AndroidManifest.xml:

<receiver android:name=".ButtonReceiver">
       <intent-filter
             android:priority="10000">              
             <action android:name="android.intent.action.MEDIA_BUTTON"/>
       </intent-filter>
</receiver>

Then the class ButtonReceiver.java

public class ButtonReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        
        Toast.makeText(context, "debug media button test", Toast.LENGTH_LONG).show();
        // will finish the code once I catch this intent
    }
}

The debug text does not show up. Though if I changed <action android:name="android.intent.action.MEDIA_BUTTON"/> to <action android:name="android.media.VOLUME_CHANGED_ACTION"/>, it does show the text when I press the volume up or down of the headset but this is not exactly what I want. I only want the app to respond to the play/pause button.

Then I read that I need to use registerMediaButtonEventReceiver, so I tried adding this in my MainActivity.java:

 private AudioManager audioManager;
 private ComponentName componentName;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        audioManager = (AudioManager) this.getSystemService(AUDIO_SERVICE);
        componentName = new ComponentName(this, ButtonReceiver.class);
        audioManager.registerMediaButtonEventReceiver(componentName);

}

Still not working. Also, it says the registerMediaButtonEventReceiver is deprecated, so I am wondering if this is the reason that it does not work.

Further reading from the official document page, it tells this:

If you are running Android 5.0 (API level 21) or later, call FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected. This will automatically call your media controller's dispatchMediaButtonEvent(), which translates the key code to a media session callback.

I find this stupid, as I do not need this extra module to play media. All I need is the detection of the headset button press. Anyway, I tried to implement the MediaSession but gave up soon as it quickly ended up with too many codes that were useless for my app since my app is NOT an audio player app!

Any suggestion? What should I do?


Solution

  • I found the solution myself finally! Instead of making a separate BroadcastReceiver class, I added a public static class in my MainActivity.java:

    public static class ButtonReceiver extends BroadcastReceiver {
           
            @Override
            public void onReceive(Context context, Intent intent) {
                String intentAction = intent.getAction();
                Toast.makeText(context, "debug media button test", Toast.LENGTH_SHORT).show();
                ...
            }
    }
    

    Then added this line in onCreate:

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

    And finally in AndroidManifest.xml:

    <receiver android:name=".MainActivity$ButtonReceiver"
           android:enabled="true">
           <intent-filter
                android:priority="10000">
                <action android:name="android.intent.action.MEDIA_BUTTON"/>
           </intent-filter>
    </receiver>
    

    It works! The app can now catch the MEDIA_BUTTON intent with this setting!