I want to write an android service that will run with an app. I want to run this service across multiple activities and have the ability to pass information back to the UI with all activities, not just the activity that starts the service.
From what I understand, I have call startService and not bind it to the activity. Is this correct?
Also, I do not want to start a new instance of the service, I want to use the same instance. If i call startService in each activity, will that use the same, running instance of the service?
startService will start the service only if there's not a previous service running, it won't spawn a second service.
Once you start your service, you can connect to it from any Activity you want, but to pass information back and forth, you need to bind to the service, so you can obtain a pointer to it.
Make sure to read Android's documentation, because the way services work is a little confusing at the beginning.
Related
I am developping a MusicPlayer app, and I use a local Service to be make the MediaPlayer run in the background. It seems that we can either send intent to start a Service or bind a Service. I understand the point of for startService, we leave it running and send intent to stopService, and for bindService, we get back a IBinder to communicate with the service. However, I'm wondering what's the point of doing this? Do we have to send intents to make it work?
If I just retrieve an static instance of Service, and directly call its methods, I can also implement both start it and communicate with it.
I found an example of not using startService nor bindService, but it works well as a simple MusicPlayer.
The fragment calls Service:
https://github.com/zacharytamas/spotify-sampler/blob/master/app/src/main/java/com/zacharytamas/spotifysampler/ui/PlayerFragment.java
The Service class:
https://github.com/zacharytamas/spotify-sampler/blob/master/app/src/main/java/com/zacharytamas/spotifysampler/services/PlayerService.java
However, I'm wondering what's the point of doing this?
To have the service be running, to tell the OS "hey, we are doing work here on behalf of the user, please let my process live a bit longer".
This is covered in the documentation.
Do we have to send intents to make it work?
Yes.
If I just retrieve an static instance of Service, and directly call its methods, I can also implement both start it and communicate with it.
Then it is merely a Java object, and there is no point in inheriting from Service. Also, it means that your process will live for less time when your UI is not in the foreground.
I found an example of not using startService nor bindService, but it works well as a simple MusicPlayer.
The service is started, via startService(), in ArtistSearchActivity. Until this is done, the service does not exist, and the singleton will be null.
startService is used when you don't need to communicate with the service.
BindService is used when yout need to communicate with it.
In your app, I think you will communicate with the service (for example, if you have an activity where you choose the song, your will send data to the service to say: "this is the song which you have to play now") and I think you will need BindService instead startService.
I hope this will help you :D
I have an activity that binds to a service. The service provides the functions to interact with an XMPP server.
Then, the activity launches a second activity that needs to access to the same service (for instance to initiate a voice call).
I was thinking to bind the second activity again to the same service, but it seems like an overkill, since when the second activity starts the service should already exist and should be there until the first activity destroys it on purpose (binding again means creating a new connection and waiting for the bind to happen asynchronously before using the service).
At the moment I'm using startActivityForResult() to launch the second activity and then I wait for the result and I access the service from the first activity, but I want to change the logic (the second activity must interact with the service and then the first one takes care of closing the second activity when a signal is received back from the service).
Any suggestion on how can I pass the service object to the second activity?
binding 2 activities to the same service is no overkill. It is actually the proper way of doing what i understand you are trying to do : access xmpp functions provided by a service from 2 different activities.
by binding the second activity, you will not start the service again, as it has already been started. it will connect to the same service as the first activity.
you could, of course, put all the binding to a single place, like a singleton or the Application class.
You could store a reference to it in the Application and then access it from your second activity.
I read some similar questions (for example at this link), but the problem I'm asking is a bit different. In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
Suppose we have a package that contains the MainService service and MainServiceActivity activity. In the file "AndroidManifest.xml" this activity is declared with action MAIN and category LAUNCHER. This activity is used to configure the service via the SharedPreferences and start the service by invoking startService method. In other words, typically the user launches the MainServiceActivity and configures/starts the MainService.
Now consider another activity (Let's call it SecondActivity) that is part of another package. Depending on the configuration, the service starts this activity using the startActivity method, so this other activity is running on a separate process than the MainService. As soon as the activity is running, it should inform the service.
At this point, a communication request/reply begins between the MainService and the SecondActivity: the service sends a request and the activity sends a reply.
The communication via messaging might fit, but the MainService is started through startService method, so the bindService method can not be invoked by activities that want to bind to the service.
Then I had an idea that makes use of an additional service (Let's call it UtilityService), which is part of the same package of MainService: the UtilityService could be started using the bindService method. As a consequence:
as soon as the MainService is running, it might perform the bind to the UtilityService;
when the MainService launches an external activity (for example the above SecondActivity), this activity bind to the UtilityService.
In this way, both the MainService and the SecondActivity are connected to the UtilityService, where the latter acts as an intermediary for communication.
Are there alternatives to this idea?
In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
You can both bind and start a service, if you wish. It's a bit unusual, but it can be done.
Are there alternatives to this idea?
Binding has nothing in particular to do with services being able to communicate with activities. Using some sort of callback or listener object via binding is a possibility, but it is far from the only one.
You can:
Have the service send a broadcast Intent, to be picked up by the activity
Have the activity send a PendingIntent (e.g., via createPendingResult()) to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity (or wherever the activity wants it to go, such as a broadcast)
Have the activity pass a Messenger tied to its Handler to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity
All of those work perfectly well between processes, as well as within a process.
You can use Android Interface Definition Language (AIDL).
You can find an easy to use guide here
I have an Activity that starts a service. When the activity is closed, I want the service to continue running in the background. I have a couple of questions here.
Will closing the activity screen cause the activity to actually stop? Or do I need to forcibly stop it to cause it to stop?
If closing the screen does cause it to stop, then I assume I need to use startService to start it. Is that correct? If that is the case, is there a way to get a handle to the running service next time the activity starts? If it is not the case, then I can just bind to the service.
When your Activity is no longer visible on the screen, it is stopped. Stopping an Activity bound to a Service does not stop the Service. However, you'll want to make sure you unbind from the Service when your Activity calls onDestroy() to make sure you don't have any dangling handlers and suchlike.
You can rebind to a running Service the same way as you did the first time. Sending an Intent to start a Service that's already running doesn't create a second instance of it, so that's safe.
A good way to start a Service like you're describing is to start it using the Context.BIND_AUTO_CREATE argument to your call to bindService().
The details of all of this can be found at the Android docs about bound services. It can be a little confusing at first. Follow the tutorial code closely since it sounds like your problem maps well onto the sample they provide.
I have a service running in background. I started it from an Activity, but I want to recover an instance of that service from another activity (in the same app) in order to call one method.
Is it possible?
There is only one instance of the service, at most. You cannot have two instances. Hence, just have the second activity bind to the service ("recovery an instance").