Android 使用AIDL

用途:您可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信

详细讲解的博客

https://www.jianshu.com/p/c2fd499261a8

文档

https://developer.android.google.cn/guide/components/aidl?hl=zh_cn

如要使用 AIDL 创建绑定服务,请执行以下步骤:

    1. 创建 .aidl 文件

    此文件定义带有方法签名的编程接口。

    1. 实现接口

    Android SDK 工具会基于您的 .aidl 文件,使用 Java 编程语言生成接口。此接口拥有一个名为 Stub 的内部抽象类,用于扩展 Binder 类并实现 AIDL 接口中的方法。您必须扩展 Stub 类并实现这些方法。

    1. 向客户端公开接口

    实现 Service 并重写 onBind(),从而返回 Stub 类的实现。

1. 创建 .aidl 文件

AIDL 使用一种简单语法,允许您通过一个或多个方法(可接收参数和返回值)来声明接口。参数和返回值可为任意类型,甚至是 AIDL 生成的其他接口。

您必须使用 Java 编程语言构建 .aidl 文件。每个 .aidl 文件均须定义单个接口,并且只需要接口声明和方法签名。

interface IIotAidlInterface {
    /**
     * @param lockNum 锁号
     * @return result 开门状态 1正常
     */
    int openDoor(int lockNum);
}

2. 实现接口

当您构建应用时,Android SDK 工具会生成以 .aidl 文件命名的 .java 接口文件。生成的接口包含一个名为 Stub 的子类(例如,YourInterface.Stub),该子类是其父接口的抽象实现,并且会声明 .aidl 文件中的所有方法。

如要实现 .aidl 生成的接口,请扩展生成的 Binder 接口(例如,YourInterface.Stub),并实现继承自 .aidl 文件的方法。

以下示例展示使用匿名实例实现 IIotAidlInterface 接口(由以上 IIotAidlInterface.aidl 示例定义)的过程:

class IotService : Service() {

    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }

    //第二部实现接口
    private val binder = object :IIotAidlInterface.Stub(){
        override fun openDoor(lockNum: Int): Int {
            TODO("Not yet implemented")
        }
    }
}

3. 向客户端公开接口

在为服务实现接口后,您需要向客户端公开该接口,以便客户端进行绑定。如要为您的服务公开该接口,请扩展 Service 并实现 onBind(),从而返回实现生成的 Stub 的类实例(如前文所述)。以下是向客户端公开 IRemoteService 示例接口的服务示例。

class IotService : Service() {

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

    //第二部实现接口
    private val binder = object :IIotAidlInterface.Stub(){
        override fun openDoor(lockNum: Int): Int {
            TODO("Not yet implemented")
        }
    }
}

现在,当客户端(如 Activity)调用 bindService() 以连接此服务时,客户端的 onServiceConnected() 回调会接收服务的 onBind() 方法所返回的 binder 实例。

客户端还必须拥有接口类的访问权限,因此如果客户端和服务在不同应用内,则客户端应用的 src/ 目录内必须包含 .aidl 文件(该文件会生成 android.os.Binder 接口,进而为客户端提供 AIDL 方法的访问权限)的副本。

当客户端在 onServiceConnected() 回调中收到 IBinder 时,它必须调用 *YourServiceInterface*.Stub.asInterface(service),以将返回的参数转换成 *YourServiceInterface* 类型。例如:

客户端

在客户端添加同样的AIDL文件

1.创建AIDL文件

package com.tic.aidls;

// Declare any non-default types here with import statements

interface IIotAidlInterface {
    /**
     * @param lockNum 锁号
     * @return result 开门状态 1正常
     */
    int openDoor(int lockNum);

}

2.使用

package com.tic.aidlc

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.widget.Toast
import com.tic.aidls.IIotAidlInterface
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    var iotService: IIotAidlInterface? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initListener()
    }

    private fun initListener() {
        val intent = Intent("com.tic.aidls")
        intent.setPackage("com.tic.aidls")

        mBtn1.setOnClickListener {
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
        }
        mBtn2.setOnClickListener {
            unbindService(mConnection)
        }

        mBtn3.setOnClickListener {
            val openDoor = iotService?.openDoor(1)
            Toast.makeText(this, "OpenDoor:$openDoor", Toast.LENGTH_LONG).show()
        }
    }

    val mConnection = object : ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {
            iotService = null
        }

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            iotService = IIotAidlInterface.Stub.asInterface(service)
        }

    }
}

双向通信

aidl

// IInventoryCallback.aidl
package com.tic.aidls;

// Declare any non-default types here with import statements

interface IInventoryCallback {
    void onSuccess(String data);
    void onError(String message);
}

// IInventoryCallback.aidl
package com.tic.aidls;

// Declare any non-default types here with import statements

interface IInventoryCallback {
    void onSuccess(String data);
    void onError(String message);
}

服务端

class IotService : Service() {

    val mCallbacks: RemoteCallbackList = RemoteCallbackList()

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

    //第二部实现接口
    private val binder = object : IIotAidlInterface.Stub() {
        override fun openDoor(lockNum: Int): Int {
            return 1
        }

        override fun register(callback: IInventoryCallback?) {
            mCallbacks.register(callback)
        }

        override fun unRegister(callback: IInventoryCallback?) {
            mCallbacks.unregister(callback)
        }

        override fun send(data: String?) {
            val size = mCallbacks.beginBroadcast();
            try {
                for (i in 0 until size) {
                    mCallbacks.getBroadcastItem(i).onSuccess("盘点啊")
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            mCallbacks.finishBroadcast()
        }
    }
}

客户端

package com.tic.aidlc

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.widget.Toast
import com.tic.aidls.IInventoryCallback
import com.tic.aidls.IIotAidlInterface
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    var iotService: IIotAidlInterface? = null

    private var remoteCallback: IInventoryCallback.Stub? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initListener()
        initCallback()
    }

    private fun initCallback() {
        remoteCallback = object : IInventoryCallback.Stub() {
            override fun onSuccess(data: String?) {

            }

            override fun onError(message: String?) {

            }

        }
    }

    private fun initListener() {
        val intent = Intent("com.tic.aidls")
        intent.setPackage("com.tic.aidls")

        mBtn1.setOnClickListener {
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
        }

        mBtn2.setOnClickListener {
            unbindService(mConnection)
        }

        mBtn3.setOnClickListener {
            val openDoor = iotService?.openDoor(1)
            Toast.makeText(this, "OpenDoor:$openDoor", Toast.LENGTH_LONG).show()
        }
    }

    private val mConnection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            iotService = IIotAidlInterface.Stub.asInterface(service)
            try {
                iotService?.register(remoteCallback)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            iotService = null
            remoteCallback = null
        }

    }
}

你可能感兴趣的:(Android 使用AIDL)