Android进程通信之AIDL的使用

AIDL

开发过程中,当我们需要需要和其他进程交互的情况时,就不得不使用到AIDL

AIDL中我们可以使用基础类型数据、String 、CharSequence、List或Map(注意List和Map 对象的元素必须是AIDL支持的数据类)以及自己定义并申明的数据类型(此数据需要实现parcelable)。

这里以自己定义的数据类型进行说明。

服务端实现

首先我们创建一个项目作为服务端(提供AIDL实现的项目)。

创建AIDL文件

  • 定义对应的需要在AIDL中使用的数据。
package com.duode.myjobinterview.aidl

import android.os.Parcel
import android.os.Parcelable

/**
 * @author duode
 * @des
 * @date 2020/7/15 10:53
 * */
data class AIDLData(var name: String, var flag: Int) : Parcelable {
    constructor(source: Parcel) : this(
        source.readString() ?: "",
        source.readInt()
    )

    override fun describeContents() = 0

    override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
        writeString(name)
        writeInt(flag)
    }

    companion object {
        @JvmField
        val CREATOR: Parcelable.Creator<AIDLData> = object : Parcelable.Creator<AIDLData> {
            override fun createFromParcel(source: Parcel): AIDLData =
                AIDLData(source)
            override fun newArray(size: Int): Array<AIDLData?> = arrayOfNulls(size)
        }
    }
}
  • 创建对应的AIDL文件申明此数据
// AIDLData.aidl
package com.duode.myjobinterview;

//申明需要在AIDL文件中使用的非常用类型;此文件的包名和数据类型的包名一定要一致
parcelable AIDLData;

可以使用AndroidStudio快速创建对应的AIDL文件。
aidl_create

  • 创建需要提供给外部调用的AIDL文件
// IDataInteractionAidlInterface.aidl
package com.duode.myjobinterview.aidl;

// 对非基础类型的数据需要进行导包;且注意此文件的包名和数据类型的包名一定要一致
import com.duode.myjobinterview.aidl.AIDLData;
interface IDataInteractionAidlInterface {
    void setData(in AIDLData data);

    AIDLData getData();
}

注意:做完这些需要构建一下项目,以生产对应的AIDL服务

实现对应的远程服务

  • 创建一个Service实现AIDL的具体调用
package com.duode.myjobinterview.servicer

import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.duode.myjobinterview.aidl.AIDLData
import com.duode.myjobinterview.aidl.IDataInteractionAidlInterface

/**
 * @author duode
 * @des
 * @date 2020/7/15 11:01
 * */
class AIDLService : Service() {

    private var mData: AIDLData? = null

    val mIBinder = object : IDataInteractionAidlInterface.Stub() {
        override fun getData(): AIDLData {
            return mData ?: AIDLData("AIDLService", -1)
        }

        override fun setData(data: AIDLData?) {
            mData = data
        }

    }

    override fun onBind(p0: Intent?): IBinder? {
        return mIBinder
    }


    override fun onCreate() {
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
    }
}
  • 申明远程服务
  <!--申明aidl服务,设置可以被外部调用,设置单独使用独立的进程-->
        <service
            android:name=".servicer.AIDLService"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <!--申明可以被外部调用的action-->
                <action android:name="com.duode.myjobinterview.servicer.AIDLService" />
            </intent-filter>
        </service>

客户端实现

创建需要调用远程服务的项目。

复制对应的AIDL数据到指定位置

这里的包名需要保持一致
client_aidl_data

复制对应的AIDL文件到指定位置

这里的包名需要保持一致
client_aidl

注意:完成以上操作之后,需要进行编译项目以生成对应的文件。

实现服务绑定

package com.duode.client

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.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.duode.myjobinterview.aidl.AIDLData
import com.duode.myjobinterview.aidl.IDataInteractionAidlInterface
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    companion object {
        val AIDL_ACTION = "com.duode.myjobinterview.servicer.AIDLService"
        val AIDL_PKG = "com.duode.myjobinterview"
    }

    private var mAIDLInterface: IDataInteractionAidlInterface? = null
    private val mServiceConnection = object : ServiceConnection {

        override fun onServiceDisconnected(p0: ComponentName?) {//服务被异常销毁时回调,如内存不足
            btn.text = "Connect"
        }

        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            btn.text = "Disconnected"
            mAIDLInterface = IDataInteractionAidlInterface.Stub.asInterface(p1)

            val data = mAIDLInterface?.data
            Log.d("Servicer", "$data")

            mAIDLInterface?.setData(AIDLData("Client", 1))
            Log.d("Client", "${mAIDLInterface?.data}")

        }
    }

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

        btn.setOnClickListener {
            if (btn.text == "Connect") {
                val intent = Intent()
                intent.setPackage(AIDL_PKG)
                intent.action = AIDL_ACTION
                bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE)

            } else {
                unbindService(mServiceConnection)
                btn.text = "Connect"
            }
        }
    }

    override fun onDestroy() {
        unbindService(mServiceConnection)
        super.onDestroy()
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值