1.AIDL的使用
下面是项目的目录结构
其中在aidl文件下创建相同的包结构,在bean目录下创建和实体类一样的aidl文件,并用 parcelable关键字声明这个类
package com.kx.studyview.aidl.bean;
parcelable MessageModel ;
MessageReceiver,用于实现服务端传递给客户端消息的监听,类似接口回调的方式。
package com.kx.studyview.aidl;
import com.kx.studyview.aidl.bean.MessageModel ;
interface MessageReceiver {
void onMessageReceived(in MessageModel receivedMessage);
}
MessageSender,主要用于实现客户端与服务端的交互
// MessageSender.aidl
package com.kx.studyview.aidl;
import com.kx.studyview.aidl.bean.MessageModel ;
import com.kx.studyview.aidl.MessageReceiver ;
interface MessageSender {
void sendMessage(in MessageModel messageModel);
void registerReceiveListener(MessageReceiver messageReceiver);
void unregisterReceiveListener(MessageReceiver messageReceiver);
}
MessageService 代码
public class MessageService extends Service {
private static final String TAG = "MessageService";
private AtomicBoolean serviceStop = new AtomicBoolean(false);
//RemoteCallbackList专门用来管理多进程回调接口
private RemoteCallbackList listenerList = new RemoteCallbackList<>();
@Override
public void onCreate() {
super.onCreate();
new Thread(new FakeTCPTask()).start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return messageSender;
}
IBinder messageSender = new MessageSender.Stub() {
@Override
public void sendMessage(MessageModel messageModel) throws RemoteException {
LogUtils.e("MessageService 进程收到消息了 " + messageModel.toString());
}
@Override
public void registerReceiveListener(MessageReceiver messageReceiver) throws RemoteException {
listenerList.register(messageReceiver);
}
@Override
public void unregisterReceiveListener(MessageReceiver messageReceiver) throws RemoteException {
listenerList.unregister(messageReceiver);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
/**
* 包名验证方式
*/
String packageName = null;
String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
if (packages != null && packages.length > 0) {
packageName = packages[0];
}
if (packageName == null || !packageName.startsWith("com.kx.studyview.aidl")) {
LogUtils.e("MessageService 进程onTransact " + "拒绝调用:" + packageName);
return false;
}
//自定义permission方式检查权限
if (checkCallingOrSelfPermission("com.kx.studyview.aidl.permission.REMOTE_SERVICE_PERMISSION") == PackageManager.PERMISSION_DENIED) {
return false;
}
LogUtils.e("MessageService 进程onTransact " + "同意调用:" + packageName);
return super.onTransact(code, data, reply, flags);
}
};
@Override
public void onDestroy() {
serviceStop.set(true);
super.onDestroy();
}
//模拟长连接,通知客户端有新消息到达
private class FakeTCPTask implements Runnable {
@Override
public void run() {
while (!serviceStop.get()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MessageModel messageModel = new MessageModel();
messageModel.setFrom("Service");
messageModel.setTo("Client");
messageModel.setContent(String.valueOf(System.currentTimeMillis()));
/**
* RemoteCallbackList的遍历方式
* beginBroadcast和finishBroadcast一定要配对使用
*/
final int listenerCount = listenerList.beginBroadcast();
for (int i = 0; i < listenerCount; i++) {
MessageReceiver messageReceiver = listenerList.getBroadcastItem(i);
if (messageReceiver != null) {
try {
messageReceiver.onMessageReceived(messageModel);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
listenerList.finishBroadcast();
}
}
}
}
MainActivity 代码
public class MainActivity extends AppCompatActivity {
private MessageSender mMessageSender ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupService();
}
/**
* 消息监听回调接口
*/
MessageReceiver mMessageReceiver = new MessageReceiver.Stub() {
@Override
public void onMessageReceived(MessageModel receivedMessage) throws RemoteException {
LogUtils.e("客户端收到服务端发过来的消息了 " + receivedMessage.toString());
}
};
// 当服务端进程Crash binder死亡时,会回调binderDied方法;
IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mMessageSender!=null){
mMessageSender.asBinder().unlinkToDeath(mDeathRecipient,0);
mMessageSender = null ;
}
// 重启服务端
setupService();
}
};
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName com4ponentName, IBinder iBinder) {
// 获得 服务端 AIDL的操作接口 相当于一个中间对象
mMessageSender = MessageSender.Stub.asInterface(iBinder);
MessageModel messageModel = new MessageModel();
messageModel.setContent("我是消息内容");
messageModel.setTo("服务端接受");
messageModel.setFrom("客户端发送");
LogUtils.e("客户端发送消息 " + messageModel.toString());
try {
mMessageSender.registerReceiveListener(mMessageReceiver);
mMessageSender.sendMessage(messageModel);
//设置 服务端 Binder死亡监听
mMessageSender.asBinder().linkToDeath(mDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
LogUtils.e("RemoteException " + e.toString());
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
/**
* bindService
*/
private void setupService() {
Intent intent = new Intent(this, MessageService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
startService(intent);
}
/**
* unbindService
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (mMessageReceiver!=null && mMessageReceiver.asBinder().isBinderAlive()){
try {
// TODO: 2018/8/9 解决当MessageService方法onBind方法返回Null时 mMessageSender为空的崩溃
if (mMessageSender!=null){
mMessageSender.unregisterReceiveListener(mMessageReceiver);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
unbindService(mServiceConnection);
}
}
当我们bindService后,在ServiceConnection中我们就可以获得服务端 AIDL的操作接口,
mMessageSender = MessageSender.Stub.asInterface(iBinder)
我们拿到服务端的AIDL操作接口对象后就可以给服务端发送消息了,
客户端调用,发送消息
mMessageSender.sendMessage(messageModel);
IBinder messageSender = new MessageSender.Stub() {
@Override
public void sendMessage(MessageModel messageModel) throws RemoteException {
LogUtils.e("MessageService 进程收到消息了 " + messageModel.toString());
}
}
如果服务端要给客户端发消息该怎么做呢?通过观察者模式实现
服务端AIDL新增接口
interface MessageSender {
void sendMessage(in MessageModel messageModel);
// 新增
void registerReceiveListener(MessageReceiver messageReceiver);
// 新增
void unregisterReceiveListener(MessageReceiver messageReceiver);
interface MessageReceiver {
void onMessageReceived(in MessageModel receivedMessage);
}
}
MainActivity中新增代码
/**
* 消息监听回调接口
*/
MessageReceiver mMessageReceiver = new MessageReceiver.Stub() {
@Override
public void onMessageReceived(MessageModel receivedMessage) throws RemoteException {
LogUtils.e("客户端收到服务端发过来的消息了 " + receivedMessage.toString());
}
};
// 将回调AIDL对象注册到服务端中去
mMessageSender.registerReceiveListener(mMessageReceiver);
MessageService中新增代码
//RemoteCallbackList专门用来管理多进程回调接口
private RemoteCallbackList listenerList = new RemoteCallbackList<>();
@Override
public void registerReceiveListener(MessageReceiver messageReceiver) throws RemoteException {
listenerList.register(messageReceiver);
}
@Override
public void unregisterReceiveListener(MessageReceiver messageReceiver) throws RemoteException {
listenerList.unregister(messageReceiver);
}
模拟发送消息
//模拟长连接,每过5秒通知客户端有新消息到达
private class FakeTCPTask implements Runnable {
@Override
public void run() {
while (!serviceStop.get()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MessageModel messageModel = new MessageModel();
messageModel.setFrom("Service");
messageModel.setTo("Client");
messageModel.setContent(String.valueOf(System.currentTimeMillis()));
/**
* RemoteCallbackList的遍历方式
* beginBroadcast和finishBroadcast一定要配对使用
*/
final int listenerCount = listenerList.beginBroadcast();
for (int i = 0; i < listenerCount; i++) {
MessageReceiver messageReceiver = listenerList.getBroadcastItem(i);
if (messageReceiver != null) {
try {
messageReceiver.onMessageReceived(messageModel);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
listenerList.finishBroadcast();
}
}
}
registerReceiveListener 和 unregisterReceiveListener在客户端传输过来的对象,经过Binder处理,在服务端接收到的时候其实是一个新的对象,这样导致在 unregisterReceiveListener 的时候,普通的ArrayList是无法找到在 registerReceiveListener 时候添加到List的那个对象的,但是它们底层使用的Binder对象是同一个,RemoteCallbackList利用这个特性做到了可以找到同一个对象,这样我们就可以顺利反注册客户端传递过来的接口对象了。RemoteCallbackList在客户端进程终止后,它能自动移除客户端所注册的listener,它内部还实现了线程同步,所以我们在注册和反注册都不需要考虑线程同步。
Binder死亡代理方法unlinkToDeath和linkToDeath
- linkToDeath -> 设置死亡代理 DeathRecipient 对象;
- unlinkToDeath -> Binder死亡的情况下,解除该代理。
//设置 服务端 Binder死亡代理
mMessageSender.asBinder().linkToDeath(mDeathRecipient,0);
// 当服务端进程 binder死亡时,会回调binderDied方法;
IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mMessageSender!=null){
mMessageSender.asBinder().unlinkToDeath(mDeathRecipient,0);
mMessageSender = null ;
}
// 重启服务端
setupService();
}
};
服务端进程Crash了,而客户端进程想要调用服务端方法,这样就调用不到了。此时我们可以给Binder设置一个DeathRecipient对象,当Binder意外挂了的时候,我们可以在DeathRecipient接口的回调方法中收到通知,并作出相应的操作,比如重连服务等等。
DeathRecipient的使用如下:
声明DeathRecipient对象,实现其binderDied方法,当binder死亡时,会回调binderDied方法;
给Binder对象设置DeathRecipient对象。