Any guidelines for handling the Headset and Bluetooth AVRC transport controls in Android 2.2 - android

I am trying to figure out what is the correct (new) approach for handling the Intent.ACTION_MEDIA_BUTTON in Froyo. In pre 2.2 days we had to register a BroadcastReceiver (either permanently or at run-time) and the Media Button events would arrive, as long as no other application intercepts them and aborts the broadcast.
Froyo seems to still somewhat support that model (at least for the wired headset), but it also introduces the registerMediaButtonEventReceiver, and unregisterMediaButtonEventReceiver methods that seem to control the "transport focus" between applications.
During my experiments, using registerMediaButtonEventReceiver does cause both the bluetooth and the wired headset button presses to be routed to the application's broadcast receiver (the app gets the "transport focus"), but it looks like any change in the audio routing (for example unplugging the headset) shits the focus back to the default media player.
What is the logic behind the implementation in Android 2.2? What is correct way to handle transport controls? Do we have to detect the change in the audio routing and try to re-gain the focus?
This is an issue that any 3rd party media player on the Android platform has to deal with, so I hope that somebody (probably a Google Engineer) can provide some guidelines that we can all follow. Having a standard approach may make headset button controls a bit more predictable for the end users.
Stefan

Google has a detailed blog post on implementing the newer 2.2 AudioManager media button event receiver while maintaining backwards compatibility with older devices.
http://android-developers.blogspot.com/2010/06/allowing-applications-to-play-nicer.html

After some experiments, I was able to get a working solution with the new transport and audio focus infrastructure in Android 2.2.
What I end up doing is requesting both the Audio Focus (using AudioManager.requestAudioFocus) and the Trasport Focus (using AudioManagter.registerMediaButtonEventReceiver) every time my application starts playback.
requestAudioFocus takes a callback that is called when the audio focus is taken away from you (for example the internal player starts a playback). In my case I just pause the playback in my application if the focus is taken permanently. Same callback also now tells you that the focus is taken only temporary (for example the Nav system is talking) so you can "duck" your playback - lower the volume or pause and resume after it is done talking.
The only issue remaining is that the built in Music Player takes the transport focus every time you connect a Bluetooth headset. This has the effect where the first press of the Play button on the headset after connecting it, always starts the playback in the default Music Player.
There is probably a way to detect the headset connection and "hijack" the transport focus. In my case, I decided to not "fight" the default player, and get the transport focus back when the user manually starts the playback in my application.
If somebody has more insight or knows of a better way of handling the transport/audio focus, please share it.

I also have this same issue with the media button registration.
Periodically the Android returns the media button registration to the default music player. I have not been able to figure out why. This can happen while may application is actively playing as well as while my application playback is paused.
After a number of users complained that their Bluetooth pause and play control buttons would periodically stop working to control my application, I implemented code that re-registers my application by calling registerMediaButtonEventReceiver every 2 seconds. This allows me to get the button registration back and for the most part avoids the time window where where the user presses a Bluetooth media button and the default media player ends up responding.
My application is holding the audio focus during this entire time period, but still loses the Bluetooth button events periodically while it has audio focus. My application always unregisters the media button event receiver if it is called with a notification that it is losing the audio focus, and then registers again if it is later called when a temporary audio focus loss returns the audio focus.
The work around to keep the 2 second timer running and re-registering has been working, but I would like to get rid of this 2 second timer if someone has found a work around for the media button registration periodically switching back to the default media player.

Related

Use MediaButton to control foreground app (no audio) with audio in background

I want to use the media buttons to control a foreground app, but not for audio use.
So the goal is to detect button clicks to do certain things in the app.
I can achieve that by using MediaSession and the MediaButtonReceiver. see here
The problem is that when the app is used, often users play music in the background, so the audio focus of the background app takes over the MediaSession and i cannot control my app anymore.
Is there a way to achieve that? Directly listening for button clicks with onKeyDown does not seem to work.
sadly there is no way for two active MediaSessions at the same time. if another app is playing music and run MediaSession then yours doesn't have focus and isn't active... this is made for purpose - better UX - only one "player" app can play music (or video). if this wouldn't work like that and you could play music by few apps at once then how should work media button on e.g. headphones? pasuing/resuming all players? this is just not user-friendly, so Android team introduced MediaSession pattern with option for calling "focus on me now" by any app, but then another app/MediaSession pauses and doesn't get any inputs (this active session does)
if you need physical buttons presses then onKeyDown should work (inside Activity or eventually using AccessibilityService, which would work "globally" in whole system). if you need some on-screen notification buttons presses then just make custom layout for your notification with as much buttons as you like, even styled as a player
note that in Android 11 active MediaSessions notification is stickied to top of notification section when you drop down status bar. your custom notification will be somewhere below between all others (you can manipulate position a bit using priority param for notification/channel)

Release AudioRecord android when other app request for recording

