Android IPC的两种方式:AIDL,Messenger


Android 进程间通信简称IPC(InterProcess Communication),实现IPC有两种方式,一种是AIDL,一种是Messenger。实际上Messenger的源码也是调用的AIDL,最终都是通过Binder实现的。只是Messenger使用方式比AIDL更便捷。下面我们就来学习一下这两种IPC方式。

一、使用AIDL在APP内进行进程间通信

第一步:新建Service

新建一个Service,添加process属性,使其在另一个进程中运行:

<service android:name=".MyService"
         android:process=":remote"/>

第二步:新建AIDL接口

新建AIDL接口IMyAidlInterface.aidl,编辑如下:

package com.example.studyaidl;

interface IMyAidlInterface {
    void plus(int a, int b);
}

编辑完成后编译项目,编译完成后Android Studio将会在generatedJava文件夹中自动生成一个接口文件IMyAidlInterface。在这个文件中会有我们定义的接口方法,如下图所示。

第三步:Service中返回实现AIDL接口的Binder

编辑MyService类:

class MyService : Service() {
    private val myBinder = object : IMyAidlInterface.Stub() {
        override fun plus(a: Int, b: Int): Int {
            return a + b
        }
    }

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

第四步:绑定Service,调用AIDL接口方法

编辑MainActivity类:

class MainActivity : AppCompatActivity() {
    private lateinit var myBinder: IMyAidlInterface

    private val connection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            myBinder = IMyAidlInterface.Stub.asInterface(service)
            Log.d("~~~", "1 + 1 = ${myBinder.plus(1, 1)}")
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
    }

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

    private fun initView() {
        btnBindService.setOnClickListener {
            bindService(Intent(this@MainActivity, MyService::class.java), connection, BIND_AUTO_CREATE)
        }
        btnUnbindService.setOnClickListener {
            unbindService(connection)
        }
    }
}

activity_main布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnBindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Bind Service"
        android:textAllCaps="false"
        app:layout_constraintTop_toTopOf="@id/btnBindService" />

    <Button
        android:id="@+id/btnUnbindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Unbind Service"
        android:textAllCaps="false"
        app:layout_constraintTop_toBottomOf="@id/btnBindService" />
</android.support.constraint.ConstraintLayout>

运行程序,Log控制台输出如下:

~~~: 1 + 1 = 2

二、使用隐式Service绑定另一个程序的Service,实现app之间的进程通信

第一步:拷贝AIDL文件

拷贝AIDL接口文件到新应用程序src/main/aidl/com.example.studyaidl中,拷贝完成后编译程序

第二步:Service中添加Action

在AndroidManifest中,给Service添加Action:

<service android:name=".MyService">
    <intent-filter>
        <action android:name="com.example.studyaidl.MyAIDLService"/>
    </intent-filter>
</service>

第三步:在另一个应用中,使用隐式Intent绑定此Service

隐式Intent绑定远程Service

val intent = Intent("com.example.studyaidl.MyAIDLService").apply {
    setPackage("com.example.studyaidl")
}
bindService(intent, connection, Context.BIND_AUTO_CREATE)

三、使用Messenger在APP内进行进程间通信

第一步:新建Service

新建一个Service,添加process属性,使其在另一个进程中运行:

<service android:name=".MyService"
         android:process=":remote"/>

第二步:Service中返回Messenger的Binder

编辑MyService类:

class MyService : Service() {
    @SuppressLint("HandlerLeak")
    private val messenger = Messenger(object : Handler() {
        override fun handleMessage(msg: Message) {
            // 初始化响应Message
            val response = Message.obtain(msg)
            // 设置响应Message的data数据
            response.data.putString("result", "${msg.arg1 + msg.arg2}")
            // 发送响应Message
            msg.replyTo.send(response)
            super.handleMessage(msg)
        }
    })

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

第三步:绑定Service,向服务端发送请求Message

编辑MainActivity类:

class MainActivity : AppCompatActivity() {

    @SuppressLint("HandlerLeak")
    private val messenger = Messenger(object : Handler() {
        override fun handleMessage(msg: Message?) {
            Log.d("~~~", "${msg?.arg1} + ${msg?.arg2} = ${msg?.data?.getString("result")}")
            super.handleMessage(msg)
        }
    })

    private val connection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            // 初始化请求Message的arg1和arg2参数
            val request = Message.obtain(null, 0, 1, 1)
            // 设置请求Message的服务端回调
            request.replyTo = messenger
            // 向服务端发送请求Message
            Messenger(service).send(request)
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
    }

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

    private fun initView() {
        btnBindService.setOnClickListener {
            bindService(Intent(this@MainActivity, MyService::class.java), connection, BIND_AUTO_CREATE)
        }
        btnUnbindService.setOnClickListener {
            unbindService(connection)
        }
    }
}

activity_main布局文件和上例一样,运行程序,Log控制台输出如下:

~~~: 1 + 1 = 2

四、使用隐式Service绑定另一个程序的Service,实现app之间的进程通信

第一步:Service中添加Action

在AndroidManifest中,给Service添加Action:

<service android:name=".MyService">
    <intent-filter>
        <action android:name="com.example.studymessenger.MyService"/>
    </intent-filter>
</service>

第二步:在另一个应用中,使用隐式Intent绑定此Service

隐式Intent绑定远程Service

val intent = Intent("com.example.studymessenger.MyService").apply {
    setPackage("com.example.studymessenger")
}
bindService(intent, connection, Context.BIND_AUTO_CREATE)

通过调用其他程序的远程Service,可以在产品矩阵中实现多个应用共享一个服务。比如Google的Google Service。

参考文章

Android Service完全解析,关于服务你所需知道的一切(下)
Android 基于Message的进程间通信 Messenger完全解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值