There is some long processing that need to be completed, so I put it in a service. The activity must be able to connect to the service, show the user current results from the service. So I start the service with start Service and later call bind Service (with BIND_AUTO_CREATE) as in LocalService from http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle. I want it to run until its job is done, and then self stop, even if client is still connected to it. (or determine the client to unbind) Is any way to do it with the sample LocalService?
I was considering passing a handler to the service so that it can send messages back to the activity, but I don't want the activity to get leaked. I am just getting used with services, so maybe I am misusing something.
EDIT: The workload consists of several threads, synchronized and run in parallel, so I guess is not a good candidate for intent service. Some data analysis is done in background service, and when the user restarts the activity that started the service, it should display some graphics according to current values computed by background service. All background processing is triggered at the beginning, and need only inspection later on, when activity connects to it. Android should not be able to stop the service. When the job is finished, the service should be able to terminate even if the activity is connected to it.
I just recorded a callback with the service. If the activity is not connected to service, it sets the callback to null. In this callback I call stopService() and then finish() on the activity. I am not sure that it is the best method, but it works fine for me.
If you want a service to be stopped when it is finished, I think what you are looking for is IntentService, they work as services, but run in another thread and when they are completed they dissappear.
Check this out
EDIT: NickT link is better, check that out! :)
Related
I'm developing an app that communicates with an embedded device via BLE (Bluetooth Low Energy). The app allows the user to send commands via an activity. Meanwhile the app needs to send location data in the background. The location data must be sent constantly, even if the activity is closed and opened multiple times over the day.
I cannot separate the continues location updates from the command requests. Because all BLE transmissions must be synchronized by one queue to prevent simultaneous transmissions which would cause package loss.
After reading the official guide (https://developer.android.com/guide/components/services#Basics), my first idea was to use a foreground service because the service must not be terminated when the activity is closed. That works fine for sending the location data. However, for sending the commands I have to communicate with the service after it has been started. I read that it's not recommended to use both startService() and bindService() but instead to decide for one way. As far as I understood a bound service can be destroyed when the referencing context (the activity in my case) is destroyed. So I guess binding to the service is not an option for me.
Another approach to talk to a started service is to send commands using broadcasts and receiving them in the service (sending commands from Activity to Service in android).
But I think there must be a better solution that I miss. What came to my mind is simply calling startService() every time I want to send a Bluetooth command. I guess that would work. But is it good practice? Effectively, I would call startService() dozens of times during a typical use case before calling stopService().
Oh wow... I read through the whole guide but overlooked this sentence in the method documentation:
startService()
Every call to this method will result in a corresponding call to the target service's onStartCommand(Intent, int, int) method, with the intent given here. This provides a convenient way to submit jobs to a service without having to bind and call on to its interface.
https://developer.android.com/reference/android/content/Context#startService(android.content.Intent)
Hope it helps in case that someone stumbles across it..
You don't have to bind the service to anything. It's enough to start it and then make sure you call startForeground on it. That will keep your process running without being killed by the system. You don't have to place your BLE code in the service class but can have it wherever you want.
So basically what i am trying to do is i want a service that runs in background and updates the LatLong to the server. This operation needs to happen all the time even if the application is running or not.
Now when the application is launched i want the service to calculate the distance between the latlong and update the UI in addition to the work that it was already doing i.e. updating the latlong to the server. i want the service to do the additional work for multiple activities. lets say i launch the application and i am on Activity A, onclick of a button on Activity A the service starts updating the UI and when we click gain it stops updating. Now i am on Activity B and on click i want the service to do some work in addition to the updation of LatLong and update the UI.
What would be the best approach to achieve this.??
EDIT
The problem i am facing is not getting the service update the UI but making the activity communicate with the service when it has already started.
i can pass on some data when i am starting the service but how to communicate with the service when it has already started. How to tell the service that see you are already running and doing some operations now you have to perform some more operation on top of the previous operation.
I can make some static method in the service and call them when i need to perform the extra operation but i dont wanna do that.. i want to better approach.
Here is the basically services runs on the same main thread process as ui. When you want make it run continuously you have run it in your tread. In this way you avoid service being get stopped as application go in background or killed. (Please take look at Service.START_STICKY flag, this is what you need as i guess).
And more coming your second problem of activity getting updated with service information or data that is being collected for this you need look at " How Bind the service". (In activity check for service connection and Binding to a activity, Unbindibg is also there have look at it also). Activity has all the call backs for it you need to implement binder.
EDIT
Service to update ui has to have send and receive intent mechanism. You can broadcast and intent from the services check your activity is running or not. If running broadcast intent and have receiver in activity to listen it.
You can do it by interface mechanism too
I coded an IntentService where I send a command line. Is related to an activity where I'm trying to program a Console. The activity's purpose is to do a 'command prompt' where I can send and receive to/from the server.
The Service's action is:
COnnect to the server
Send command line
Get response
Retrieve response to user
The main problem is that every time I send a command line, the Service has to reconnect to the server. (Cause every time I'm starting the whole Service)How can I avoid this step?
I would like to "keep alive" the service waiting for a command line to send, without the need of reconnect every time I execute its action.
Is there any way to do it action-responsive? I mean, I start the service and every time I set its action (setAction) and put the line I want (putExtra). Then I have to start the service again?
Good night. Tomorrow I'll be back :)
Thanks in advance!
Due to its "one shot" design, using an IntentService isn't a good approach IMO.
If you don't want to start the service each time you send a command, then I'd suggest you 'bind' to a standard Service (see Bound Services). If you bind to the Service in your Activity's onResume() method and unbind in onPause() your Activity will be able to directly call methods in the Service.
You will, of course, have to create your own worker Thread in your Service to handle any work involving your network connection however. If you want any tips on how to do that, look at the source code for IntentService - it's fairly straight-forward.
Don't use an IntentService. Per the documentation:
the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Instead, you should consider using a normal Service (calling stopSelf()) when you want to stop the service (and your connection to the server). Or, if you'd like the connection to the server to have the same lifecycle as the activity, you can create a bound service: it will start when your activity binds to it and then stop when the last activity is unbound.
I have created a service that runs various tasks by calling methods, such as toggling wifi, sending a message etc.
It only runs one task at a time, and after that I want it to close the service.
Is there a way to check if the service has completed its processing and then shut down the service?
Thank you.
The service knows when the service “has completed its processing”, so the service can stop itself via
stopSelf()
Or, better yet, use
IntentService
instead of
Service
This gives you a background thread (which you may need, depending upon the work that you are trying to do) and will automatically stop itself when there is no more work to be done.(Reference1)
Reference
I have a class that implements fileuploader service. Activites bind to it and supply it a list of files to be uploaded, and then unbind immediately. The files are then uploaded one-by-one by the service in a background thread(asynctask).
I start this service in my dashboard actvity using startService(), so that it keeps running until specifically stopService() is called.
Now, my question is when do I stop this service?
Basically I need to check two conditions: 1: all files are uploaded; 2: app has exited.
Also, to exit the App, user has to press back button on dashboard activity.
I could have overrided back button press and queriesd the service whether any files are left, but I dont want to use that method.
Any suggestions?
Activites bind to it and supply it a list of files to be uploaded, and then unbind immediately.
I would recommend then using startService() rather than bindService().
The files are then uploaded one-by-one by the service in a background thread(asynctask).
This seems like a much better fit for startService() and an IntentService (or a WakefulIntentService perhaps, if you are concerned about the device falling asleep during uploads).
I start this service in my dashboard actvity using startService()
This would not be needed if you used startService() for sending over the work.
so that it keeps running until specifically stopService() is called.
Ideally, the service would shut itself down, like IntentService does. After all, only the service knows when the service is done.
my question is when do I stop this service?
When you have no more work to do. IntentService does this automatically. If you really want to maintain your own thread pool for doing the work, then when your work queue is empty and all threads are done, call stopSelf() from within the service.
Basically I need to check two conditions: 1: all files are uploaded
Yes.
2: app has exited
No. Your UI should not care whether the service is running or not running. The service should take care of itself.
Also, to exit the App, user has to press back button on dashboard activity.
Users are welcome to leave your app however they please: BACK, HOME, RECENTS, a Notification, an incoming phone call, etc.
Any suggestions?
Use an IntentService. Send over the jobs to be uploaded via calls to startService(), packaging all needed data into the Intent used with startService() (e.g., extras). Do your upload work in onHandleIntent(). If desired, use LocalBroadcastManager to let activities in your app know about the upload status, so they can reflect that in their UI if they so choose. IntentService will handle stopping itself when its work queue empties.