Android Aidl C++ Example

6 min read Jun 28, 2024
Android Aidl C++ Example

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

  1. Create a New Project: Start by creating a new Android Studio project. You can choose a basic "Empty Compose Activity" template.

  2. Create an AIDL Interface: Create a new file named MyInterface.aidl in your project's app/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.

  3. Create a C++ Service: Create a new C++ class in your project's app/src/main/cpp folder named MyService.cpp. This class will implement the IMyInterface 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);
    }
    
  4. Create Java Class for Service Binding: Create a new Java class named MyService.java in your project's app/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();
                }
            }
        }
    }
    
  5. 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)
    }
    
  6. Create CMake File: Create a CMakeLists.txt file in your project's app/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)
    
  7. Generate Native Code: Build the project. Android Studio will automatically generate the native code based on your CMakeLists.txt file.

Using the AIDL Service

  1. Bind to the Service: In your activity, you can bind to the service using an Intent and ServiceConnection.

    Intent intent = new Intent(this, MyService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    
  2. 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.

Latest Posts