Android AIDL C++ Example
This article will guide you through creating a simple Android application using AIDL (Android Interface Definition Language) with C++ for inter-process communication (IPC).
What is AIDL?
AIDL is a powerful tool for enabling communication between different Android processes. It allows you to define interfaces that can be used to exchange data and methods across process boundaries.
Setting up the Project
-
Create a New Project: Start by creating a new Android Studio project. You can choose a basic "Empty Compose Activity" template.
-
Create an AIDL Interface: Create a new file named
MyInterface.aidl
in your project'sapp/src/main/aidl
folder. This file defines the interface for your inter-process communication.package com.example.aidlcpp; interface IMyInterface { int add(int num1, int num2); }
This interface defines a simple method called
add
that takes two integers as input and returns their sum. -
Create a C++ Service: Create a new C++ class in your project's
app/src/main/cpp
folder namedMyService.cpp
. This class will implement theIMyInterface
interface.#include
#include #include "MyInterface.h" class MyService : public ::ndk::ScopedAIBinder, public IMyInterface { public: MyService() {} int add(int num1, int num2) override { return num1 + num2; } static void registerService(JNIEnv* env, jobject thiz) { // Register the service with the binder process. AIBinder_ProcessState* processState = AIBinder_ProcessState_getInstance(); AIBinder* binder = AIBinder_new(static_cast (thiz)); AIBinder_ProcessState_addStrongRef(processState, binder); } static void unregisterService(JNIEnv* env, jobject thiz) { // Unregister the service from the binder process. AIBinder_ProcessState* processState = AIBinder_ProcessState_getInstance(); AIBinder* binder = AIBinder_new(static_cast (thiz)); AIBinder_ProcessState_removeStrongRef(processState, binder); } }; // JNI functions to register and unregister the service. extern "C" JNIEXPORT void JNICALL Java_com_example_aidlcpp_MyService_registerService(JNIEnv* env, jobject thiz) { MyService::registerService(env, thiz); } extern "C" JNIEXPORT void JNICALL Java_com_example_aidlcpp_MyService_unregisterService(JNIEnv* env, jobject thiz) { MyService::unregisterService(env, thiz); } -
Create Java Class for Service Binding: Create a new Java class named
MyService.java
in your project'sapp/src/main/java
folder. This class will handle binding to the C++ service.package com.example.aidlcpp; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; public class MyService extends Service { private IMyInterface mInterface; @Override public IBinder onBind(Intent intent) { // Create and return the binder object. return new IMyInterface.Stub() { @Override public int add(int num1, int num2) throws RemoteException { return mInterface.add(num1, num2); } }; } @Override public void onCreate() { super.onCreate(); // Initialize the C++ service. mInterface = IMyInterface.Stub.asInterface(new MyServiceNative(this)); } @Override public void onDestroy() { super.onDestroy(); // Uninitialize the C++ service. mInterface = null; } // JNI wrapper class for the C++ service. private class MyServiceNative { public MyServiceNative(MyService service) { try { System.loadLibrary("native-lib"); // Register the C++ service. Class.forName("com.example.aidlcpp.MyService").getMethod("registerService", Object.class).invoke(null, service); } catch (Exception e) { e.printStackTrace(); } } } }
-
Define Native Interface: Add a native interface declaration in
MyService.java
:package com.example.aidlcpp; public class MyService { // ... (other code) public native void registerService(Object thiz); public native void unregisterService(Object thiz); // ... (other code) }
-
Create CMake File: Create a
CMakeLists.txt
file in your project'sapp/src/main/cpp
folder. This file will define the build rules for your C++ code.cmake_minimum_required(VERSION 3.10.2) add_library(native-lib SHARED MyService.cpp) find_package(android-ndk REQUIRED) find_library(log android::log) target_link_libraries(native-lib ${log}) # Include AIDL generated headers include_directories(${CMAKE_SOURCE_DIR}/../aidl/com/example/aidlcpp)
-
Generate Native Code: Build the project. Android Studio will automatically generate the native code based on your
CMakeLists.txt
file.
Using the AIDL Service
-
Bind to the Service: In your activity, you can bind to the service using an
Intent
andServiceConnection
.Intent intent = new Intent(this, MyService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
-
Call the Interface Method: After binding to the service, you can access the
IMyInterface
object and call its methods.int result = mInterface.add(5, 3);
Conclusion
This example demonstrates the basic steps involved in using AIDL with C++ to implement inter-process communication in Android. You can expand this example to create more complex services and interfaces as needed.