Android跨进程方式
-
Bundle
-
ContentProvider
-
Socket
-
Messager
-
AIDL
Bundle
-
Android开发中,Bundle 无处不在,不管是启动Activity、Service或者发送Broadcast,都会用到。Android可以通过设置 android:process 设置Activity 或者Service所在的进程,因此Android在设计Bundle 的时候就支持跨进程
Uri uri = Uri.parse("smsto:10086"); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); Bundle bundle = new Bundle(); bundle.putString("sms_body", "SMS Text"); intent.putExtras(bundle); // intent.putExtra("sms_body", "SMS Text"); startActivity(intent);
ContentProvider
- 通过继承 ContentProvider ,并实现ContentProvider 的增删改查等方法,实现与其他应用共享数据
文件共享
- 通过共享文件,将共享数据写到文件,然后其他程序通过读取文件,就可以实现数据的共享。
Messenger
-
服务端定义 Messenger,在 onBind()方法返回
class MessengerService : Service() { var serviceHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { 0x110 -> { LogUtils.d("收到了客户端消息") msg.replyTo.send(Message().apply { what = 0x110 }) } } } } var messenger = Messenger(serviceHandler) override fun onBind(intent: Intent?): IBinder? { return messenger.binder } } -
客户端绑定服务,发送消息时Message.replyTo 设置成客户端 Messenger
var handler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { 0x110 -> { LogUtils.d("收到了服务端0x110消息的回复") } } } } var clientMessenger = Messenger(handler) var conn = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { var messenger = Messenger(service) messenger.send(Message().apply { what = 0x110 replyTo = clientMessenger }) } override fun onServiceDisconnected(name: ComponentName?) { } } var intent = Intent().apply { action = "com.zjp.messengerservice" setPackage("com.zjp.androidacrossprocessesservice") } var result = bindService(intent, conn, Context.BIND_AUTO_CREATE) -
服务端收到消息,通过Message.replyTo 给客户端发送消息
var serviceHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) when (msg.what) { 0x110 -> { LogUtils.d("收到了客户端消息") msg.replyTo.send(Message().apply { what = 0x110 }) } } } } var messenger = Messenger(serviceHandler)
AIDL
-
创建AIDL文件:
通过Android Studio File -> New ->AIDL ->AIDL File ,就可以创建一个AIDL文件。然后Rebuild Project ,Android Studio 就会自动在 build -> generated -> buildType -> out 目录下生成对应的 .java文件,里面就包含了后期我们用到的Stub类。
-
实现Stub 接口:
var stub = object : Stub() { override fun basicType( anInt: Int, aLong: Long, aBoolean: Boolean, aFloat: Float, aDouble: Double, aString: String? ): String { return "this data is from service" } } -
onBind 方法返回 stub,向客户端公开接口:
override fun onBind(intent: Intent?): IBinder? { return stub.asBinder() }现在,
binder是Stub类的一个实例(一个 Binder),其定义了服务的远程过程调用 (RPC) 接口。在下一步中,我们会向客户端公开此实例,以便客户端能与服务进行交互。-
默认情况下,RPC 调用是同步调用。如果您知道服务完成请求的时间不止几毫秒,则不应从 Activity 的主线程调用该服务,因为这可能会使应用挂起(Android 可能会显示“Application is Not Responding”对话框)— 通常,您应从客户端内的单独线程调用服务
-
您引发的任何异常都不会回传给调用方。
AIDL 支持一下数据类型
-
Java基本数据类型 byte char short int long float double boolean
-
String
-
CharSequence
-
List List里面所有数据必须实现 Parcelable
-
Map Map里面所有数据必须实现 Parcelable
-
-
复制服务端 aidl 文件夹到 客服端对应位置,客户端在 onServiceConnected() 回调中YourServiceInterface*.Stub.asInterface(service),以将返回的参数转换成YourServiceInterface类型。
-
var conn = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { var stub = IMyAidlInterface.Stub.asInterface(service) var result = stub.basicTypes(1, 1, false, 1.0f, 1.0, "测试") } override fun onServiceDisconnected(name: ComponentName?) { } }
最后
-
文件共享:适用于 实时性要求不高,并发场景不多的情况,用法简单通用
-
Bundle: 适用于Android四大组件之间
-
ContentProvider: 适用于为其他客户端提供数据,不涉及双向通信
-
AIDL: 适用于大量复杂数据,有实时双向数据通讯
-
Messenger: AIDL的简化版本,适用于数据简单,数据交换不是那么频繁