Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is AIDL/Messenger bound to a Service?

Scenario: I have a Controller (normal Java class) that must be able to pilot several Slaves.

A Slave's nature can differ, so that it can either be:

  1. A Service, let's call it a ServiceSlave: the lifecycle of this object usually differs from the application's components (say, it does not depend on the current activity)
  2. A simple Java class, say a ObjectSlave: the lifecycle of this object is somewhat bound to the scope in which it is created (say, the current activity)

What these two types of Slaves have in common, is that they can reside in different processes.


Because of this last "requirement", I immediately turned my attention to AIDL/Messenger as the form of communication between a Controller and a Slave, since it provides IPC.

However, it seems that AIDL (and in turn Messenger, since it should be based on AIDL as well) has only been defined if you are to work with a Service. That is, there is no way for me to implement an AIDL-based interface without an IBinder object, which usually is provided in the onServiceConnected method.

FIRST QUESTION: can AIDL really be used only when dealing with a Service? If it is, why so?

Now, consider my scenario. I would like, as any other good developer would, to write a single, elegant interface that allows the Controller to pilot every Slave, regardless of their nature. The only solution that came to my mind so far involves using Intents and BroadcastReceivers, all conveniently wrapped in dedicated Java classes.

SECOND QUESTION: is this the only viable way? Am I overseeing something?


EDIT

I guess I should've given more details on what the Controller element actually does. It is a component that is loosely coupled with several UI widgets, who subscribe to it. It has been designed (willingly) so that it doesn't need a reference to a Context. So it doesn't need or use UI widgets directly, but in turn those widgets depend on the Controller.

like image 931
Sebastiano Avatar asked Jan 09 '15 16:01

Sebastiano


People also ask

What is the purpose of an AIDL file in terms of a bound service?

The Android Interface Definition Language (AIDL) is similar to other IDLs you might have worked with. It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC).

What is the difference between using Messenger and AIDL?

Based on my analysis, I think AIDL is the only option because Messenger provides a very generic way of sending messages across apps. The Messenger is limited to send(Message) on the client-side and handleMessage(Message msg) on the server. There are other differences too such as multi-threading.

What is bound service?

A bound service is the server in a client-server interface. It allows components (such as activities) to bind to the service, send requests, receive responses, and perform interprocess communication (IPC).


2 Answers

This is a good, but not a simple question to answer. Like most things, there are multiple approaches to take to solve this type of problem. The first thing to examine is whether or not your Controller needs or uses a UI component. If not, then you'll need to encapsulate it in a Service. Activity lifecycle is such that it will only be running when it is the current thing on screen. As soon as the user presses HOME or BACK it is either stopped or destroyed, respectively. Starting another app via notification or from within your app will have an effect similar to pressing HOME: your Activity will be paused.

So, assuming you don't need/want UI for your Controller, you have numerous things at your disposal:

  1. Make your service a "bound" service by exposing a custom AIDL interface. Not difficult, but not for the feint of heart either.
  2. Make your service respond to custom Intents to take some action. The Service could then fire back broadcasts or start a specific "slave" Activity. If interested in this, explore the use of the IntentService to better manage the threading and prevent ANR of your app.
  3. Similar to the previous, use a custom Intent and have your slave send a Messenger object it has created as an extra within the Intent. At that point the Service can send messages to the Messenger, which is owned by the slave Activity and will be delivered to a specific Handler.

You do not need a custom AIDL exposed interface for options 2 and 3. You are correct in that you must define an AIDL interface if you are going to use a bound service and your Service.onBind() method must return an instance of your binder interface stub implementation.

All of that being said, you could use any of the 3 approaches to meet your goal of working with slave classes which reside in either Activity or Service instances. The advantage of using the AIDL or Messenger approaches is a reduction in context switching (more efficient) since you're not sending Intent objects. Each time you send an Intent, the sender contacts the ActivityManagerService running in a system process to resolve where the Intent is to be delivered. With AIDL and Messenger, only the initial bindService() or startService() calls reach out to the ActivityManagerService. After that point the communication is performed using direct binders between the two processes.

like image 171
Larry Schiefer Avatar answered Oct 06 '22 01:10

Larry Schiefer


Turns out AIDL and Binder are not tied to Services.

While it is true that a IBinder reference is provided only when binding to a Service, the framework offers the Binder class, which already implements the IBinder interface.

Moreover, a Binder instance works transparently across processes and it is not required to live in a Service context.


[still elaborating, will provide a scheme on how the structure can be implemented by directly using a Binder instance]

like image 37
Sebastiano Avatar answered Oct 05 '22 23:10

Sebastiano