一、客户端调用服务端的方法。
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() {@Overridepublic 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);}}@Overridepublic void onServiceDisconnected(ComponentName name) {}
};
3、服务端Service的实现如下:
public class TestService extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return new TestBinder();}class TestBinder extends Binder {final static int ADD = 1;@Overrideprotected 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;@Overrideprotected 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() {@Overridepublic 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);}}@Overridepublic void onServiceDisconnected(ComponentName name) {}
};
3、服务端TestBinder类修改如下:
class TestBinder extends Binder {final static int ADD = 1;@Overrideprotected 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",则说明服务端调用客户端的方法成功。