Closed GoogleCodeExporter closed 9 years ago
I don't have an ICS phone yet. I hope to soon. Once I do, I can look into
this. It might be the functionality changed significantly in ICS and it's no
longer possible to write an app like media button router.
Original comment by harleens...@gmail.com
on 7 Dec 2011 at 8:46
A couple of additional data points:
A few other apps stopped taking bluetooth headset buttons commands with ICS:
- Audible
- Beyondpod
Beyondpod posted a beta version of their app on their site which fixed the
problem.
I wrote to Audible about this but didn't yet get a response.
A couple of other applications seem to continue working fine:
- PowerAmp
- Music (the native app)
Not sure if all this helps, but there you go... and thanks for your prompt
response!
Original comment by mi...@google.com
on 7 Dec 2011 at 9:22
I did get a Google Nexus but I haven't had time to investigate this yet. I will
probably have some time over the holidays.
Also, to anyone who is interested, please feel free to contribute a patch or
anything to this project :) I wrote this app for when I was commuting by car.
I've since moved and now commute by train. So, I'm not the most motivated
driver of this project anymore (pun intended).
Original comment by harleens...@gmail.com
on 20 Dec 2011 at 6:53
tl;dr version: Difficult, if not impossible, to get media button router to work
in Android 4.0
The problem is that the priority in Android's built in broadcast receiver
(declared in AudioService.java) changed. This receiver is the one that forwards
Media Button keys to a receiver registered to be the sole receiver via
http://developer.android.com/reference/android/media/AudioManager.html#registerM
ediaButtonEventReceiver(android.content.ComponentName). It's used so that when
a music app is opened and playing music, no other app can handle the media
button keys. Before ICS, Android's broadcast receiver was being registered with
priority IntentFilter.SYSTEM_HIGH_PRIORITY. But I guess because some music apps
were always trying to take control and setting priorities higher than this
(Integer.MAX_VALUE), Google changed how they're registering Android's own
receiver to also be Integer.MAX_VALUE and it always wins.
Unfortunately, media button receiver had a legitimate reason for using
Integer.MAX_VALUE (we want to replace android's behavior for media buttons). In
order for media button router to work with Ice Cream Sandwich, I'd have to
change the approach significantly. I'd also have to have different code for ICS
and prior versions of Android. I don't even know if there is a workable
alternative. One possible solution would be to register Media Button Receiver
also via AudioManager.registerMediaButtonReceiver. The difficulty is making
sure MediaButtonRouter is always on top of the stack if no music is playing (or
even if music is playing would be workable).
I will leave this ticket open, but in all likelihood it won't be fixed anytime
soon if ever. I will also open a ticket in Android's issue list asking for
similar behavior to be a core part of Android, or way to swap out the handling
behavior.
Original comment by harleens...@gmail.com
on 22 Dec 2011 at 1:31
Here's a patch that gets it working again with ICS. It might need a little work
to get it going on older versions of the SDK, but it should be compatible.
There were two problems with ICS:
1. The Android AudioService registers itself for the MEDIA_BUTTON intent with a
priority of Integer.MAX_VALUE so that it can do its own thing which is to send
the intent to whatever activity registered itself most recently using
registerMediaButtonEventReceiver.
I'm getting around this problem by creating a service
(MediaButtonMonitorService) that watches the system preference
(Settings.System.MEDIA_BUTTON_RECEIVER). Whenever another package calls
registerMediaButtonEventReceiver, AudioService updates that preference with the
name of the class. So when MediaButtonMonitorService sees the preference change
(and it isn't set to MediaButtonReciever), it changes it back to
MediaButtonReceiver.
2. My Bluetooth device on ICS is sending different key codes when I press the
media button. It's sending KEYCODE_MEDIA_PLAY (126) and KEYCODE_MEDIA_PAUSE
(127). The latest version of Music has been fixed to work with these, but not
older apps like Listen. I just adjusted the places where MediaButtonConfigure
looks at the key codes to convert either of these key codes to
KEYCODE_MEDIA_PLAY_PAUSE which works with both.
Original comment by pet...@sapros.com
on 24 Dec 2011 at 4:52
Attachments:
I forgot one more issue I had. In MediaButtonReceiver, it only looks for apps
that have foreground set to true. That never worked for me. I had to take the
foreground checks to get things to work, but I'm not really sure why.
Original comment by pet...@sapros.com
on 24 Dec 2011 at 4:56
Thank you so much for continuing to work on this project. It is much safer
to use my phone while driving with this app.
Ryan Quellet
Original comment by rquel...@gmail.com
on 24 Dec 2011 at 4:57
Thanks Peter! I had no idea you could listen for an event to be informed when
another app calls registerMediaButtonEventReceiver. That was my major hangup,
having a way to always be on top of the stack without running a service that
blindly re-registered itself every couple seconds. Is
Settings.System.MEDIA_BUTTON_RECEIVER documented anywhere? I'm curious.
The foreground check was just when I was guessing which app was currently
playing music. It wasn't always used. I can make it a preference to disable
this foreground check. Also, with this patch and ICS, I can always just
de-register media button router when music is playing and re-fire the event.
Then the receiver on the stack right below will get the event. This should be
the correct media player in ICS since apparently media players that don't
register themselves via registerMediaButtonEventReceiver don't get events.
Thanks for also informing me about the other key codes, I had no idea.
I'll test this out and try to release an updated media button receiver early
January (if not sooner).
Original comment by harleens...@gmail.com
on 24 Dec 2011 at 5:06
I had to go combing through the Android source code to figure it out. I don't
think it's documented. It's a hack. The AudioService is just saving that value
so that if the audio settings get reloaded (on a restart or whatever), it loads
the same media button receiver. Since Android has a callback for watching
settings, you get pretty much the effect of getting notified any time another
service calls registerMediaButtonEventReceiver because every time that gets
called AudioService updates the system setting.
Original comment by pet...@sapros.com
on 24 Dec 2011 at 5:22
Your last comment explains why it was sometimes starting Music whenever Listen
was playing audio and I hit the button to stop it. Without the .foreground
stuff its guesses about who was playing audio were wrong. So I went ahead and
implemented your other idea. I couldn't figure out a good way to re-fire the
event to the next receiver on the stack because we don't really have access to
the stack. Instead I had the MediaButtonMonitorService store the value of the
system preference whenever another app updated it and put in an app preference
variable and then the MediaButtonReceiver takes a look at that and uses that to
figure out who to pass the event on to. Seems to work well.
Original comment by pet...@sapros.com
on 24 Dec 2011 at 6:42
Attachments:
Thank you all for your efforts to fix this!
Original comment by mi...@google.com
on 24 Dec 2011 at 6:43
I've incorporated Peter's changes. The big thing that remains and that I'm
working on is getting list navigation in the selector to work again with the
previous, next, and play buttons.
Original comment by harleens...@gmail.com
on 24 Dec 2011 at 4:40
I've fixed the problem with the list navigation in the selector. I ended up
just having the MediaButtonReceiver just broadcast every media button event it
gets. Then the
ReceiverSelector just listens for that broadcast the same way it did the
original media button broadcast. It seems to work okay, but the text to speech
audio doesn't trigger after it changes the selection for some reason I haven't
figured out yet.
I made this patch using 'hg export' this time (I'm new to Mercurial, so I was
just using diff before). That might make it easier for you to pull it in. I
think the MediaButtonMonitorService.java file didn't make it into your last
commit.
Original comment by pet...@sapros.com
on 26 Dec 2011 at 6:11
Attachments:
Taking out the textToSpeech.stop(); line in ReceiverSelector.onPause fixes the
audio problems for me.
Original comment by pet...@sapros.com
on 26 Dec 2011 at 6:36
Thanks Peter. Instead of taking textToSpeech.stop() in
ReceiverSelector.onPause, I changed the MedaiButtonReceiver so that if the
selector is open, it just broadcasts the custom action you created, and
returns. Otherwise, what was happening is the receiver would get the custom
action, but then also be shown (paused/resumed) again by the showSelector logic
in the receiver.
Original comment by harleens...@gmail.com
on 26 Dec 2011 at 7:32
Fixed in version 1.3.0 (should be on market shortly)
Original comment by harleens...@gmail.com
on 26 Dec 2011 at 11:53
Original issue reported on code.google.com by
mi...@google.com
on 7 Dec 2011 at 7:58