Android IPC Mechanisms #1 — AIDL

You should use this method if you need a multithreaded IPC structure. If you are not going to perform concurrent operations, you can choose Messenger instead of AIDL.
In this method, an application calls the method in another application on the same device, namely RPC (Remote Procedure Call). Since these methods can be called from many different processes/threads simultaneously, we need to take care that the mechanism we will handle calls is thread-safe.
So what is AIDL?
If you are familiar with the concept of IPC, you consider AIDL as Android-IDL (Interface Definition Language). This method is known as AIDL because the interface where the applications/processes shake hands for the communication to be established is created in the AIDL language. AIDL is a language that has Java syntax.
Let’s begin!
Let’s create two applications that can communicate with each other. In the rest of the article, I will refer to these applications as server and client for simplicity. You can access the source codes of the applications from the link at the end of the article.
Let’s code a scenario that includes the following functionalities:
- The client gets the server’s PID and how many connection requests have been received to the server.
- The client gets the count of how many connection requests have been received to the server.
- The client sends information of self such as its PID and package name to the server application. The server displays them as the last connected client info on the UI.
It will look like this when the sample is finished:
In this method, communication is based on Binder architecture. Calling bindService is a way to start a service. A component within the application or the remote process can bind to the service. A binder object is returned to the component(activity, service) that is bind. We will not go further into the details of the Bound Service concept as it is not the subject of this article.
In this example, the client will bind to the service of the server application. Thus the client can access the methods defined in the server application.
Let’s Create the Server Application
First, let’s create a new project. I named it IPCServer.
Create an AIDL file
We create our AIDL file containing the methods to be called from the client by right-clicking on the project explorer section on the left and following the path
New-> AIDL-> AIDL File
When we create it in this way, our file will automatically be created in the same directory as java and res, in the aidl folder. For example in this project, in src/main/aidl/com/pmirkelam/ipcserver/directory.

Modify the AIDL file
Now, let’s modify this file. We will add our own methods instead of the basicTypes method.
getPid: Get the process ID of the server application
getConnectionCount: Get the information about how many times the server application has received a client connection request during its life-cycle.
setDisplayedValue: The client set some information about itself to the server such as package name, PID, and arbitrary text. The server will display this information on its GUI.
There are some restrictions for the parameters and return types that AIDL methods take. You can find below all the types that can be used as parameters and return values. If we want to use a class that we have defined, it needs to be parcelable so that parsed to a level that the operating system can understand.
- All primitive types in the Java programming language (such as
int
,long
,char
,boolean
, and so on) - Arrays of primitive types such as
int[]
String
CharSequence
List
: All elements in theList
must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. AList
may optionally be used as a parameterized type class (for example,List<String>
). The actual concrete class that the other side receives is always anArrayList
, although the method is generated to use theList
interface.Map
: All elements in theMap
must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. Parameterized type maps, (such as those of the formMap<String,Integer>
) are not supported. The actual concrete class that the other side receives is always aHashMap
, although the method is generated to use theMap
interface. Consider using aBundle
as an alternative toMap
.
in, out, and inout prefixes
All non-primitive parameters require a directional tag indicating which way the data goes. Either in
, out
or inout.
In AIDL, the
out
tag specifies an output-only parameter. In other words, it's a parameter that contains no interesting data on input, but will be filled with data during the method.For example, a method that copies an array of bytes might be specified like this:
void copyArray(in byte[] source, out byte[] dest);
The
inout
tag indicates that the parameter has meaning on both input and output. For example:
void charsToUpper(inout char[] chars);
This is important because the contents of every parameter must be marshalled (serialized, transmitted, received, and deserialized). The in/out tags allow the Binder to skip the marshalling step for better performance.
Thanks to Gladed for this explanation.
Generate Stub
After creating our AIDL file, perform the steps to build project:
Build -> Rebuild Project
Then we see that a file with the same name but with a .java extension is automatically generated. This is an interface that has an abstract subclass called Stub, which implements the methods we have defined. In the service of the server, we will extend our binder object from the Stub class.

