1
0
Fork 0
forked from len0rd/rockbox

Rework MediaButtonReceiver a bit:

* Get rid of reflection since the lack of methods can be detected via exceptions
 * Use requestAudioFocus/abandonAudioFocus APIs on 2.2+ to play nice with other music apps.
 * Don't unregister the receiver on exit so we can receive media button presses (and startup the service) after idle poweroff (hopefully it's ok if mMediaButtonReceiver is garbage collected)

This should fix that Android calls the standard music app sometimes when those buttons are pressed.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29865 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thomas Martitz 2011-05-13 11:26:18 +00:00
parent fffc6c4a80
commit 94dacca559
2 changed files with 32 additions and 19 deletions

View file

@ -21,7 +21,6 @@
package org.rockbox.Helper; package org.rockbox.Helper;
import java.lang.reflect.Method;
import org.rockbox.RockboxFramebuffer; import org.rockbox.RockboxFramebuffer;
import org.rockbox.RockboxService; import org.rockbox.RockboxService;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@ -30,6 +29,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.media.AudioManager; import android.media.AudioManager;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
public class MediaButtonReceiver public class MediaButtonReceiver
@ -55,7 +55,9 @@ public class MediaButtonReceiver
{ {
try { try {
api = new NewApi(c); api = new NewApi(c);
} catch (Exception e) { } catch (Throwable t) {
/* Throwable includes Exception and the expected
* NoClassDefFoundError */
api = new OldApi(c); api = new OldApi(c);
} }
} }
@ -102,46 +104,54 @@ public class MediaButtonReceiver
void unregister(); void unregister();
} }
private static class NewApi implements IMultiMediaReceiver private static class NewApi
implements IMultiMediaReceiver, AudioManager.OnAudioFocusChangeListener
{ {
private Method register_method;
private Method unregister_method;
private AudioManager audio_manager; private AudioManager audio_manager;
private ComponentName receiver_name; private ComponentName receiver_name;
/* the constructor gets the methods through reflection so that private boolean running = false;
* this compiles on pre-2.2 devices */
NewApi(Context c) throws SecurityException, NoSuchMethodException NewApi(Context c)
{ {
register_method = AudioManager.class.getMethod(
"registerMediaButtonEventReceiver",
new Class[] { ComponentName.class } );
unregister_method = AudioManager.class.getMethod(
"unregisterMediaButtonEventReceiver",
new Class[] { ComponentName.class } );
audio_manager = (AudioManager)c.getSystemService(Context.AUDIO_SERVICE); audio_manager = (AudioManager)c.getSystemService(Context.AUDIO_SERVICE);
receiver_name = new ComponentName(c, MediaReceiver.class); receiver_name = new ComponentName(c, MediaReceiver.class);
} }
public void register() public void register()
{ {
try { try {
register_method.invoke(audio_manager, receiver_name); audio_manager.registerMediaButtonEventReceiver(receiver_name);
audio_manager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
running = true;
} catch (Exception e) { } catch (Exception e) {
// Nothing // Nothing
e.printStackTrace(); e.printStackTrace();
} }
} }
public void unregister() public void unregister()
{ {
try try
{ {
unregister_method.invoke(audio_manager, receiver_name); audio_manager.unregisterMediaButtonEventReceiver(receiver_name);
audio_manager.abandonAudioFocus(this);
running = false;
} catch (Exception e) { } catch (Exception e) {
// Nothing // Nothing
e.printStackTrace(); e.printStackTrace();
} }
} }
public void onAudioFocusChange(int focusChange)
{
Log.d("Rockbox", "Audio focus" + ((focusChange>0)?"gained":"lost")+
": "+ focusChange);
if (running)
{ /* Play nice and stop for the the other app */
if (focusChange == AudioManager.AUDIOFOCUS_LOSS)
RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_STOP, false);
}
}
} }

View file

@ -353,7 +353,10 @@ public class RockboxService extends Service
public void onDestroy() public void onDestroy()
{ {
super.onDestroy(); super.onDestroy();
mMediaButtonReceiver.unregister(); /* Don't unregister so we can receive them (and startup the service)
* after idle poweroff. Hopefully it's ok if mMediaButtonReceiver is
* garbage collected.
* mMediaButtonReceiver.unregister(); */
mMediaButtonReceiver = null; mMediaButtonReceiver = null;
/* Make sure our notification is gone. */ /* Make sure our notification is gone. */
stopForeground(); stopForeground();