I am working on a applicatin that syncs with videos on server. It starts a IntentService that downloads playlist, inserts it into database and than downloads actual video files to sd-card.
I am using a messenger passed via intent when starting the service to communicate back how much % is already downloaded.
I works but obviously when activity gets destroyed and starts back again, the messenger doesnt reconnect.
What would be the solution to this problem, steer me into correct direction. Thanks
If you want to use a messenger, you need to keep a reference to the handler created with the messenger that you passed to the intent service.
If the activity gets destroyed and recreated, that handler is still bound to the previous activity (which may also result in a leak).
One approach may be to have a reference to that handler inside a singleton object or inside the application object.
However, because of the asynchronous nature of intentservices, what I would do is notify the progress through broadcasts, so new activities may register to the same broadcast thrown by the intentservice. You never know if the service is still alive or has finished its job.
Using localbroadcasts may result in a more efficient solution.
Related
I know this look like tons of question around SO. But it's not (although I can also be wrong).
I have a long running Service (running in a separate thread using blutooth socket pooling for data in a OBD2 adapter every 5 seconds).
This Service is running in the same process and is a Foreground Service.
The user start this Service through an Activity. It then connect to the Bluetooth device and start pooling and saving data to a SQLiteDataBase.
The user can then minimize the activity and do other stuff.
When he returns (if ever, he can stop the service through a notification area button) to the application it checks if the Service is running and if so, it starts another Activity which show the data that is being pulled from the OBD2.
My question is, between this visualization Activity and the Service should I use and by this I mean the recommended or the right one:
LocalBroadcast? This is actually what I am using. Every time the service pull some data, it sends a broadcast with the data everytime it was pulled. Then in the onReceive method call runOnUiThread to update the respective View.
Messenger? As far as I know (never used it) I should send a Messenger from the Activity to the Service (much like a Handler) and in the Service it should send the Messages with the data pulled. But from this I would get a RemoteObjectException if the Activity was destroyed (like I said, the user could just minimized the activity and then it got GCed). So, I would probably need a way of sending the Messenger to the Service every time the Activity gets created and check if it's ok to use the messenger form the Service every time (if that's even possible, I've never used this).
BindService? Should I bind to the service when I open the Activity and then get the data directly from methods in the Service? But this would probably mean I would have another thread in the Activity gets this data from the Service every time, right?
Handler? (for a moment now I realize don't know the difference between Messenger and Handler, should it be that "use Messenger when Service runs in another process and Handler otherwise)
I've seen/read a lot of answers here in SO and through the web in general.
But in the end I don't see a ultimate answer for my case. But I'm sorry if this is just because I couldn't figure it out.
Thanks in advance!
EDIT: forgot to mention, I would rather make use only support libraries and android framework stuff, I'm still learning Android and I want to understand what's happening within its own classes.
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! :)
I have a service that downloads some data from internet and periodically sends progress to the indicator activity. In the end of processing service sends a result.
I have a question what is the best way to achieve persistence of the communication.
Messenger or ResultReceiver, I need to parcel them into Intent and store list of listeners in the service. But on configuration change activity destroys, and it's hard to maintain this list.
LocalBroadcastManager, I need to migrate from Messages to Intents, and also there is no sticky send in this class. So if I get result while my progress activity is in background result will be lost.
BroadcastManager is good, but I don't need to broadcast my progress system wide, and security issues.
Any ideas?
You may want to give Otto (http://square.github.io/otto/) a try.
In your service, whenever you want to communicate with the activity, post a new event using a shared Bus. You should do that on main thread with a handler or main looper since you are probably using IntentService. The service may act as a producer as well. When your activity is recreated, current known value will be posted.
Your activity just needs to register with the Bus and subscribes to the right event. When it is paused, just unregister with the Bus.
I belive the best way to achieve that persistance is:
After the service downloads, you should save your data in a database or a file.
The service then sends broadcast to update.
If the activity is "alive" all goes well and it goes to the database/file to get the updated content.
If the activity was killed or something, you just have to make sure the data is in the database/file so that when you start/restart the activity you can get the latest content from database/file.
While downloading keep a state and progress saved in the db/file the same way.
Check this Google I/O Session, it explains this really good.
Use static variables inside your Application class (extends Application). Inside Service you set this variables. Inside Activity you read periodically this variables.
You should use massenger to send download progress, because it is more secure and less expensive method then broadcast receiver.
I'm developing an app with a service that forwards calls to a web-service, and a few activities that place those calls. The activities need to process the results of those calls. For example, I have a writeComment method on the service, that accesses the web-service and returns some information about the newly written comment.
Right now I let the Activity take care of all the threading. The Activity binds the service, and then uses an AsyncTask that calls the bound service's writeComment method.
All works well as long as the Activity isn't stopped while the AsyncTask is running. If it does (easily happens when flipping the phone), the AsyncTask dies a violent death when trying to update the UI in onPostExecute. I'm not entirely sure how to fix this - I do need to let the user know the server has been updated.
If I go the other way around, and register a callback with the Service, I'm still a bit stump, because I need to notify the Service the Activity has changed - I need to tell it not to notify me in the first Activity's onDestory, and reregister in the second Activity's onCreate. And I need to handle the case where the asynchronous task completes after onDestroy and before onCreate.
What is considered Best Practice in this case?
Thanks,
Itay.
My intuition tells me to let the service handle the threading. Services are far less transient (although still transient to some degree) than activities and therefore you'll have less issues of threads trying to interact with a Context (be it an Activity or a Service) that's no longer there. Have you looked at the IntentService class? It handles a lot of the threading for you.
In my app, I have a long-running service and Activities that need to render data in the service. The service also pings the Activities when there is a change but the Activity can also query the service. The way I approached this was two-fold.
Firstly, I bind my activity to the Service in order to send messages from Activity to service.
Secondly, the Service sends notifications with Broadcasts and the Activity listens for those broadcasts. I set that up in the Activity onResume and tear it down in the onPause. I think this is the part that you're missing.
I have a Worker Service, and a bunch of Activities. Every Activity has a Handler. The Activites can start jobs by sending Intents to the Service with the startService method. These jobs get into a queue, and are processed sequentially.
To report back the results of the finished jobs, I supply the proper Activity's Handler wrapped in a Messenger object with the Intent that describes the job. The Service sends back some message for the calling Activity through this. This works just fine.
But the supplied Handlers seems to remain in memory, even after the corresponding Activites got destroyed, continuing to handle the completion messages.
How can this be? Shouldn't the handlers be destroyed with the Activity they're part of?
Does this cause a memory leak?
Since the Service has a reference to the Itnents which still have a reference to the Activities Handler then the Handler isn't going to become available for Garbage Collection.
Have you seen this video from Google IO? It's about building apps that use RESTful web services so isn't directly relevant but the approach of delegating the responsibility for responding to long running events will partially map to your problem.
If you don't want to change things around too much then you need a way in your Activities onClose or onDestroy to notify the Service (and through it the Intent) that the long running task it is in charge of isn't needed anymore. It removes it's reference to the Handler and so the GC can get rid of it.
That or centralise the management (as in the video) of running tasks and responding to their lifecycle in a ServiceHelper class. That class can publish events as things happen and the activities can listen for those events.
This has the benefit of your code being in one place so you don't have to change every activity when you want to change how you handle the service.