1 aidl相关困扰点
1 制作步骤复杂,先定义然后编译,然后复制,两边都要一一对应
2 增加回调,自定义对象流程更加麻烦,还要处理对象数据流是 in 还是out。
3 一方异常怎么办,虽然服务端可以用 RemoteCallbackList 客户端可以用DeathRecipient来处理,但很麻烦
4 考虑服务端一对多时候,需要一对一发送消息
很累很麻烦,使用还不方便,所以我必须设计一个aar包,将这些细节全都封进去,以后再也不关心这些破玩意了
2 解决方案
1 为了应对各种对象,统一转为string进行传输(可通过json等转成对应的对象)
2 通过添加封装类对 aidl的连接流程进行封装,本地的也封装以下(虽然本地的bind可以直接进程内通信)
3 传输监听对象时,需要传输一个唯一值 ,通过map保存该唯一值。这样就可以通过key值进行针对性传输,也可以找到该监听类,不再通过RemoteCallbackList来移除监听类了。
4 提供异步和同步访问,因为有些操作同步会导致 service 卡顿(四大组件之一的服务是运行在主线程),所以是需要提供下异步操作的。
3 实现
接下来看下大概的类图吧,然后下一步就是具体的实现了。
先来看下本地服务类代码: public abstract class AsynService extends Service {protected static final String TAG = "JsonProtocolService";protected WorkThread worker;public void onCreate() {super.onCreate();if (this.worker == null || !this.worker.isRunning()) {this.worker = new WorkThread();this.worker.start();}}public void onDestroy() {super.onDestroy();if (this.worker != null && this.worker.isRunning()) {this.worker.interrupt();this.worker = null;}}protected String getRequestAuthor(String params) {String requestAuthor = null;try {JSONObject jsonObject = new JSONObject(params);if (jsonObject.has(SDKConstants.KEY_CLIENT_REQUEST_AUTHOR)) {requestAuthor = jsonObject.optString(SDKConstants.KEY_CLIENT_REQUEST_AUTHOR);}} catch (JSONException e) {Log.e(TAG, "getRequestAuthor: ", e);}return requestAuthor;}protected void offerReq(JsonProtocolManager.Message message) {this.worker.offerReq(message);}//具体实现接口抽象出来给外部实现public interface ServiceCallback {void onEvent(int event, String msg);void received(String params, Bundle bundle);String receivedSync(String params, Bundle bundle);}protected static class WorkThread extends Thread {private static final Object syncObj = new Object();private final LinkedBlockingQueue<JsonProtocolManager.Message> msgLBQ = new LinkedBlockingQueue<>();private boolean isRunning = false;private ServiceCallback serviceCallback;public void init(ServiceCallback callback) {synchronized(syncObj) {this.serviceCallback = callback;syncObj.notify();}}public void onEvent(int event, String msg) {synchronized(syncObj) {if (this.serviceCallback != null) {this.serviceCallback.onEvent(event, msg);}}}public void offerReq(JsonProtocolManager.Message message) {this.msgLBQ.offer(message);}public void run() {this.isRunning = true;while (this.isRunning) {try {JsonProtocolManager.Message msg = this.msgLBQ.take();synchronized(syncObj) {while (this.serviceCallback == null) {syncObj.wait();}}if (!this.onReceive(msg)) {this.msgLBQ.offer(msg);}} catch (Exception e) {e.printStackTrace();}}}boolean isRunning() {return this.isRunning;}private boolean onReceive(JsonProtocolManager.Message message) {synchronized(syncObj) {if (this.serviceCallback != null) {LogUtils.e(TAG, "receive params=" + message.mParams);this.serviceCallback.received(message.mParams, message.mBundle);return true;} else {return false;}}}}protected ServiceCallback mServiceCallback;public void setServiceCallback(ServiceCallback mLocalCallback) {this.mServiceCallback = mLocalCallback;}abstract void send(JsonProtocolManager.Message message);abstract String sendSync(String params, Bundle bundle);//本地bind,进程内通信public class ServiceBinder extends Binder {public void setServiceCallback(ServiceCallback callback) {AsynService.this.setServiceCallback(callback);AsynService.this.worker.init(callback);}public void send(JsonProtocolManager.Message message) {AsynService.this.send(message);}public String sendSync(String params, Bundle bundle) {return AsynService.this.sendSync(params, bundle);}} }
再来看下 实现类:
public class AidlService extends AsynService {private static final String TAG = "JsonProtocolService";private final HashMap<String, ICallback> mCallbacksMap = new HashMap<String, ICallback>();private final ServiceBinder localBinder = new ServiceBinder();private final IServiceBinder.Stub remoterBinder = new IServiceBinder.Stub() {@Overridepublic int register(int versionCode, String caller, ICallback callback) {LogUtils.d(TAG, "register: versionCode = " + versionCode + " , caller = " + caller);mCallbacksMap.put(caller, callback);//remoteCallbackList.register(callback);worker.onEvent(SDKConstants.EVENT_CLIENT_CONNECTED, "client is connected!");return SDKConstants.VERSION_CODE;}@Overridepublic void received(String params, Bundle bundle) {JsonProtocolManager.Message message = new JsonProtocolManager.Message(params, bundle);offerReq(message);}@Overridepublic String receivedSync(String params, Bundle bundle) {return mServiceCallback == null ? "" : mServiceCallback.receivedSync(params, bundle);}@Overridepublic void unregister(String caller, ICallback callback) {mCallbacksMap.remove(caller);//remoteCallbackList.unregister(callback);worker.onEvent(SDKConstants.EVENT_CLIENT_DISCONNECTED, "client is disconnected!");}};@Overridepublic IBinder onBind(Intent intent) {LogUtils.d(TAG, "onBind");if (intent != null && intent.hasExtra(SDKConstants.CONNECT_EXTRA_KEY)) {String from = intent.getStringExtra(SDKConstants.CONNECT_EXTRA_KEY);if (SDKConstants.CONNECT_EXTRA_VALUE_LOCAL.equals(from)) {LogUtils.d(TAG, "onBind:local");return this.localBinder;}if (SDKConstants.CONNECT_EXTRA_VALUE_REMOTER.equals(from)) {LogUtils.d(TAG, "onBind:remoter");return this.remoterBinder;}}return null;}@Overrideprotected void send(JsonProtocolManager.Message message) {try {int N = mCallbacksMap.size();if (N > 0) {LogUtils.e(TAG, "send params=" + message.mParams);ICallback l = null;String requestAuthor = getRequestAuthor(message.mParams);if (mCallbacksMap.size() > 0 && !TextUtils.isEmpty(requestAuthor)) {l = mCallbacksMap.get(requestAuthor);}if (l != null) {l.received(message.mParams, message.mBundle);}else {Log.e(TAG, "send: client is NOT connected:" + requestAuthor);}} else if (N == 0) {Log.e(TAG, "send: client is NOT connected");}} catch (Exception e) {LogUtils.e(TAG, "send params=" + message.mParams);}}@Overrideprotected String sendSync(String params, Bundle bundle) {try {int N = mCallbacksMap.size();if (N > 0) {LogUtils.e(TAG, "send params=" + params);ICallback l = null;String requestAuthor = getRequestAuthor(params);if (mCallbacksMap.size() > 0 && !TextUtils.isEmpty(requestAuthor)) {l = mCallbacksMap.get(requestAuthor);}if (l != null) {return l.receivedSync(params, bundle);} else {Log.e(TAG, "sendSync: client is NOT connected:" + requestAuthor);}} else if (N == 0) {Log.e(TAG, "sendSync: client is NOT connected");}} catch (Exception e) {LogUtils.e(TAG, "send params=" + params);}return null;}}
下次再来接下来的manager类