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 实现步骤
-
服务端进程
创建一个Service来处理客户端连接请求,同时创建Handler并通过他来创建Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder。
-
客户端进程
首先绑定服务端的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 实现步骤
-
服务端
创建一个Service用于监听客户端的连接请求,然后创建AIDL接口,将需要的方法在接口中声明,最后在Service中实现这个AIDL接口。
-
客户端
绑定远程服务,然后将服务端返回的Binder对象转成AIDL接口所需的对象,直接调用AIDL方法。
-
创建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)
}
}
运行结果
可以看到成功的将“毛笔”添加到远程服务中