第一种方式
1. 服务端:
public class MyService extends Service {
private static final String TAG = "MyService";
private static final int CODE_DO = 1;
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return myBinder;
}
Binder myBinder = new Binder(){
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (code == CODE_DO) {
int a = data.readInt();
int result = plusOne(a);
reply.writeInt(a);
Log.i(TAG, "result value is" + result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
};
public int plusOne(int a) {
return a++;
}
}
步骤说明:
- 自定义了一个myBinder,并重写了onTransact()方法
- 在onTransact()方法中通过parcel data读取客户端传过来的值,并写入到另一个parcel reply中
2.客户端:
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBinder = iBinder;
transactValue(2);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
private void transactValue(int i) {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInt(i);
try {
//调用远程服务
mBinder.transact(CODE_DO,data,reply,0);
//获取远程服务返回的值
int result = reply.readInt();
Log.i(TAG, " result " + result);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
步骤说明:
- 绑定服务后通过serviceConnection获取服务端的IBinder对象 mBinder
- 构造一个Parcel data 然后写入数据到data中,构造一个Parcel reply 读取数据
- 通过transact调用远程服务
- reply 通过readInt()读取远程服务返回的值
3. 小结
- 需求:客户端的目的是向服务端传值,服务端的目的是把客户端传过来的值进行处理然后返回给客户端
- 缺点:这段代码对客户端暴露了Binder的具体细节transact,对服务端也暴露了Binder的具体细节onTransact
- 优化方向:将服务端需要实现的方法放到一个接口中,自定义一个Binder来继承这个接口,通过代理模式来隐藏具体的细节,见第二种方式
第二种方式
1. 把plusOne方法放到一个接口中
public interface IPlusOne extends android.os.IInterface {
//binder 描述符
static final String DESCRIPTOR = "com.example.myapplication.IPLUSOne";
static final int TRANSACTION_plusOne = IBinder.FIRST_CALL_TRANSACTION;
public int plusOne (int a) throws RemoteException;
}
2. 自定义一个Binder类
package com.example.myapplication;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
public class PlusOneImpl extends android.os.Binder implements IPlusOne {
@Override
public int plusOne(int a) throws RemoteException {
return 0;
}
@Override
public IBinder asBinder() {
return this;
}
public PlusOneImpl() {
this.attachInterface(this, DESCRIPTOR);
}
public static IPlusOne asInterface(IBinder obj) {
if (obj == null) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if ((iin != null) && (iin instanceof IPlusOne)) {
return (IPlusOne) iin;
}
return new PlusOneImpl.Proxy(obj);
}
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION:{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_plusOne: {
data.enforceInterface(DESCRIPTOR);
int args = data.readInt();
int result = this.plusOne(args);
reply.writeInt(result);
return true;
}
}
return super.onTransact(code,data,reply,flags);
}
private static class Proxy implements IPlusOne {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public int plusOne(int a) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInt(a);
mRemote.transact(TRANSACTION_plusOne,data,reply,0);
} finally {
reply.recycle();
data.recycle();
}
return 0;
}
@Override
public IBinder asBinder() {
return mRemote;
}
}
}
步骤说明:
- 使PlusOneImpl继承Binder类,从而可以重写Binder的onTransact()方法,接收客户端传来的数据
- PlusOneImpl实现IPlusOne的接口,从而可以在服务端实现plusOne()方法
- PlusOneImpl 通过asInterface(IBinder)来构建一个Proxy类给客户端使用,IBinder即PlusOneImpl自身
- Proxy类实现了PlusOneImpl接口,从而客户端可以调用到Proxy端的plusOne()方法
- 这个Proxy中包含一个IBinder对象,在plusOne()方法中Proxy通过IBinder来执行transact方法进行跨进程访问
3. 服务端:
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return myBinder;
}
private final PlusOneImpl myBinder = new PlusOneImpl() {
@Override
public int plusOne(int a) throws RemoteException {
return a++;
}
};
}
4. 客户端:
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IPlusOne mPlusOne = mPlusOneImpl.asInterface(iBinder);
try {
mPlusOne.plusOne(3);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
小结:
-
将服务端所需要的实现的方法,放到一个接口中,然后让自定义的Binder去实现这个接口,最终在服务端初始化自定义的Binder并重写这个接口以实现具体的功能,这是通过依赖倒置让Binder去依赖Service,从而实现Service对Binder的把控
-
跨进程通信过程中通过代理模式向客户端隐藏具体细节