Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Google Play Music hogging all ACTION_MEDIA_BUTTON intents?

When sending a sendOrderedBroadcast with an ACTION_MEDIA_BUTTON intent (I'm imitating that the user is clicking the play button on a bluetooth headset), Google Play Music opens and plays the last album played instead of the foreground music playing app.

If I change it to sendBroadcast, both Google Play Music AND the current music playing app (Pandora in my case), will enact the play button.

This only occurs in Android 4.0 and above. Is Play Music hogging this intent (a bug)? Do you suspect that Pandora is not registering itself as the current media button handler following this advice: http://android-developers.blogspot.com/2010/06/allowing-applications-to-play-nicer.html

Is there a way I can direct this intent to the current music playing app only?

Here is my code:

public void broadcastMediaIntent(MediaIntent intentType){

      long eventtime = SystemClock.uptimeMillis(); 

      Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); 
      Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); 

      KeyEvent downEvent = null;
      KeyEvent upEvent = null;

    switch(intentType){
    case NEXT:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT, 0);

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT, 0); 

        break;
    case PLAY_PAUSE:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0); 

        break;
    case PREVIOUS:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS, 0);  
        break;
    case FAST_FORWARD:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 0);  
        break;
    case REWIND:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_REWIND, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND, 0);
        break;

    default:
        break;
    }

      downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent); 
      sendOrderedBroadcast(downIntent, null); 

      upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent); 
      sendOrderedBroadcast(upIntent, null); 

}
like image 593
joepetrakovich Avatar asked Sep 24 '12 21:09

joepetrakovich


1 Answers

The following should do the trick. BTW, where did you find the source code for the lock screen?

   public void handleMediaKeyEvent(KeyEvent keyEvent) {

    /*
     * Attempt to execute the following with reflection. 
     * 
     * [Code]
     * IAudioService audioService = IAudioService.Stub.asInterface(b);
     * audioService.dispatchMediaKeyEvent(keyEvent);
     */
    try {

        // Get binder from ServiceManager.checkService(String)
        IBinder iBinder  = (IBinder) Class.forName("android.os.ServiceManager")
        .getDeclaredMethod("checkService",String.class)
        .invoke(null, Context.AUDIO_SERVICE);

        // get audioService from IAudioService.Stub.asInterface(IBinder)
        Object audioService  = Class.forName("android.media.IAudioService$Stub")
                .getDeclaredMethod("asInterface",IBinder.class)
                .invoke(null,iBinder);

        // Dispatch keyEvent using IAudioService.dispatchMediaKeyEvent(KeyEvent)
        Class.forName("android.media.IAudioService")
        .getDeclaredMethod("dispatchMediaKeyEvent",KeyEvent.class)
        .invoke(audioService, keyEvent);            

    }  catch (Exception e1) {
        e1.printStackTrace();
    }
}
like image 80
user1937272 Avatar answered Sep 18 '22 00:09

user1937272