I have noticed an issue with my audio streaming app on Android 6.0 devices. Audio streaming is done via HLS over a network connection. Audio playback occurs in a foreground service with an active notification. What I've noticed is that when the app enters doze mode/app standby, the wifi connection is lost and playback pauses. My service is in the foreground and has an active notification which, according to the docs, should qualify my app to not be interrupted. I also acquire and maintain a Wifi Lock. I've read about whitelisting my app, however apps like Spotify don't request any special permissions to avoid this issue. Any thoughts or suggestions?
The recommended solution is to have separate processes, one for audio playback and for the UI. See this long thread for lots of details
Here's the relevant section from Ms Hackborn:
... have your foreground service run in a different process than the activity. From what I can see, this will work fine. I would be interesting in seeing if you get the desired behavior there.
Also this is actually our recommended practice for this situation -- if you have a long-running foreground service, it should be in a separate process from the activity, so it doesn't force all of the memory associated with the activity to be kept around. (This is also why this bug got through, all of our [Google] apps use this pattern.)
Related
Context / Current Approach
Hello, I'm curious about my usage of a Foreground Service. I have an app which performs voice communication and maintains a persistent connection to our backend via a websocket. It is a common use case for our users to background our app and do something else which is memory- and CPU-intensive, in particular playing mobile games.
In order to prevent our app's process from dying and severing the voice connection, we run a Foreground Service in our app's process (a local service, in some vocabularies). This Foreground Service doesn't actually do much, it displays a notification that allows the user to interact and mute/deafen/disconnect from the notification tray. All the voice logic doesn't actually live in the Service.
Our hypothesis is that by running a Foreground Service, we effectively mark our process as "foregrounded", and the OS is less likely to kill our app. This also allows the user to swipe away our app and have the process stay alive (including the voice connection). This appears to work and looks very similar to the process/service signatures of similar products (Skype, Spotify) using adb shell dumpsys activity services and the inspectors in the device's settings.
However, from time to time we still hear about users who experience our app being killed while gaming or streaming videos, even when they are on voice and the Service is running.
And Now For The Question(s)
After much research it FEELS like we are doing the right thing already. However, we'd like to make our voice stability more bulletproof if possible, and address those user complaints.
Am I doing the right thing already, or is my understanding of using a Service to "mark our app as foreground priority" flawed? (Addendum: It took me getting to the end of writing this for this question to pop up in my searches. It reads like we're on the right track already).
Is there any way I can verify that the OS is indeed killing my app process? Conventional wisdom says no. However I can imagine some solutions which abuse the STICKY flag to relaunch the Service, log to our servers that the Service was relaunched by the OS (and therefore, must have been killed by the OS), and then stops itself again. I just thought of this while writing so forgive me for not having tried it yet...
Do we have other options? The UI components of our app are not particularly heavyweight. This leads me to think that even if we were to invest in a Remote Service (running in another process), if the OS is already killing our Foreground Service, then the OS will likely also just kill that Remote Service. I don't want to use STICKY to combat that as it would be a poor user experience -- it makes sense for services passively processing data but for active voice chat, restarting "later" doesn't sound great...
Thank you very much for taking the time to read the question, I'm happy to provide any additional necessary context.
i'm building app for listening to acc stream. I m using this library:
https://code.google.com/p/aacdecoder-android/
Especially this player.
PlayerCallback clb = new PlayerCallback() { ... };
MultiPlayer aacMp3Player = new MultiPlayer( clb );
aacMp3Player.playAsync( "http://..." ); // URL of MP3 or AAC stream
It's playing in AsyncTask, but for some smarphones when you put app to backround playing just stop.
Only in methond onDestroy i'm stopping AsyncTask, not in onPause or oStop.
Anyone have an idea why player stops?
Short answer: Music streaming apps need to have a Service running to avoid being terminated by Android.
On a cheaper device or when memory resources run low, Android will simply terminate processes as soon as they go into the background or when more memory is needed. This likely explains why it only happens on "some smartphones" as you mentioned. You can also go into the Developer Options on your phone and play with the "Don't Keep Activities" and "Background process limit" settings to simulate the same thing.
You can read more about how Android prioritizes processes and activities for termination when they are not the active app in the foreground at this link here. You'll read that Services are at higher priority for being kept around than background processes (e.g. Activities that the user exited from, but still have a running thread).
On my music streaming app, when music starts, I start a service (same process as the Activity) and add my app's Main Activity to the Notification area. When the user stops the music, I stop the service and remove the app from the notification area. You'll likely notice very similar behavior between the NPR App, Spotify, i-heart-radio, and others.
I am currently working on an Android project on which we have a audio recorder module.
I am using MediaRecorder and it's working as expected except in some annoying situations :
When a notification sound is triggered by Android, the MediaRecorder stops
When receiving a phone call and even if refusing the call, the MediaRecorder stops
When the screen goes off
mRecorder = new MediaRecorder ();
mRecorder.setAudioSource (MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat (MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile (mFileName3GP);
mRecorder.setAudioEncoder (MediaRecorder.AudioEncoder.AAC);
mRecorder.setAudioEncodingBitRate (96000);
mRecorder.setAudioSamplingRate (48000);
mRecorder.start ();
I obviously doesn't want the audio recording to still be running during a call but on other situations I'd like my app to still perform the recording normally.
I didn't find anything pointing towards a solution. However, I am thinking about wakelocks (for screen off) and AudioFocus (for notifications and incoming calls).
Any advice ?
Thanks,
ant1
If this logic is embedded into an Acitivity it will be subject to the regular lifecycle changes in Android. Even if you prevent some normal operations from happening, you are then preventing/disrupting some of the expected behavior of the device. Maybe that is what you want, but there is another way.
You could use a Service instead:
http://developer.android.com/guide/components/services.html
http://developer.android.com/reference/android/app/Service.html
http://www.vogella.com/tutorials/AndroidServices/article.html
This will run in the background, so will not be affected by normal life-cycle interruptions, but you can still communicate via BroadcastReceivers and Intents.
This requires a little extra work to handle all the communication between the two, and possibly some kind of notification for the user to pause/stop/restart recordings, or whatever makes sense in your case.
Update:
Found this article on the Android docs which imply that you should be trying to pause and start your recording along with the activity pausing and starting:
http://developer.android.com/guide/topics/media/audio-capture.html
Maybe this can help too. One comment mentioned that the microphone stops input when you make/receive a call. Maybe there are built in limitations to what you are trying to do:
Pause and Resume Audio recording in Android
I have an app that plays audio streamed from a server (or locally).
According to what we've seen*, if playing audio through a background Service, the audio will keep playing. However, some users report that the audio will stop when their device goes to sleep. I haven't seen any documentation on audio behaviour while sleeping, definitely the API docs don't mention anything: http://developer.android.com/reference/android/media/MediaPlayer.html . Are there any guarantees that the MediaPlayer will continue playing while sleeping, and if not, should I enable the WAKE_LOCK while playing?
*(and this question seems to support it: Playing music in sleep/standby mode in Android 2.3.3)
I don't think setting the wake lock will matter, in my experience it has nothing to do with keeping a service alive. The Android Service documentation states that services that don't use the startForground() method can be killed to free up memory. It's likely the service is either being killed to free up resources or an exception is causing it to silently crash.
If you app goes into the background, it can be killed by the OS. This is most likely what is happening. You can reduce the chance of this happening greatly by making your Service a foreground service by using startForeground(). A wake lock will not help. Under intense memory strain, your foreground service may be killed, but this is very unlikely when the phone is asleep.
I'm trying to write an Android application which will allow users to listen to a radio station.
I have got the start and stop buttons to work and it plays the stream. If I press the home key and start doing other bits and pieces with the phone, the stream continues to play. This is how I want it to work.
Should I bother creating a service to play the stream, or is the method I already use good enough? What benefit would having it in a service bring? A lot of tutorials and examples online seem to use services but it seems to me it's just adding extra complications into the code. Or is it more efficient?
Regards,
David
You don't need to use a service, but your users may under normal use find that playback stops unexpectedly, it depends on the normal use case, so a Service is the best approach.
The reason is due to the lifetime of the Activity that your streaming object / media player is currently attached to.
At some point the system will completely release the Activity now that it is no longer visible to the user, and once GC happens playback will stop. This will happen depending on memory pressure and what other actions the user takes, such as launching other apps. Services are allowed a longer life span, in general they will be released only after all other backgrounded activities are released but before the foreground activity. A more complete description of process lifecycle rules around Services can be found in the Android docs here.
You may also want to look at the PowerManager and the use of PARTIAL_WAKE_LOCK, which would allow playback to continue when the handset would normally sleep (at the cost of battery life).