I have two services A and B. If we want to access some methods of service B in service A we have to create a ServiceConnection class and inside service A we have to create Stub and implements the methods.
But I also want to access the methods of service A from service B. For trial I created one more aidl connection and implemented ServiceConnection it works fine, is it the only way OR we can use the existing serviceconnection and implement this functionality by other way?
I would assume this is the only way AIDL works from my experience. You could always create a custom callback that could be passed into service B from service A, then when B would like to send back to A it could trigger the callback. There is also the option of passing intents back and forth or communication through a socket. Just make sure you are blocking on the other side.
Services can certainly have callback interfaces (i.e. so services can call methods in clients).
Suggest you refer to the RemoteService example in the SDK.
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 have a service that communicates through AIDL with other services. I want that service to be bound by activities in my application. Can the service define two binders\interfaces? I've tried yo use a messenger for communicating with the activities, overriding "onBind" method so that it returns a different binder according to the intent it gets (one for the other services and one for the activities).
But when the activities (that use the same binder) unbind from the service, I have an error "myService has leaked ServiceConnection ... that was originally bound here", which I believe is about the binder the service use to communicate with the other services.
If a service cant use two interfaces, how can I implement the communication between the activities and that service?
thank you,
-Liron
If by
"overriding "onBind" method so that it returns a different binder
according to the intent it gets "
You mean, that you set an extra to your Intent, indicating what to do it won't work.
According to the Docs in onBind(Intent):
Intent: The Intent that was used to bind to this service, as given to
Context.bindService. Note that any extras that were included with the
Intent at that point will not be seen here.
Try to give your intent a custom action and check if that works
AIDL and Messenger are used for IPC with other applications/processes. From the Android API Guide:
Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.
If your activities are in the same process as the service, you just need to extend Binder.
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.
This graphic regarding the bound service lifecycle may help with how you are binding/unbinding (http://developer.android.com/guide/components/bound-services.html#Lifecycle):
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
Right now the main Activity (Act. A) starts a Service which holds the Bluetooth Connection.
(It binds the Service)
The Service is a modified version of BluetoothChatService (Android BluetoothChat Sample)...
... modified with an added Messenger and Handler in accordance with MessengerService (Android Remote Messenger Sample)
Activity A makes sure that the Bluetooth is connected to an external device, and later starts another activity (Act. B).
The problem is to get the Service to keep running and serve the Bluetooth Connection to the new activity smoothly. I don't know how to:
Make sure that the Service is not restarted or reinstanced, when it switches from activity A to B
Make sure that the messenging functionality works as desired (from the currently active activity)
Do I need to rebind the Service to the new activity, and how do I assure that the BT connection is not lost (due to other instance of Service)?
Or do i need to pass along the Messenger object to the new activity to communicate with the alread instantiated Service. If so, how do I do that best?
Very thankful for answers!
Make the service "sticky" so that it will continue to run. And create a base Activity class for your 2 activities. The base Activity class can handle all the common functionality of binding with the service and providing the proper communication. I would definitely recommend unbinding your service when the activities pause and re binding them in the activities when they resume. But this can be done once in the common base class activity.
Binding to the service should only start it if it is not already running and if you bind/unbind in Resume/Pause you should have only one active connection to the service at any given time.
You either subclass Application and store information in there (see here), or you could make your "service" a singleton, so it has a static member of its own type that you initialize only if it's null.
This is an old question, but I ran across this situation today and came up with a solution that works based on the other responses. Since I couldn't find a working implementation, I will post it up for others who may be curious. I created a "sticky service" and then a ServiceManager class that is responsible for managing the life-cycle and binding for the Service. Then I put the ServiceManager class into a sub-class of Application so the Activities can access it as a scoped global. It works well. Source is available on GitHub.
I have a situation which I will try to explain clearly. I have two services, Service A and Service B.
Activity C connects to service A using onBind(). Service A connectes to Service B using a callback object. I want Service A's onbind to not be executed until Service B is connected to Service A. What will be a good way to achieve this?
The right answer is: combine the two services into one.
The next-best answer is: redesign your app such that A is not binding to B, or that C does not care whether A is bound to B.
You can't delay the call from the onBind. If your service's interaction is such that it may not be ready for use until later, you could have a method on the interface returned by onBind that allows a client to get a callback when it is ready. (You could even have this set up where the main interface is just "getRealInterface" that takes a callback, which is given the real interface for your service once you are ready to give it.)