Define data classes
- Create Client data class
- Create a singleton RecentClient class where we will keep the last connected client. A list of connected clients could also be kept here, but in this example, we will only show the details of the last connected client on the UI.
Create a service.
- Create our binder object by extending from the Stub class. Here we fill the methods.
- Return our binder object to the client with bind.
- Update our RecentClient object when the client bind and unbind so the UI is updated.
Note: If you are going to perform concurrent operations, Coroutines can be used in the methods of the binder object.
Define service on Manifest
- Do not forget to add an intent filter to our service in Manifest. This way, the service will be marked as exported by default. The “exported” expression means that the service can be accessed from other processes.
- We will use the action name we have given here in the client application also.
Create an XML file for Activity
String resource file
Use ViewBinding
For code simplicity, we can choose to use the ViewBinding library. Let’s declare that we will use it.
Modify the Activity
- Now we can update Activity according to client info
- The last connected client will be displayed. The layout will be hidden if there is no connected client.
We have completed the server application!

Let’s Create the Client Application
First, create a new project. I named it IPCServer.
In the rest of the article, we will use the same application for other IPC methods (Broadcast, Messenger). For this reason, while creating the project, let’s choose Bottom Navigation Activity from the activity gallery. With AIDL, Messenger and Broadcast options.

Copy-paste the AIDL file
After opening the project, we need to add exactly the same AIDL file that we created in the server application, then build again. We can create the file again by following the path
New-> AIDL-> AIDL File.
The point to note here is that the directory where the file is located is the same in both applications. When we create the file with the help of IDE, it will automatically be created under the directory src/main/aidl/com/pmirkelam/ipcclient/ and we need to update it to
src/main/aidl/com/pmirkelam/ipcserver/.

- Copy file content, including the same package name
Set UI related things
- Edit the menu file in the/res/menu/ directory
- Edit the navigation file in the /res/navigation/ directory
- Edit the string resource file
- Change the colors in the theme to make it look different from the server
- Do not make changes in the Activity XML file
- Let’s configure navigation and binding in Activity
Create a fragment
- Create the fragment XML file
- Create the connect-disconnect button.
- Add a hidden layout that will appear when the connection is established. In this layout. The layout includes the information received from the server application.
Put bussiness logic on Fragment
- Do the view binding stuff in Fragment
- Bind to the server service when the Connect button is pressed
- If the service has not yet been created while bind, we add the BIND_AUTO_CREATE flag for automatic creation.
- Let’s listen for connection situations by implementing the ServiceConnection interface.
- When the connection is established, let’s send the message, packet name and PID. Then print the responses on GUI.
- When the connection is broken, we leave behind clean by unBind to the service. When the operating system needs memory, it can kill background services in applications that have not user interaction for a while. In Bound Services, as long as there is at least one bound client, background services are not killed, except in extreme cases. In order not to cause waste of resources, let’s not stay bound to the service even though we do not use it.
We have completed our client application! When calling methods on the server, the flow in the graphical interface will be like this:

In this example, only the client can send a message to the server. So what can we do when the server needs to send a message to the client?
- For example, the client called a long-running-blocking method of the server, and when the process is finished the server must return a callback to the client.
- It is possible to implement this mechanism by giving another AIDL as a parameter to the AIDL method, as in the example below.
- AIDL works synchronously by default. The oneway keyword is a prefix that should be added in asynchronous usage as follows.
However, if you need such an asynchronous structure and you are not going to do concurrent operations, using Messenger method instead of AIDL would be a more meaningful solution.
In Messenger, you can establish two-way communication and return a callback to the client without making such an effort.
You can access the next article includes Messenger technique here.
Other parts of the series:
References:
- developer.android.com/training/articles/security-tips#IPC
- developer.android.com/guide/components/aidl
- Deep Dive into Android IPC / Binder Framework at Android Builders Summit
- dev.to/xuhaibahmad/inter-process-communication-in-android-lessons-learnings-1p6n
- budhdisharma.medium.com/aidl-and-its-uses-in-android-e7a2520093e