一、客户端调用服务端的方法。
1、客户端绑定服务端Service。
Intent intent = new Intent();
intent.setComponent(
new ComponentName("com.example.servicetest","com.example.servicetest.TestService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
2、客户端在绑定服务端的回调方法中直接调用服务端的方法。
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
// 这个校验Token是可选的,建议添加
data.writeInterfaceToken("com.example.service.test");
final int ADD = 1;
int a = 1;
int b = 2;
data.writeInt(a);
data.writeInt(b);
// 发起Binder事务,调用服务端add方法
service.transact(ADD, data, reply, 0);
// 获取服务端是否发生异常
reply.readException();
// 获取add方法调用的返回值
int result = reply.readInt();
Log.i("MainActivity", "result = " + result);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
3、服务端Service的实现如下:
public class TestService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new TestBinder();
}
class TestBinder extends Binder {
final static int ADD = 1;
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code) {
case ADD:
// 校验客户端的Token,如果校验错误会抛异常
data.enforceInterface("com.example.service.test");
int a = data.readInt();
int b = data.readInt();
// 调用add方法进行计算
int result = add(a, b);
// 写入没有异常产生
reply.writeNoException();
// 写入add方法调用的返回值
reply.writeInt(result);
return true;
default:
return super.onTransact(code, data, reply, flags);
}
}
public int add(int a, int b) {
return a + b;
}
}
}
4、如果打印"result = 3",则说明客户端调用服务端的方法成功。
二、服务端调用客户端的方法。
假如服务端的add比较耗时(5秒),我们可以采用回调的方式,将计算结果上报。下面是具体实现。
1、客户端添加一个继承Binder的类,用于接收服务端的回调。
class MyBinder extends Binder {
final static int NOTIFY_RESULT = 10;
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code) {
case NOTIFY_RESULT:
data.readException();
int result = data.readInt();
notifyResult(result);
return true;
default:
return super.onTransact(code, data, reply, flags);
}
}
public void notifyResult(int result) {
Log.i("MainActivity", "result = " + result);
}
}
2、客户端绑定服务端的回调方法修改如下:
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
// 这个校验Token是可选的,建议添加
data.writeInterfaceToken("com.example.service.test");
final int ADD = 1;
int a = 1;
int b = 2;
data.writeInt(a);
data.writeInt(b);
// 将客户端用于接收服务端回调的Binder传递过去
data.writeStrongBinder(new MyBinder());
// 发起Binder事务
service.transact(ADD, data, reply, 0);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
3、服务端TestBinder类修改如下:
class TestBinder extends Binder {
final static int ADD = 1;
@Override
protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
switch (code) {
case ADD:
// 校验客户端的Token,如果校验错误会抛异常
data.enforceInterface("com.example.service.test");
int a = data.readInt();
int b = data.readInt();
IBinder binder = data.readStrongBinder();
new Thread(()->{
try {
final int NOTIFY_RESULT = 10;
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
// 调用add方法
int result = add(a, b);
_data.writeNoException();
_data.writeInt(result);
binder.transact(NOTIFY_RESULT, _data, _reply, 0);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}).start();
return true;
default:
return super.onTransact(code, data, reply, flags);
}
}
public int add(int a, int b) {
SystemClock.sleep(5000);
return a + b;
}
}
4、如果打印"result = 3",则说明服务端调用客户端的方法成功。