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.
Related
There are several ways to connect to Service to Activity. I am only interested in local service and my LocalService will stand there untill user stops it(which also means end of app). I might know things wrong, if so please correct me.
On the reference page, it is stated that in order to use methods of local service directly, we should use ServiceConnection. After binding, we can have a reference to LocalService class, and we can use methods of this LocalService directly. AFAIK the methods we call using this reference run on main thread with relevant Activity.
The thing that confuses me, what if I use skeleton structure and access LocalService's methods by directly its static reference (ie. by LocalService.getInstance()). Well, I have already used it and did not face any problem, but still I am not sure which one is better, and why.
Thanks in advance. I might add additional info if requested.
edit:
In my previously mentioned solution, no activity is keeping a reference to the LocalService.
It is used to
start some LongRunningAsyncTasks(which are all halted and reference-nullified before service stop),
update the app Notification,
get getFilesDir(),
to keep an enum value (whose reference is not kept elsewhere, it is just used for comparison) in order to access from everywhere(not worthy of using SharedPreferences).
show some toasts
aware of static references of activities and services because they can be a reason of memory leak. if you don't want your service run in main process, then extract it into another process and work with service connection.
If you don't need any feedback from service, then just don't use connection and simply use startService() with several commands which will be executed in onStartCommand() method of the service.
If you need feedback from service, but not frequently, then use startService() and feedback from service with sendBroadcast() or through Handler class.
If you need feedback frequently (for example update slider of media player), then it's better to use service connection.
Remember that your service can be killed anytime without executing method onDestroy() and without any notification, that's why keeping static reference is not good idea.
It appears from what you are saying that you probably don't need a Service at all. Looks like you are not doing any long-standing task in your LocalService. If that's the case, you can as well use AsyncTask or Handlers and be done. The motivation to use a Service (Local or otherwise) is to do some long standing task inside it and not stall the main UI thread. If your tasks are not gonna take up too much time, then you don't need a Service.
The Service does run on the main thread by default. Unless it's an IntentService where a worker thread is created for you automatically and all tasks are queued and handled one at a time in this worker thread. Otherwise, it's your responsibility to create a separate thread for your service tasks.
So, first analyze if you really need a Service. If your task can quickly get executed, then don't bother having a Service even.
Hope that helps.
I am developing an Android data entry app that saves the entered data to a file. A Service (let's call it FileIOService) is launched using the filename, and loads and saves data that is passed to it from each Activity that the user accesses.
I am trying to make the whole app as robust as possible, and at the moment I feel I need to pay particular attention to the interaction between each Activity and the Service. Here are the issues I can see:
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
The thing is, once the Activity launches the Service, there's a while before the Service finishes opening the file and becomes ready for I/O requests. To address this, in my Activity, I have both:
an inner class subclassing ServiceConnection, with its onServiceConnected() method completed
a private reference to an anonymous inner subclass of BroadcastReceiver, with its handleMessage() method completed. This gets called when the Service sends out a broadcast to indicate it's finished opening its file.
Both of these methods then call a setUpActivity() method that pulls data from the Service. This is where it starts to get ugly. Because onServiceConnected() may run before the file is ready for I/O, and handleMessage() might be called while the Service is not bound to the Activity, I have to make both handleMessage() and onServiceConnected() set boolean flags that can later be checked in setUpActivity(), like this:
if ((fileLoaded && serviceConnected))
{
//access the file data
}
As I said, this feels ugly and awkward, and relies on setting extra boolean variables.
There's another problem - if my Activity launches an external Activity, like the Camera app, upon returning to my app the Service and Activity may both have been destroyed (especially with an orientation change) and the app crashes.
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
Let's ignore the fact that I am skeptical that this is a valid use case for a service (a service whose existence is simply to read and write files?).
If the Service is killed by the system, it needs to restart and open the file that it had open: I can handle this by using START_REDELIVER_INTENT.
The service is not "killed by the system". The process is killed by the system. This will eradicate your activities as well as your service.
The one possible exception to this is if the user manually stops the service (and only the service) from Settings, in which case I have no clue what the expected behavior would be. This should be fairly uncommon nowadays, particularly for an app that the user had just been using. Users will be more inclined to use a task manager, such as swiping your app off the recent-tasks list, which will get rid of the entire process, not just the service.
If an Activity is destroyed, for instance by an orientation change, it needs to reconnect to the Service.
Not necessarily:
Bind using the Application context (getApplicationContext()) instead of from the Activity directly
Use a retained fragment to maintain the binding across the configuration change
My feeling is that I may be missing some overall pattern that would define how each Activity should relate to the Service, and vice versa, while remaining robust and able to cope with unexpected terminations/restarts.
This is one of the many reasons why I try to avoid the binding pattern altogether. Use a service for processing commands, sent via startService(), with results (if any) delivered by LocalBroadcastManager, or Otto, or greenrobot's EventBus, or a "real" broadcast Intent, or maybe a Messenger. Particularly when the service is an IntentService, the service nicely cleans up after itself when there is no more work to be done.
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 Networking service that i want to use as a Service. It's a local Service since it's not valid anymore once the application process is dead and no Other applications need to access it.(or should...).
I was pondering if to use the IBinder interface with local reference to the class and decided not to, for the moment.
I have the following issues:
if the service dies, and i know it can during request processing, it's an issue for me, first i've seen it, the process wont die until the net request returns (then the thread dies gracefully), unless kill -9 is used on the process... then i'm not sure what android does with the connections. I'm not sure what's the approach i should take here.(it will be true though even if this was a local thread and not a service...)
if i want the service to listen on a callback and call it once the network processing is done, i'm in a problem, no instances can be passed on using Intents. So i need some other solutions, all the ones i though of sounds bad to me: A. use IBinder to get instance of the network service class then i can call one of it's methods and pass on an instance, this will work since they all run in the same process, BUT requires me to use Async way to get a Network instance which is not so suitable for me. B. Use static member in the Service i can access, then what to i need the service for ? C. use intent to send parameters only to the service, the service will compose a Request out of it and put it in the queue, then once done will send a response using intent which will encapsulate the response (which might be long!) and will also contain the name of the calling class as a string so all the Receivers will know if it's for them or not - BIG overhead of encapsulating data in Intent and search in all the receivers for the right one to get the response.
I don't want to use the service as a local running simple thread since i'm afraid if i'll run it in the root activity i will have to use static container so it will be visible in each activity and if the root will be destroyed for some reason it will take all the service with it, even if i start new task and the process is still alive...
Anyone got some nice ideas on how to approach this thing ?
Eventually i gave up on the service.
The reason to not use the service But to extend Application object and keep the networking class as a member of that Application object, it is started when the application is created, before any activity is created,and it is shut down before the application draws it's last breath. I know application onTerminate might not be called at all times, but if someone will call kill -9 or equivalent on my Application and the process will die killing the application with it, i'm all set as my Service will be destroyed anyway.
The reasons i gave up a service were:
i have a way to keep a worker thread running during the application life cycle.
Since i have and for future planning will have only one application it will still work in the future.
Since It's not connected and started with any specific Activity it wont be affected by their death or by their creations.
it has a context that will last through the lifecycle of the application so i CAN use it to broadcast events using intents.
when the application dies my service dies with it. unless kill -9 and then the system will kill all threads related to the application, mine included, so i'm still good.
Every activity can use getApplication() and cast to my Application object and get the service.
So no need to use binding and complicate my code with it, no need to think of how to start or end the service, if i'd made a service most chances i'll be starting it from the Application anyway (or the root activity), so i think for me and my app this is the best option.
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.