文章目录
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完全解析