Binder
Introduction
what is it
[1]Binder is an Android-specific interprocess communication mechanism, and remote method invocation system. It is one of the kernel modules of Android.
[2] IBinder is the base interface for a remotable object, the core part of a lightweight RPC (remote procedure call) mechanism designed for high performance when performing in-process and cross-process calls.
Shortly, Android offer an unique IPC mechanism which is Binder, Ibinder is the interface describes the abstract protocol for interacting with a remotable object.
Ibinder organization
[3] The following figure shows the Java layer of the Binder framework which contains main classes and their dependencies
Ibinder and Parcelable
[4] Parcel is a container for a message (data and object references) that can be sent through an IBinder.
[5] Parcelable is the Interface for classes whose instances can be written to and restored from a Parcel.
That means any class implements Parcelable can be passed through Ibinder, for example Intent.
Usability patterns
Implement IBinder allows you to perform in-process and cross-process calls.
Ibinder and inter process
The most flexible way to implement IBinder is using AIDL (Android Interface Definition Language).
AIDL generates code that takes care of writing the values into the parcels (marshalling) , sending them via Binder IPC, receiving them, reading the values (unmarshalling) and calling the methods of service and writing and sending the result back.
It is widely used in Android SDK, but it should be used carefully. [6] 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.
Here is an example how to use AIDL pass callback to activity
- define an AIDL file
1 | interface ICallback { |
\2. create a custom object class that supports the Parcelable which will be used for communication
- Make your class implement the Parcelable interface.
- Implement writeToParcel, which takes the current state of the object and writes it to a Parcel.
- Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface.
1 | public class CallBack implements Parcelable { |
\3. start activity and pass this callback through intent
1 | Callback callback = new CallBack(new ICallBack.Stub(){ |
Ibinder inside of service
Using Bound Service is the most common situation you need to implement Ibinder.
[7] Bound Service allows components (such as activities) to bind to the service, send requests, receive responses, and perform interprocess communication (IPC).
To provide binding for a service, you must implement the onBind() callback method. This method returns an IBinder object that defines the programming interface that clients can use to interact with the service.
According to different situations, you can choose different ways to implement this interface.
- 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().
- If you need your interface to work across different processes, you can create an interface for the service with a Messenger. (which is based on AIDL)
- If you want your service to handle multiple requests simultaneously, then you can use AIDL directly. In this case, your service must be thread-safe and capable of multi-threading.
Here is an example how to use bound service and extend binder to pass callback to activity
- create a custom service and define a binder which helps you get its instance
1 | public class CustomService extends Service { |
\2. implemen ServiceConnection and the onServiceConnected() callback.
1 | private ServiceConnection connection = new ServiceConnection() { |
\3. bind this service in your client (activity or ApplicationContext etc)
1 | final Intent intent = new Intent(context, CustomService.class); |
\4. you can use the same way to bind another client to this service and pass callback to this new client.
ResultReceiver Ibinder as simplified
If you just want to receive a callback result you can use ResultReceiver.
[8] ResultReceiver is a generic interface for receiving a callback result from someone. Use this by creating a subclass and implement onReceiveResult(int, Bundle), which you can then pass to others and send through IPC, and receive results they supply with send(int, Bundle).
It is also implemented by wrapping around Binder
Here is an example how to use ResultReceiver to receive a callback result, no need to pass callback to activity
- implement a ResultReceiver and its onReceiveResult callback and pass it by intent
1 | intent.putExtra(RESULT_RECEIVER, new ResultReceiver(null) { |
\2. in activity get this resultReceiver and call its send method
1 | resultReceiver = intent.getParcelableExtra(RESULT_RECEIVER); |
Conclusion
Binder is Android IPC mechanism, it has a low level implementation, work as an important module in Android.
Android provides IBinder interface and Binder class as high level abstraction.
If you want to perform custom in-process call, you just need to implement IBinder interface.
If you want to define custom programming interface to realize your own IPC logic, you need to implement IBinder interface or extend Binder class and work with service.
For some simple situations, like receive a callback result, you can choose resultReceiver class which has already wrapped around a Binder.
Messenger(Ibinder) as callback channel
You can use Messenger with service like AIDL. Little difference is you need to implement a handler to handle message callback
- server side
1 | public class MessengerService extends Service { |
- client side
Since messenger impements Parcelable and also provides implementation for Ibinder, you can also use it similar to ResultReceiver without service.
References
[1] https://elinux.org/Android_Binder
[2] https://developer.android.com/reference/android/os/IBinder
[3] https://www.nds.ruhr-uni-bochum.de/media/attachments/files/2012/03/binder.pdf
[4] https://developer.android.com/reference/android/os/Parcel
[5] https://developer.android.com/reference/android/os/Parcelable
[6] https://developer.android.com/guide/components/aidl
[7] https://developer.android.com/guide/components/bound-services
[8] https://developer.android.com/reference/android/os/ResultReceiver
http://gityuan.com/2015/11/28/binder-summary/
https://www.jianshu.com/p/2e6936e2de3d