Android 使用AIDL

用途:您可以利用它定義客戶端與服務(wù)均認(rèn)可的編程接口,以便二者使用進(jìn)程間通信 (IPC) 進(jìn)行相互通信

詳細(xì)講解的博客

http://www.itdecent.cn/p/c2fd499261a8

文檔

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

如要使用 AIDL 創(chuàng)建綁定服務(wù),請執(zhí)行以下步驟:

    1. 創(chuàng)建 .aidl 文件

    此文件定義帶有方法簽名的編程接口。

    1. 實現(xiàn)接口

    Android SDK 工具會基于您的 .aidl 文件,使用 Java 編程語言生成接口。此接口擁有一個名為 Stub 的內(nèi)部抽象類,用于擴(kuò)展 Binder 類并實現(xiàn) AIDL 接口中的方法。您必須擴(kuò)展 Stub 類并實現(xiàn)這些方法。

    1. 向客戶端公開接口

    實現(xiàn) Service 并重寫 onBind(),從而返回 Stub 類的實現(xiàn)。

1. 創(chuàng)建 .aidl 文件

AIDL 使用一種簡單語法,允許您通過一個或多個方法(可接收參數(shù)和返回值)來聲明接口。參數(shù)和返回值可為任意類型,甚至是 AIDL 生成的其他接口。

您必須使用 Java 編程語言構(gòu)建 .aidl 文件。每個 .aidl 文件均須定義單個接口,并且只需要接口聲明和方法簽名。

interface IIotAidlInterface {
    /**
     * @param lockNum 鎖號
     * @return result 開門狀態(tài) 1正常
     */
    int openDoor(int lockNum);
}

2. 實現(xiàn)接口

當(dāng)您構(gòu)建應(yīng)用時,Android SDK 工具會生成以 .aidl 文件命名的 .java 接口文件。生成的接口包含一個名為 Stub 的子類(例如,YourInterface.Stub),該子類是其父接口的抽象實現(xiàn),并且會聲明 .aidl 文件中的所有方法。

如要實現(xiàn) .aidl 生成的接口,請擴(kuò)展生成的 Binder 接口(例如,YourInterface.Stub),并實現(xiàn)繼承自 .aidl 文件的方法。

以下示例展示使用匿名實例實現(xiàn) IIotAidlInterface 接口(由以上 IIotAidlInterface.aidl 示例定義)的過程:

class IotService : Service() {

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

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

3. 向客戶端公開接口

在為服務(wù)實現(xiàn)接口后,您需要向客戶端公開該接口,以便客戶端進(jìn)行綁定。如要為您的服務(wù)公開該接口,請擴(kuò)展 Service 并實現(xiàn) onBind(),從而返回實現(xiàn)生成的 Stub 的類實例(如前文所述)。以下是向客戶端公開 IRemoteService 示例接口的服務(wù)示例。

class IotService : Service() {

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

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

現(xiàn)在,當(dāng)客戶端(如 Activity)調(diào)用 bindService() 以連接此服務(wù)時,客戶端的 onServiceConnected() 回調(diào)會接收服務(wù)的 onBind() 方法所返回的 binder 實例。

客戶端還必須擁有接口類的訪問權(quán)限,因此如果客戶端和服務(wù)在不同應(yīng)用內(nèi),則客戶端應(yīng)用的 src/ 目錄內(nèi)必須包含 .aidl 文件(該文件會生成 android.os.Binder 接口,進(jìn)而為客戶端提供 AIDL 方法的訪問權(quán)限)的副本。

當(dāng)客戶端在 onServiceConnected() 回調(diào)中收到 IBinder 時,它必須調(diào)用 *YourServiceInterface*.Stub.asInterface(service),以將返回的參數(shù)轉(zhuǎn)換成 *YourServiceInterface* 類型。例如:

客戶端

在客戶端添加同樣的AIDL文件

1.創(chuàng)建AIDL文件

package com.tic.aidls;

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

interface IIotAidlInterface {
    /**
     * @param lockNum 鎖號
     * @return result 開門狀態(tài) 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);
}

服務(wù)端

class IotService : Service() {

    val mCallbacks: RemoteCallbackList<IInventoryCallback> = RemoteCallbackList()

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

    //第二部實現(xiàn)接口
    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
        }

    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容