What are the ways to communicate between an Activity and a Service on android?
Today I learnt how to communicate by sending an Intent from Activity and replying back using BroadcastRecevier.
Which are my other options? Does anyone have a tutorial/reference regarding this?
Answer to this question is:
There are several way for an activity to communicate with an service and vice versa. This section dicusses the different ways and gives recommendation which to use.
5.1. Activity binding to local service
If the Service is started in the same process as the Activity, the Activity can directly bind to the service. This is a relatively simple and efficient way to communication.
5.2. Using receiver
You can also use dynamically registered receivers for the communication. For example your activity can dynamically register a receiver and the service sends outs corresponding events.
5.3. AIDL for services in a different process
To bind to a service which runs in a different process you need to use Inter Process Communication (IPC) as the data needs to be send between different processes. For this you need to create a AIDL file which looks similar to an Java interface but ends with the .aidl file extension and is only allowed to extend other AIDL files.
This approach is required if your service should be provided to other applications, otherwise you should prefer a local service.
5.4. Sending Intent data and bundle to the services
The service receives data from the starting Android component and can use this data.
5.5. Handler and Messenger
If the service should be communicating back to the activity it can receive an object of type Messenger via the Intent data it receives from the Activity. If the Messenger is bound to a Handler in the activity the service can send objects of type Message to the activity.
A Messenger is parcelable, which means it can be passed to another process and you can use this object to send Messages to the Handler in the activity.
Messenger provides also the method getBinder() which allows to pass a Messenger to the activity. The Activity can therefore send Messages to the service.
Thanks to http://www.vogella.com/articles/AndroidServices/article.html
Ways to connect Activity to service:
Broadcasts: easiest way, implement a BroadcastReciever in each to listen to actions of others.
Messengers: Very good for multiple types of clients, Both service and client have a Messenger , service provides it Messenger in onBind(), clients sends a register/unregister message with its own messenger in replyTo() of message. Service saves client messenger. Now both can send/recieve messages.
IBinder: If you need full fledged remote IPC . Define an Interface for service with AIDL and pass Implementations to clients in onBind().
Android online reference has explanations of each.
The guys are right, you should really google for answers!
However, I recently learned a neat way to send intents to a service. You can simply call startService(myIntent) to send an intent to your service. If the service is not running, it will be started. If the service is running, you have the possibility to react on the new information.
Related
I have never worked with services before, but I looked at many posts and tutorials and I never quite understood how this works.
So what I need is something (like a Service) that runs in the background independently of the apps lifecycle to receive and execute requests asynchronically.
In more detail I want this to be a download queue.
I planned on doing this by having a service started if the user requests a download. If another download is requested while the first isn't finished the service puts it into its queue. The service sends periodical messages so the UI gets updated. The user can also pause or cancel a download (so the activity has to have the ability to send messages to the service).
I know how to do the download stuff and I think I know how to start the Service, but I don't understand how to send messages to the service.
For messages to the Activity I would do something like this:
private void sendUpdateMessage(Bundle data) {
Intent intent = new Intent("DownloadUpdate");
intent.putExtra("data", data);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
For messages to the Service I guess there has to be some sort of binding (which I don't understand well). I found this Communication between Activity and Service or this https://developer.android.com/reference/android/app/Service.html#remote-messenger-service-sample, but this seems very complicated and I sadly do not understand it.
It would be nice if anyone had a simple explenation for how to communicate between Activity and Service.
(Again, I know there are post on this topic on Stackoverflow, but for some reason I do not understand how to do it properly)
I found a very helpful page with great examples:
Effective communication between Service and Activity
There are three possible ways:
Broadcasts and BroadcastReceivers
The simplest solution uses Broadcasts and BroadcastReceivers. However, this method has the following disadvantages:
The message sender does not know who will receive the data (it broadcasts the message).
Broadcasts consume a lot of bandwidth and are not suited for high traffic.
Binder
For Activities and Services used in one application the “Binder” solution is recommended. After binding with the service, the Binder will allow the activity (or other class bound to the service) to call any public method of the service.
Messenger
The recommended method of communication between Activities and Services for different applications’ Inter-Process Communication (IPC) is by using Messengers. In this case, the service defines a handler for different incoming messages. This handler is then used in Messenger for transferring data via messages.
To get bi-directional communication, the activity also has to register a Messenger and Handler. This Messenger is passed to the service in one of messages. Without this the service wouldn’t know to who it should respond.
For my project I chose the last one.
I have two problems:
I know that for connection activity and remote-service I have to use AIDL.
I tried this and it's work but I can find only one way connections example. In simple words - reading something from service (by activity). But I need solve for sending some data to activity (by or from service). It's so important because the service have to send some information to activity immediatly after some its events (obtain data from the net).
Is it way to bring to front again closed application (activity) from the remote service?
Any suggestions would be greatly appreciated.
Regards
Artik
It's so important because the service have to send some information to activity immediatly after some its events (obtain data from the net).
You can use AIDL for two-way communication. You would need to expose not only the service interface, but a callback interface, via AIDL, with the client having the .Stub of the callback and supplying an instance of it in a parameter to a method on the service interface. This gets a bit complex -- here are a pair of sample apps from my book that demonstrate the technique:
Service
Client
Is it way to bring to front again closed application (activity) from the remote service?
Your service can call startActivity(), but generally that is a bad idea. The user may be in the middle of doing something else, when all of a sudden your activity pops into the foreground. Occasionally, the user may deem your activity to be more important, but not always. Consider using a Notification instead, to let the user know that there is something in your app that needs the user's attention.
First, create a private resultreceiver variable in your service. Then create a method to set this resultreceiver via a connected activity. Then use AIDL to pass on a resultreceiver to the running service from the activity via the method you just made. Then in the service use resultreceiver.send if the resultreceiver is not null.
A few examples to get you started
http://lalit3686.blogspot.com/2012/06/how-to-update-activity-from-service.html?m=1
http://chrisrisner.com/31-Days-of-Android--Day-28–Intents-Part-3--Service-Intents
In my app I've designed it to have a Service that gets data constantly (for good reason, it's from some sensors) and provides it to two clients:
A UI Activity to display the live data
Another service that logs the data
At any time, both, one or neither of these clients may be running.
I think that this service should be a Bound service, whereas the logging service is a Started service.
The Android documentation for this says I should extend the Binder class, or use a Messenger if I want to access the service from another process.
This service, the logging service and the UI Activity will all be in the same apk, so they'll presumably be in the same process - but what is going to be the best solution here? I suspect the documentation might not be taking into account the possibility that I could have two clients in the same process as the service.
Thanks
The Android documentation clearly says
Extending the Binder class
If your service is private to your own application and runs in the same process as the client (which is common), you should create your interface by extending the Binder class and returning an instance of it from onBind(). The client receives the Binder and can use it to directly access public methods available in either the Binder implementation or even the Service.
This is the preferred technique when your service is merely a background worker for your own application. The only reason you would not create your interface this way is because your service is used by other applications or across separate processes.
Using a Messenger
If you need your interface to work across different processes, you can create an interface for the service with a Messenger. In this manner, the service defines a Handler that responds to different types of Message objects. This Handler is the basis for a Messenger that can then share an IBinder with the client, allowing the client to send commands to the service using Message objects. Additionally, the client can define a Messenger of its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the Messenger queues all requests into a single thread so that you don't have to design your service to be thread-safe.
So, the best option is to use a service by extending IBinder class when this service is a local service. When both services are created by using Messenger and AIDL, they are remote services.
imrankhan's preferred solution (Binder) did seem to work, but in the end I opted for a Messenger as in practise I found this solution more flexible and logical to code.
Common scenario - Activity with a background Service to poll server.
The Service will run periodically via AlarmManager and also perform tasks for the Activity (user hits a button, go fetch something from server).
I'd like to know the best practices here. I think the best design would be the Android LocalService example:
http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
However in the example the Activity has a reference to the activity mBoundService but there is no reverse connection (the Service has no way to call the Activity).
What is the best way for the Service to call the Activity?
Do I use Intents, BroadcastReceivers, Messages? How?
I think the best design would be the Android LocalService example: http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
I wouldn't. Use the loosest possible coupling you can stand. Hence, on average, aim for the command pattern with startService() instead of the binding pattern with bindService(). Notably, binding is a bit of a pain when it comes to dealing with configuration changes (e.g., screen rotations).
What is the best way for the Service to call the Activity? Do I use Intents, BroadcastReceivers, Messages? How?
See Notify activity from service
If you need tight coupling between your activity using bindService(), the way you communicate depends on who is originating the communication.
If the Service is originating (due to say an Alarm that has some new information to share), it would typically send a broadcast.
If the Activity is originating (due to say your example "go fetch something from server"), it could be handled asynchronously using AsyncTask or similar. That is, you could fetch from the server in the AsyncTask.doInBackground(), and post the results back to the activity in AsyncTask.onPostExecute. This scenario be a bit more complicated if the requested operation is expected to take a very long time - in which case I would de-couple it, and send a broadcast back from the Service instead.
As written here
When you want to communicate from service to an Activity or Fragment
which did NOT started the service or to communicate from service to multiple activities/fragments then you can use Event Bus or
Broadcast Intents since they can receive callback for an event in any
activity or fragment wherever they are implemented.If you want to
communicate from service to an activity/fragment which started the
service then you can use Pending Intent or Messenger as they can be
put into an Intent extra and passed to Service.
Pending Intent
We can use createPendingResult() which creates a new PendingIntent
object which you can hand to service to use and to send result data
back to your activity inside onActivityResult(int, int, Intent)
callback.
Event Bus
You can have the service raise events which activities or fragments
can listen for and respond to using Event Bus.
Messenger
Messenger is parcelable ,and can therefore be put into an Intent
extra,so your activity can pass this Messenger to the service.Service
will populate Message object with whatever data needs to be
send.
Broadcast Intents
Service can send a broadcast which can be responded by the activity.
I wanna create an notification application/service, which should be accessable from other applications similar to android's Notification and NotificationManger.
As i m a newbie to android development, i wanna know how to develop an service running in background n how to access it from other applications?
Check out the Service framework: android service
You may also be interested in the ContentProvider framework.
Android inter-process communication is very different from other platforms. Each process is separate from other processes. You can only send messages between processes.
If you want to invoke a method of a service from an activity, you can bind to it asynchronously (often in onCreate()) and after you're bound then you can call its methods directly. But this is only available in activities.
To call a service from another service or a Broadcast Listener, use startService() to send it messages, which can contain actions and extras (equivalent of methods and parameters).
Activities can register broadcast listeners, which also process actions and extras.
I hope this helps.