I'm an android beginner, and unfortunately I could not find a satisfying answer for my service problem so far. I hope you can help me. I think that my question addresses a common task.
My situation is the following: I have implemented my own service that simply records GPS locations and stores them in a list. Once the service stops, it writes the data to a database.
This works well, but now the service should have some kind of "pause mode" where it stops recording and can be resumed later on. What would be the best way to implement this functionality?
So far I came up with two (admittedly not very satisfactory) ideas:
Implementing my own service lifecycle (start, stop, pause, resume) and binding the GUI to the service. Moreover, it seems that the binding happens asynchronously, which makes updating the GUI (enabling and disabling the start/stop controls) a little messy.
On pause, the service is stopped and the GPS locations are appended to some list in a singleton class. On resume, the service is started again and so on. The problem I see here is that the application might get killed while in pause mode and the data is lost.
Related
I need to record uncompressed audio from the microphone continuously (hours) in an Android app, process the audio and visualise the result in a plot. If the app loses focus, the plotting can (and should) stop, but the recording and the analysis shouldn't.
I'm not sure I got the right steps, so this is the implementation I have in mind:
A RecordActivity handles the view, in particular plotting the results as they arrive and handling the button presses. A record button starts a RecordService
A RecordService service initialises an android.media.AudioRecord and on its AudioRecord.OnRecordPositionUpdateListener reads in the buffer, saves it to file and analyses its contents. The result of the analysis is stored.
The RecordService uses a PendingIntent to communicate the results of the analysis to the RecordActivity, which updates the plot.
When the users presses the stop button, RecordActivity kills the service by calling stopService.
My questions are:
Is it right to use a service for this or can I just use an activity?
Is it right to use a started service rather than a bound one?
What parts of this process should be handled by a different thread (or even process)? The AudioRecording? (The analysis obviously depending on the requirements). The entire service?
Should the service being a Foreground service?
In general, is this structure correct?
A Service is a good solution, what I don't understand is why you're using a PendingIntent. Maybe you should consider using LocalBroadcast and normal Intent
In this case, since the service is bound to the lifecycle of the Activity, I suggest to use a bounded Service :)
Well...it depends. If the AudioRecording implementation has its own thread (as I guess in Android), then it's not strictly required to use a thread. But if you write many datas to filesystem, it could be better to start a thread inside the service and handle your logic there (remember that services are not thread)
It depends by your design. If you pause your Service logic when the app goes to background, it's not necessary. But if you need your service even when the app goes in background, then it's better to use a foreground Service
In general, I believe it's a good solution
I have an app which starts a service (using startService). This service performs something similar to playing music. It can be seen as an indefinite work which has to be stopped manually through my activity.
In my activity, I would like to use a "switch" to show the state of the service (running/not running). This is somewhat like a play/pause button on a music player.
When my activity is created, how would I create the UI (switch) to be consistent with the service state (running/not running)?
I don't this using saveInstanceState/restore... will work. My app could be killed completely and the service will service and I will not receive the instance state once started again.
I don't this using SharedPreferences/DB will work. My process could have been killed and at next start, the app would think that the service is running.
The only stable solution I've been able to come up with is to ask the service (maybe through binding) if it is doing work or not.
Would this work? How would you do this?
Binding to the service would work (we have this exact scenario with a background audio player and resolved it that way).
Be mindful that binding is asynchronous, though.
my knowledge of services in any operating system, is that they usually run in the background and perform whatever work they have to do.
but the first time I got familiarized with android services, I got confused.
it appears they only run when the application is working, and that for me, makes them no more then sophisticated threads.
do I have this all wrong? how do I make a service that runs when the application doesn't? (so that I can check for updates and create notifications for the user that will then lead him to the application if he chooses to open them).
does push notifications have anything to do with it?
Edit:
thank you guys for your answers so far.
my problem seems to be the fact that the service is only started officialy when the device is booted up. I do call startService when the app starts, but that doesn't seem to help. the service still dies when the app is turned off (unless it was booted)
also I never call stopService
If you are trying to implement a long running task that is performed in a (background) service, you have to start one or more threads within your service. So the service just gives you the opportunity to have an application context without having to have a user interface ;) you can consider it as a kind of container.
This page give you a nice overview about different thread approaches in Android. As you can see a service has not its own thread.
Anyway, in your case it seems that an AlarmManager is probably the better option. Running services for polling information all the time can be quite CPU and battery consuming (see this post for instance). So try to avoid having threads that run all the time.
If you can push information about updates from a server it's just fine. Check out Googles Cloud Messaging in this case.
Michael who commented on my question first was right in his comment about startService()
so it goes like this:
my receiver is only activated on boot, and uses an AlarmManager to
time the service to certain intervals.
what I did was to bind the activities to the service. if the service
was off and I binded it and unbinded it, then by the time the app was
terminated, there was nothing keeping it alive.
by simply making sure that the service was started properly with
startService if it is not already on, I managed to keep the service
alive at all times
also thanks to Trinimon who gave a very nice explanation on what
services are, and the importance of not overloading the CPU with
excessive polling. (which is kind of a trade off situation)
good luck to all :)
I have been given multiple solutions to what I thought would be a common scenario. Unfortunately, none seem to work as expected.
I have created a pretty simple android game. The users can invite friends to play and there are a few activities they are routed through during the game lifecycle. All turns and data is stored in a remote server which is exposing the data through web services. Every time an invitation is sent, or the opponents complete their turn, the user is prompted via the service to play their turn.
The service prompts the user using a standard android notification telling them it's their turn. I don't want the service to poll the web service or present notifications while the user is viewing the game (they'll already know if it's there turn).
I have tried the following solutions without any success.
Start the service in the onPause method of the main activity and stop the service in the onResume method of the main activity.
Problem - Each time the user leaves the activity for another one the service starts. The user may be writing something or creating an invitation and they are prompted to take their turn.
Bind each activity to the service and set a boolean (running) flag in the same onPause/onResume methods of all activities.
Problem - This seems logical, but for some reason the service never presents a notification. This is likely user-error, but I'm not sure this is the correct solution anyway.
Start the service in the onPause method of all activities and stop the service in the onResume method of all activities.
Problem - Based on the toasts I'm presenting on the screen showing the state of the service this works as expected. The problem is the user is presented with notifications while the service is off. Apparently my toasts are misleading.
Any help is greatly appreciated. Sample code is not necessary, but would be appreciated if the solution is any more complex than the concept described above.
Thank you.
Don't use a service, use the Google Cloud Messaging and in the receiver of the broadcast, check the state of the game and then decide whether or not to show the notification. Polling is generally bad, uses data and battery unnecessarily.
I am making an android app which will have two services that will keep sending data about the usage of the phone by the user every 24 hours.
The user should execute the app, toggle the buttons to enable the logging of the usage of the phone and then the user should be able to do a normal life with his phone, until he starts again the app and disables the toggle button to stop the logging of the info.
What considerations should I take about the life cycle of the services?
What about the interaction of the user with the phone while the services should be sending the data?
All info is very much appreciated, as I my mind is getting a little bit overwhelmed with all this!
Thanks a lot in advance everybody!
The service can be cut at any time through the settings menu. It can also be killed at any time by Android if it decides it needs the resources for the currently running activity. onDestroy() will be called regardless so use that to store anything needed.
The service runs in the background but through the main UI thread. Thus, it is possible to block operation of the phone through a service. It looks like the phone locked up when it's really a service trying to do something. Any blocking procedure should be used in a thread such as Java timer, Java thread, or AsyncTask.
There can only be one running version of the service at any given time. However, calling startService(myService) if "myService" is already running will essentially override the current running service and onStartCommand() will be called again. However, one call to stopService(myService) is needed to stop it no matter how many times startService(myService) was called.
stopService(myService) will not stop a service if the service is bound to anything. It will wait until all bindings are removed before the service stops.