跨进程通信AIDL使用

1.Messenger

1.1 定义

通过Messenger在不同进程中传递Message对象,在Message中放入需要传递的数据。底层实现是AIDL

构造方法

public Messenger (Handler target){
    mTarget = target.getMessenger();
}
public Messenger (IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

Messenger对AIDL进行了封装,并且一次只处理一个请求,不需要考虑线程同步问题。

1.2 实现步骤
  1. 服务端进程

    创建一个Service来处理客户端连接请求,同时创建Handler并通过他来创建Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder。

  2. 客户端进程

    首先绑定服务端的Service,绑定成功后使用服务端返回的IBinder对象创建一个Messenger对象,通过它向服务端发送Message消息。如果需要服务端能够回复客户端,则需要创建一个Handler并创建新的Messenger,并把这个Messenger对象通过Message的replyTo传递给服务端。服务端通过这个replayTo参数回应客户端。

1.3 具体实现

定义服务端

class MyService : Service() {

    companion object {
        val TAG = "MyService"
		//用于处理客户端消息的Handler
        class MessengerHandler : Handler() {
            override fun handleMessage(msg: Message) {

                when (msg.what) {
                    1 -> {
                        Log.d(TAG, "收到客户端消息:${msg.data.getString("msg")}")
                    }
                    else -> {
                        super.handleMessage(msg)
                    }
                }

            }
        }
    }

    private val mMessenger = Messenger(MessengerHandler())//创建Messenger对象

    override fun onBind(intent: Intent): IBinder {
        return mMessenger.binder//返回Messenger内部的binder
    }
}

//在清单文件中
<service
 android:name=".MyService"
 android:enabled="true"
 android:exported="true"
 android:process=":remote"//运行在单独的进程中
></service>

客户端实现

class MainActivity : AppCompatActivity() {

    private var mService: Messenger? = null

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

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mService = Messenger(service)
            val message = Message.obtain()
            val data = Bundle()
            message.what = 1
            data.putString("msg", "听得见吗,这是来自客户端的消息")
            message.data = data
            try {
                mService!!.send(message)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent(this, MyService::class.java)
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
    }


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

运行结果

在这里插入图片描述

服务端回应

修改服务端代码

class MyService : Service() {

    companion object {
        val TAG = "MyService"

        class MessengerHandler : Handler() {
            override fun handleMessage(msg: Message) {

                when (msg.what) {
                    1 -> {
                        Log.d(TAG, "收到客户端消息:${msg.data.getString("msg")}")
                        val client: Messenger = msg.replyTo//从Message.replyTo取出用于回复的Messenger
                        val message = Message()
                        message.what = 2
                        val bundle: Bundle = Bundle()
                        bundle.putString("reply", "已收到消息,这是来自服务端的回应")
                        message.data = bundle
                        try {
                            client.send(message)//通过该Messenger发送回复消息
                        } catch (e: Exception) {
                            e.printStackTrace()
                        }
                    }
                    else -> {
                        super.handleMessage(msg)
                    }
                }

            }
        }
    }

    private val mMessenger = Messenger(MessengerHandler())


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

修改客户端代码

companion object {
        val TAG = "MainActivity"

        class MessengerHandler : Handler() {
            override fun handleMessage(msg: Message) {
                when (msg.what) {
                    2 -> {
                        Log.d(TAG, "收到服务端回应:${msg.data.getString("reply")}")
                    }
                    else -> {
                        super.handleMessage(msg)
                    }
                }
            }
        }
    }

    private val mReplyMessenger = Messenger(MessengerHandler())//创建给服务端用于回复的Messenger

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

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mService = Messenger(service)
            val message = Message.obtain()
            val data = Bundle()
            message.what = 1
            data.putString("msg", "听得见吗,这是来自客户端的消息")
            message.data = data
            message.replyTo = mReplyMessenger//绑定成功后将mReplyMessenger作为replyTo的参数传递给服务端
            try {
                mService!!.send(message)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

    }

运行结果
在这里插入图片描述

2.AIDL

2.1 实现步骤
  1. 服务端

    创建一个Service用于监听客户端的连接请求,然后创建AIDL接口,将需要的方法在接口中声明,最后在Service中实现这个AIDL接口。

  2. 客户端

    绑定远程服务,然后将服务端返回的Binder对象转成AIDL接口所需的对象,直接调用AIDL方法。

  3. 创建AIDL接口

2.2 具体实现

创建AIDL接口

//IPenManager.aidl
import com.brins.aidldemo.Pen;
interface IPenManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

            void addPen(in Pen pen);
            List<Pen> getPenList();
}

在IPenManager中添加了两个方法

//Pen.aidl
package com.brins.aidldemo;

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

parcelable Pen;

Pen.aidl是与Parcelable对象同名的AIDL文件

class Pen(var type: String?, var price: Int) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readInt()
    ) {
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(type)
        parcel.writeInt(price)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Pen> {
        override fun createFromParcel(parcel: Parcel): Pen {
            return Pen(parcel)
        }

        override fun newArray(size: Int): Array<Pen?> {
            return arrayOfNulls(size)
        }
    }
}

注意 AIDL文件中,并不是所有的数据都支持,AIDL支持的数据类型

  • 基本数据类型和字符串类型(int、long、char、boolean、double、String和CharSequence)
  • List:只支持ArrayList,且里面的元素必须是能够被AIDL支持的
  • Map:只支持HashMap, 且每个元素是AIDL所支持的,包括key和value
  • Parcelable:实现Parcelable的对象
  • AIDL:所有AIDL本身也可以在AIDL文件中使用

远程服务端实现

class MyService : Service() {

    companion object {
        val TAG: String = "MyService"
    }

    private val mPenBinder: IPenManager.Stub = object : IPenManager.Stub() {
        override fun addPen(pen: Pen?) {
            pen?.let {
                pens.add(it)
            }
        }

        override fun basicTypes(
            anInt: Int,
            aLong: Long,
            aBoolean: Boolean,
            aFloat: Float,
            aDouble: Double,
            aString: String?
        ) {
        }

        override fun getPenList(): MutableList<Pen> {
            return pens
        }

    }

    override fun onCreate() {
        super.onCreate()
        pens.add(Pen("钢笔", 10))
        pens.add(Pen("铅笔", 5))
    }

    private val pens: CopyOnWriteArrayList<Pen> = CopyOnWriteArrayList()

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

客户端实现

class MainActivity : AppCompatActivity() {

    companion object {
        val TAG = "MainActivity"
    }

    private var isConnectSuccesss = false
    private var mRemoteService: IPenManager? = null

    private val connection: ServiceConnection = object : ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {
            mRemoteService = null
            println(mRemoteService.toString() + " disconnected! ")
        }

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mRemoteService = IPenManager.Stub.asInterface(service)
            try {
                val list = mRemoteService?.penList
                list?.forEach {
                    Log.d(TAG, "${it.type} 价格:${it.price}")
                }
                Log.d(TAG,"=======================================")
                mRemoteService?.let {
                    it.addPen(Pen("毛笔", 8))//调用addPen
                }
                val newlist = mRemoteService?.penList
                newlist?.forEach {
                    Log.d(TAG, "${it.type} 价格:${it.price}")
                }
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
            println("bind success! $mRemoteService")


        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent(this, MyService::class.java)
        isConnectSuccesss = bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }
}

运行结果
在这里插入图片描述
可以看到成功的将“毛笔”添加到远程服务中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值