I have an audio recording service in my app which will record the sound continuously. So, it will always occupy the AudioRecord. It means no other app can use audio recorder as it is already occupied by the service. Is there any way to notify that other app is requesting for audio recorder(so that I can release it) and also when the app releases it(so that I can assign it back to the service)?
Maybe a possible way is to create a BroadcastReceiver which receives an event from the app which is requesting the control over the mic source. The onReceive() method should interact with the service and release the resource. When the other app is finishing it can revert the process to start the service again. If you can't get control over the behavior of the requesting app I think there's a slightly different problem. Anyway:
The problem is all about knowing when the resource is being requested, this can be done through AudioManager intent types.
Be sure to check Managing audio focus which talks about audio focus loss in TRANSIENT way!
As #Rekire mentioned, there is possibly no way to achieve this. Also, AudioManager provide no such broadcasts, so it is not possible for different apps. Maybe rooting the device is the only option.
This can be done with AudioManager.OnAudioFocusChangeListener callback. Just stop recording on AUDIOFOCUS_LOSS_TRANSIENT event and start again on AUDIOFOCUS_GAIN event.
This solution works well for Google Voice Search (Google Search widget, Google Chrome, etc).
But unfortunately it works poorly for other ordinary applications (for example HTC M7 Voice Recorder app is not able to start recording on first click on "Record" button, second click do the trick - it seems app should be ready to retry recording on failure several times).

When should a music player gain and give up audio focus?

I'm writing an Android music player, and is stuck on audio focus issue.
It seems like audio focus mainly affects media button receiving, but after reading the document I have no idea about when to gain and give up focus.
My music app will run in background, and need to detect play/pause button every time. That is, even when my app is not running, a user should be able to press headset's play button and start music.
It seems I should never give up audio focus, so why should I implement it?
Does anyone know practically how audio focus should be used? Thank you!
It seems like audio focus mainly affects media button receiving, but
after reading the document I have no idea about when to gain and give
up focus.
They both are separate functionalities, and thus have separate listeners. You may have audio focus taken away from you but you may still choose to respond to play pause hardware keys
That is, even when my app is not running, a user should be able to
press headset's play button and start music.
I am assuming that you meant by the above line is that you are still playing music but not showing an activity. To keep listening to hardware button press, dont unregister your media button receiver(dont call audioManager.unregisterMediaButtonEventReceiver(receiver) yet).
It seems I should never give up audio focus, so why should I implement
it?
you dont give up the focus , it gets taken from you. To handle that gracefully you have AudioFocus listener. For ex, consider an incoming phone call. Would you still like to continue playing your music?

Stop ringtone and audio in Android when listening audio

I am building an Android app for webradio.
I am using vitamio player that extends the functions of the standard MediaPlayer. This problem could also be happening in the standard Media Player as well.
If I'm listening radio and I receive a call, ringtone starts, but the radio doesn't stop!!!
How can I stop it ?
Which event?
Otherwise, I think what you are looking for if you are a developer of the said app is provided at this link. It provides an example of hooks that monitor phone state. On the ringing or call active states you can set your app to a paused or silent state.

Creating 'middleman' headset button controller in Android

All,
I have searched for an answer to this, but I'm not getting anything exact... It's my first time writing an Android app, so please be gentle :)
I'm pretty bummed about the minimal headset support in Android - unlike e.g. iPhone, it only natively seems to support a single button, so no volume control on headset compatibility. Additionally, if I'm listening to music and a call comes in, the OS pauses the music automatically, but the headset button still functions ONLY as a media button - I can't use it to answer/end the call. If I answer the call via the screen and press the headset button, the music starts again, but the call continues...
I'd like to create a 'middleman' app that can pick up that the headset button has been pressed (via Keyevent.KEYCODE_HEADSETHOOK) and can then determine whether to perform the default ACTION_MEDIA_BUTTON action (toggle play/pause in my chosen media player) or, if there is an incoming call, pause the music and answer the phone (and then, when pressed again, end the call and restart the media player). Perhaps even check for ACTION_MULTIPLE on the headset button to assign different options (ACTION_MEDIA_NEXT, ACTION_MEDIA_PREVIOUS etc.). Perhaps also be able to determine whether different buttons on the headset have been pressed (if the headset is e.g. a fancy iPhone headset) and 'translate' those button presses into the appropriate ACTION_MEDIA_*). This might not be possible if the OS can't tell the difference between different buttons, obviously.
Obviously such an app would have to receive the intent with a high enough priority that it would be able to abort the broadcast before the current media player gets it.
I've been tinkering with creating assorted BroadcastReceiver classes and intent filters etc., but part of the problem is that the bult-in Android emulator that comes with Eclipse doesn't seem to have the ability to simulate a user plugging in the headset and/or subsequently clicking the headset button. Therefore, every time I get somethign that looks promising, I have to put it onto my actual phone and try it out - time-consuming and a hassle.
3 questions then:
Am I missing somethign obvious - is this a real problem and if so, has it already been solved?
If it IS a problem, is it possible to write such a middleman app?
Are there any other Android emulators that can check for headset-related activities?
Thanks,
Rory
i´ve already written exactly this kind of app. Its called like the topic of this thead: Headset Button Controller ;-)
http://www.androidpit.com/en/android/market/apps/app/com.kober.headset/Headset-Button-Controller
Cheers Christoph

Categories

Resources