服务器向客户端传递信息吗,关于AIDL 服务端向客户端传输数据问题

最近有个需求,用到了AIDL来进行跨进程通信,关于AIDL,我们常规的操作是客户端向服务端发送请求,这很简单,只需要在Stub上调用定义的方法即可,顶多需要执行方法的返回值。

但是坑爹的需求总是那么多,例如我需要反向操作,服务器端向客户端发送数据。整个Binder的模型有点像网络的DNS模型,既然能连通,那应该是可以反着走的。

回想一下观察者模式,被观察者持有观察者的一个接口回调,当被观察者数据变化时,通过该接口通知外部的观察者数据的变化情况,主体思路就是这样。

注意的内容是什么呢?

1、由于我们是进行了跨进程的操作,定义的回调接口理论上不属于AIDL默认支持的数据类型,所以要新建一个AIDL文件

2、原先的Stub类需要注册这个回调接口

3、关注 RemoteCallbackList 这个类,它是专门用于删除跨进程listener的接口,它是一个泛型,支持管理任意的AIDL接口

上核心代码:

1、新建listener的AIDL

interface IOnWebSocketListener {

void onSocketConnected();

void onReceiveServerMessage(in CMDEntity aidlCMDEntity);

void onSocketClose();

void onSocketError();

}

2、原有的AIDL注册listener

import com.ideacode.test.IOnWebSocketListener;

interface IWebSocketAidlInterface {

void registListener(IOnWebSocketListener listener);

void unregistListener(IOnWebSocketListener listener);

}

3、客户端要做的事情

private IWebSocketAidlInterface webSocketAidlInterface;

IOnWebSocketListener listener = new IOnWebSocketListener.Stub() {

@Override

public void onSocketConnected() throws RemoteException {

Logger.e("连接成功");

}

@Override

public void onReceiveServerMessage(CMDEntity aidlCMDEntity) throws RemoteException {

Logger.e("收到消息:" + aidlCMDEntity.getMessage());

}

@Override

public void onSocketClose() throws RemoteException {

Logger.e("连接关闭");

}

@Override

public void onSocketError() throws RemoteException {

Logger.e("连接异常");

}

};

ServiceConnection serviceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

webSocketAidlInterface = IWebSocketAidlInterface.Stub.asInterface(iBinder);

try {

webSocketAidlInterface.registListener(listener);

} catch (RemoteException e) {

e.printStackTrace();

}

}

@Override

public void onServiceDisconnected(ComponentName componentName) {

webSocketAidlInterface = null;

}

};

@Override

protected void onDestroy() {

super.onDestroy();

if (serviceConnection != null && webSocketAidlInterface.asBinder().isBinderAlive()) {

try {

webSocketAidlInterface.unregistListener(listener);

} catch (RemoteException e) {

e.printStackTrace();

}

unbindService(serviceConnection);

}

}

4、服务端要做的事情

private RemoteCallbackList mListener = new RemoteCallbackList<>();

IWebSocketAidlInterface.Stub mBinder = new IWebSocketAidlInterface.Stub() {

@Override

public void registListener(IOnWebSocketListener listener) throws RemoteException {

mListener.register(listener);

WebSocketManager webSocketManager = WebSocketManager.getInstance();

webSocketManager.registCallback(mListener);

}

@Override

public void unregistListener(IOnWebSocketListener listener) throws RemoteException {

mListener.unregister(listener);

WebSocketManager webSocketManager = WebSocketManager.getInstance();

webSocketManager.unregistCallback(mListener);

}

};

5、在需要的位置进行listener的响应

private RemoteCallbackList callbackList;

@Override

public void onOpen(ServerHandshake handshakedata) {

//连接成功

Logger.i("websoeket opened connection");

int n = callbackList.beginBroadcast();

for (int i = 0; i < n; i++) {

IOnWebSocketListener listener = callbackList.getBroadcastItem(i);

if (listener != null) {

try {

listener.onSocketConnected();

} catch (RemoteException e) {

e.printStackTrace();

}

}

}

callbackList.finishBroadcast();

}

注意的地方:

1、RemoteCallbackList这个东西并不是一个List,所以不能进行foreach遍历

2、beginBroadcast和finishBroadcast要成堆出现,哪怕是要获取RemoteCallbackList中的元素个数。

这样客户端就能收到服务器端回调过来的消息啦,实测通过,比我之前用的方案更清晰,很好很好!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值