Music playback in background on Android
I'm working on a music player and my current focus is to port it to Android. I have problem to play music if the player is in background. The current song remains playing but it won't start the next track.
The playback is implemented by using a QMediaPlayer instance and connecting it's signal QMediaPlayer::stateChanged to find out that the current track has stopped.
I believe the program is suspended in background and either the signal is not sent or the code which should react to the signal is not executed.
Is there any solution to my problem? I was looking for some information and it seems I need to use a service for this and that won't be available until Qt5.7. But that is only a guess.
Pablo J. Rogina
Thank you for pointing me at the article. I didn't study the code really deeply but I'm afraid it is exactly the opposite to what I need. The article is about running C++ code in Android UI thread. But what I need is to run my code in the background (even if the UI part is not displayed).
I found this BogDan's comment. I tried to use the second suggestion and in AndroidManifest.xml changed the value android.app.background_running to true. That partially does the trick.
However there still remain some problems. My player sometimes crashes when in background. I should not update the UI. But how do I recognize that my app is in background?
Another problem is that in that case Android can kill my player at any time. I'm not sure how it works inside. But according to my experience with Android, if an application has an icon is notification area, it won't be killed by the system. My player doesn't have such icon.
Do you have any ideas how can I solve these 2 problems? I'm sure I will need some Java code in the future but I'm trying to avoid it as long as possible.
UI update does not crash programs in Android background. Something is wrong with your code if application crashes.
If your app has android.app.background_running == true then while it will have some working thread - then Android won't kill it.
@Gourmet That's not entirely correct. You should not update your UI if the app is in background. But I already know how to recognize that and avoid any crashes because of it.
Also I moved the background tasks to a service which runs independently on the UI thread.
@vlada probably you confused with "background thread" and "background application" terms. UI should not be updated from any background thread inside app. It can be updated only from UI thread running on foreground. This is true for any Qt based application, not only on Android but any other OS supported. Attempting to do that forces application crash. But if entire application screen is not visible (application works in background) in Android or any other OS then it can update it's UI as well. Setting android.app.background_running == true means app can run under other's app covering screen or desktop. This DOES NOT relate to background threading inside app. For example all my apps work fine if any other app covers Android screen completely. And yes - all my apps have android.app.background_running == true to allow this. They draw on their widgets even being covered. But they never crash.
By default the main QEventLoop is freezed when it goes in background. We need to do it because the surface that Qt needs to paint to is not available anymore and if you try to paint something your application might crash. There are two ways to keep going on Qt world after it goes in background: – create a new thread , call QThread::exec() then create all the timers and other QObjects that you need the in that thread. – don’t freeze the Qt main loop. You need to edit AndroidManifest.xml and set “android.app.background_running” to “true”, but you must make sure you don’t draw anything when the application is backgrounded.
I think in the last sentence BogDan clearly states that I shouldn't draw anything on the UI when the app is in background. Has anything changed since then? Because at that time my application was really crashng if I tried to modify something in the UI.
May be changed or may be this was an error in article. My app has music visualization widget which intensively draws in it's paintEvent(). All works fine in all Android versions from 4.1 to 8.0. Running in background this app works fine and does not crash. Some other similar apps have other widgets redrawing in paintEvent(). No one crashes in background.
@Gourmet OK, so I have to try it if it will works now. Maybe I'm now doing some unnecessary things.
Btw. how do you have music visuaiation implemented? I want to do it too but I don't know how can I get decoded music data.
@vlada Android Visualizer class. But it probably has bug in API level 26.