From 94dacca5592cd1fd3cdcbe3d569ababc633668c7 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Fri, 13 May 2011 11:26:18 +0000 Subject: 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 --- .../org/rockbox/Helper/MediaButtonReceiver.java | 46 +++++++++++++--------- android/src/org/rockbox/RockboxService.java | 5 ++- 2 files changed, 32 insertions(+), 19 deletions(-) (limited to 'android/src') diff --git a/android/src/org/rockbox/Helper/MediaButtonReceiver.java b/android/src/org/rockbox/Helper/MediaButtonReceiver.java index a57bdd4831..eebdbb985b 100644 --- a/android/src/org/rockbox/Helper/MediaButtonReceiver.java +++ b/android/src/org/rockbox/Helper/MediaButtonReceiver.java @@ -21,7 +21,6 @@ package org.rockbox.Helper; -import java.lang.reflect.Method; import org.rockbox.RockboxFramebuffer; import org.rockbox.RockboxService; import android.content.BroadcastReceiver; @@ -30,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; +import android.util.Log; import android.view.KeyEvent; public class MediaButtonReceiver @@ -55,7 +55,9 @@ public class MediaButtonReceiver { try { api = new NewApi(c); - } catch (Exception e) { + } catch (Throwable t) { + /* Throwable includes Exception and the expected + * NoClassDefFoundError */ api = new OldApi(c); } } @@ -102,46 +104,54 @@ public class MediaButtonReceiver 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 ComponentName receiver_name; - /* the constructor gets the methods through reflection so that - * this compiles on pre-2.2 devices */ - NewApi(Context c) throws SecurityException, NoSuchMethodException + private boolean running = false; + + 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); receiver_name = new ComponentName(c, MediaReceiver.class); } + public void register() { 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) { // Nothing e.printStackTrace(); - } + } } public void unregister() { try { - unregister_method.invoke(audio_manager, receiver_name); + audio_manager.unregisterMediaButtonEventReceiver(receiver_name); + audio_manager.abandonAudioFocus(this); + running = false; } catch (Exception e) { // Nothing 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); + } + } } diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java index 3aeffa21ff..346e4a189c 100644 --- a/android/src/org/rockbox/RockboxService.java +++ b/android/src/org/rockbox/RockboxService.java @@ -353,7 +353,10 @@ public class RockboxService extends Service public void 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; /* Make sure our notification is gone. */ stopForeground(); -- cgit