Android uses AIDL for cross-process communication in android studio

When I write this article, I don’t want to start with the most basic introduction. I’ll go directly to the steps.

1. Create a server

1.1: Create a server-side project: My as version is relatively high, and the page looks like this

1.2: Create AIDL file, right-click the project and select aidl

The aidl name can be customized or defaulted.

BasicTypes comes with it, you can delete it or not delete it, and then write the interface you need

1.3: Create a service called by aidl:

1.4: Generate java files based on aidl for service calls: click Rebuild Project and wait for completion

This is the generated java file

1.5: Edit service and implement the aidl interface: If java is not generated, IReceiverAidl will not be found

package com.howfor.receiver

import android.app.Service
import android.content.Intent
import android.graphics.Bitmap
import android.os.IBinder
import android.util.Log


class MyService : Service() {

    var catBinder = object: IReceiverAidl.Stub() {
        override fun basicTypes(
            anInt: Int,
            aLong: Long,
            aBoolean: Boolean,
            aFloat: Float,
            aDouble: Double,
            aString: String?
        ) {
            Log.e("TAG","basicTypessetTime===========anInt")
        }

        override fun setTime(time: Long) {
            Log.e("TAG","setTime===========$time")
        }

        override fun reboot() {
            Log.e("TAG","reboot===========")
        }

        override fun shutdown() {
            Log.e("TAG","shutdown===========")
        }

        override fun install(fullPath: String?) {
            Log.e("TAG","install===========$fullPath")
        }

        override fun beat(aBoolean: Boolean) {
            Log.e("TAG","beat===========$aBoolean")
        }

        override fun setPower(power: MutableList<String>?) {
            Log.e("TAG","setPower===========${power!!.size}")
        }

        override fun updateFirmware(localFile: String?) {
            Log.e("TAG","updateFirmware===========${localFile}")
        }

        override fun getDeviceId(): String {
            Log.e("TAG","getDeviceId===========")
            return ""
        }

        override fun getName(): Array<String> {
            Log.e("TAG","getName()===========")
            val arrayEmpty = emptyArray<String>()
            return arrayEmpty
        }

        override fun getPath(): Array<String> {
            Log.e("TAG","getPath()===========")
            val arrayEmpty = emptyArray<String>()
            return arrayEmpty
        }

        override fun shouldClean(path: String?): Boolean {
            Log.e("TAG","shouldClean()===========")
            return true
        }

        override fun getBitmap(): Bitmap {
            Log.e("TAG","getBitmap()===========")
            var bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
            return bitmap
        }

        override fun getVersion(): String {
            Log.e("TAG","getVersion()===========")
            return ""
        }
    }


    override fun onBind(intent: Intent): IBinder {
        return catBinder
    }
}

1.6: Set the attributes of the service: name will be used in client binding, so we will customize one first, and there is no need to follow your Myservice

 <service
            android:name=".MyService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.howfor.receiver.service.ReceiverService" />
            </intent-filter>
        </service>

2. Client use:

2.1: Create client project

2.2: Copy the aidl of the server to the client: it must be exactly the same, it is recommended to copy and paste directly

2.3: Generate java files, the same steps as server 1.4:

2.4: Use aidl and bind the service of the server: com.howfor.receiver.service.ReceiverService here is the attribute set in 1.6, and the package name is the package name of the server:

package com.example.aidlkhute

import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

import com.howfor.receiver.IReceiverAidl

class MainActivity : AppCompatActivity() {

    var mIReceiverAidl: IReceiverAidl? = null

    var mConnections = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.e("TAG", "onServiceConnected")
            //Note 3:
            mIReceiverAidl = IReceiverAidl.Stub.asInterface(service)
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.e("TAG", "onServiceDisconnected")
             mIReceiverAidl = null
        }
    }

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val intent = Intent()
        intent.setPackage("com.howfor.receiver")
        intent.action = "com.howfor.receiver.service.ReceiverService"
        try {
            var se = bindService(intent, mConnections, Context.BIND_AUTO_CREATE)
            Log.e("TAG", "se=========$se")
        } catch (e: RemoteException) {
            Log.e("TAG", "e=========${e.message}")
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        unbindService(mConnections)
    }
}

Add two buttons using the interface inside

findViewById<Button>(R.id.test).setOnClickListener {
            if (mIReceiverAidl != null) {
                try {
                    mIReceiverAidl!!.reboot()
                } catch (e: RemoteException) {
                    Log.e("TAG", "e=========${e.message}")
                }
            } else {
                Log.e("TAG", "mIReceiverAidl====null")
            }
        }

        findViewById<Button>(R.id.test1).setOnClickListener {
            if (mIReceiverAidl != null) {
                try {
                    mIReceiverAidl!!.shutdown()
                } catch (e: RemoteException) {
                    Log.e("TAG", "e=========${e.message}")
                }
            } else {
                Log.e("TAG", "mIReceiverAidl====null")
            }
        }

Run the server first, you don’t need to do anything, then run the client, click the corresponding interface, and the corresponding log will be printed:

se==========true //Indicates that the service binding is successful
reboot=========== //Click the first button to print
shutdown============ //Click the second button to print

There is also a small problem: binding failure will occur on higher versions (targetSdk 33). Then I checked it and found that on Android 11 and above, Google has done some operations on the system. You can find the details on Baidu: Solution, at The client can add the content in the red box