I'm trying to architect a REST-heavy application.
Following one of the models proposed by Virgil in his Google I/O presentation, I've set up my application like so:
My Activity calls upon a "Service Helper" which is a singleton. This singleton instantiates a Service which, upon start, uses a ContentProvider to hit my application's database and spins a thread to hit a web service for any pertinent syncing. The last piece I now need is having the Service callback to the singleton, which calls back to any listening Activities.
This is the part I'm confused about.
Right now, I'm looking at the Android SDK's provided RemoteService ApiDemo. In RemoteServiceBinding.java, an IRemoveService member var is declared called mService. mService is used in various handlers to handle the callbacks.
However, this code will go in my Service Helper (remember this is a singleton). There could be N number of calls to this class to start up Services for database and web service functions. I can't just declare 1 variable called mService, right? The RemoteService declares an ISecondaryService, but I could have N number of pieces of code calling this singleton. It needs to be dynamic.
Ex:
User is on Activity A and wants to show things in a list. The Service Helper singleton is hit, returns a Cursor and starts a Service which is querying a web service for new things. mService is instantiated to handle callbacks for this Service instance.
Before this Service is finished, the user switches to Activity B and does the same thing for the things in that Activity's list. mService is already instantiated for the previous Service instance. What do I do now?
Suppose the connection was slow and the user could do this for 20 Activities before the first one finished getting new things. mService is already instantiated for the previous Service instance. What do I do now?????
What do I do here? I'm at a loss.
It would be really really nice if the Twitter app was open sourced already...
I don't know where you ended up on this, but if you used an IntentService, only one Service would need to be created, and that IntentService would place new calls to Context#startService(Intent i) in a queue.
As the single IntentService handles the queue, they will be processed in the onHandleIntent(Intent i) method of your IntentService. In this method you could to pull extras from the passed Intent to figure out exactly how to handle the requirements set forth by the calling Activity.
Related
I have a service that opens a Bluetooth connection to a device. I need to have access to this connection from 2 activities. I know how to bind one activity to a service but what if I need to bind 2 activities to a service.
If I bind to the second activity to the service, will it create a second instance of the service?
The other answer is not really correct (I don't think they read their own doc references). You can bind multiple times to a service without any problems. Each connection to the service will operate independently of each other, and their ServiceConnection objects will reflect when they independently connect and disconnect.
There will only ever be one instance of a service as defined in the manifest. When a client is bound for the first time, the service object will be created. Each new client will not create a new object instance of that service. But when the last client is unbound, the service destroy (as long as it is not also currently "started") by onStartCommand.
You can verify all this behavior by using well-placed log statements in your code.
will it create a second instance of the service?
Yes, it does
However, multiple instance of the same service cannot be run simultaneously!
Possible solution to your problem would be :to bind the Service in the onResume() method, and unbind it in the onPause() method. This allows you to give two un-related Activities access to the service, while only having one bound at a time.
For further info, read these questions as well:
here
here
Also, consider reading this article on local bound services
I'm trying to connect to a Service using bindService().
I am able to obtain reference to the Service in onServiceConnected() method of ServiceConnection.
My question is if I declare a method say downloadFile() in Service and call it through the Service object from an Activity rather than calling startService() and then calling downloadFile() from onStartCommand(), then what is the difference between the two approaches ?
What is the difference between the two approaches ?
The method you are proposing is a wrong-headed approach, for three reasons:
In Android, Activitys and Services are considered to be app components. A component should be treated as an independent entity whose internal methods are not directly called by other components/classes. Such a component should be started using an Intent and then left to do its own work.
If you don't call startService(), you literally never start the Service. How then would you call a method defined inside it ? And manually creating instances of classes that are app components is frowned upon in Android. You should never do something like
new Service()
or
new Activity()
That's just bad and you're inviting a whole lot of trouble.
If you are going to call downloadFile() directly from your Activity, then why put it in a Service in the first place ? Isn't that redundant ? The reason for putting it in a Service is that the download operation is a non-UI task that requires no user interaction, which is what a Service is meant for. An Activity, on the other hand, is a UI-based component that is explicitly meant for user interaction. If the user dismisses your Activity while the download is in progress, then a NullPointerException gets thrown when the download completes and your code tries to post the data on the UI.
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.
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've encountered a weird issue that has gotten me stumped for a few days now. First some background info:
I have an activity that binds to a third party service (given to me as a library). This service sends asynchronous callbacks to the client (my activity) whenever the client requests an action be performed. The service is never started with startService() and stopService() calls; I perform bind when i need the servcie and unbind when I am done. I never have more than one activity bound to the service at any one time.
My issue:
The user starts my activity (lets call it instance A). I bind to the service in onCreate() and issue a request. I receive a callback from the service and set some local variables accordingly. Once i go through what i need to do, i call finish(). onDestroy() gets called and i then perform un bind service. My assumption at this point is that both the Service instance and my activity should not be able to be referenced any more.
Now, after A has finished, the user starts my activty again (lets call this instance B). I again bind in onCreate and issue a request. However when i receive a callback, i notice that the service has issued a callback to my old "ghost" instance A. I am now using all of instance A's local variables instead of using This new instance B. I even printed out the "this" reference before binding and again after receiving the callback and was able to see that the reference changes from instance B's to instance A's. Execution in my activity continues to proceed, but since my local variables are now set incorrectly to their old state at the end of A's execution, B's execution fails.
So a few questions:
How is it possible that A is still being referenced after
onDestroy() and unbind is called?
Is it likely that this issue could be related to the third party
service and not my implementation? (again, I don't have the
source code to this service, i'm just using it)
Thanks for any insights you all can offer.
-Jason
Turns out it was the the third party service.