进程间通信框架,非AIDL(进程间通信机制有哪些)

网友投稿 919 2022-10-11

进程间通信框架,非AIDL(进程间通信机制有哪些)

进程间通信框架,非AIDL(进程间通信机制有哪些)

IPCCommunication github地址

#进程间通信 说到Android进程间通信,大家肯定能想到的是编写aidl文件,然后通过aapt生成的类方便的完成服务端,以及客户端代码的编写。

什么是IPCCommunication

IPCCommunication是通过两种方式实现进程间通信,一种是手写binder实现进程间通信,互相传递使用Bunder,可以在Bunder中自定义协议,另外一种是基于Message,客户端与服务端之间使用Message进行通信;

#为什么要写这个框架 曾经听过一个人说过,程序中尽量使用通用组件或者框架,这样可以尽量的少写代码,这样有两个好处,一是少写代码就意味着少犯错误,二是可以多出喝咖啡的时间 ; #使用 手写Binder方式有两种方式 1.使用通用的IPCService服务库,包括与Activity通信 服务端 服务端可以通过Activity 启动也可以不启动,若不启动可以通过继承BaseIPCService的方式,具体实现查看SimpleService

public class MainActivity extends AppCompatActivity { private ServiceUtils mServiceUtils; private static final String TAG = "jcy_service"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mServiceUtils = new ServiceUtils(this); } @Override protected void onResume() { super.onResume(); //调用默认IPC 服务 mServiceUtils.setConnectListener(mConnectListener); mServiceUtils.bindService(); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); mServiceUtils.unBindService(); } ConnectListener mConnectListener = new ConnectListener() { @Override public void onBind() { } @Override public void onDisconnected() { } @Override public void onConnected(boolean success) { mServiceUtils.setReceiverListener(mReceiverListener); } @Override public void onUnbind() { mServiceUtils.setReceiverListener(null); } ; }; private ReceiverListener mReceiverListener = new ReceiverListener() { @Override public Bundle receiveInfo(int code, Bundle msg) { String msgStr = msg.getString("msgStr"); int msgInt = msg.getInt("msgInt"); Log.d(TAG, "receiveInfo: msgStr " + msgStr + " ,msgInt : " + msgInt); Bundle ret = new Bundle(); ret.putString("return", "服务端返回 code " + code + " ,msgStr " + msgStr + " ,msgInt : " + msgInt); return ret; } };}

客户端

public class MainActivity extends AppCompatActivity { private static final String TAG = "jcy_client_one"; private TextView mTextView; private TextView tv_state; private ClientUtils mClientUtils; private Button btnGet, btn_bind, btn_unbind; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.tv_service); tv_state = (TextView) findViewById(R.id.tv_state); btnGet = (Button) findViewById(R.id.btn_getService); btn_bind = (Button) findViewById(R.id.btn_bind); btn_unbind = (Button) findViewById(R.id.btn_unbind); btnGet.setEnabled(false); tv_state.setText(" 服务未绑定 "); mClientUtils = new ClientUtils(this); mClientUtils.setConnectListener(mConnectListener); btn_bind.setEnabled(true); btn_unbind.setEnabled(false); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { super.onDestroy(); if(mClientUtils!=null){ mClientUtils.unBindService(); } } /** * 获取数据 * * @param v */ public void onGetServie(View v) { if (mClientUtils.isConnect()) { Bundle send = new Bundle(); send.putString("msgStr", "ClientOneApp发送消息"); send.putInt("msgInt", 110); try { Bundle ret = mClientUtils.send(110, send); if (ret == null) { Log.e(TAG, "onGetServie: ret==null"); } else { String retStr = ret.getString("return"); mTextView.append("\n"+retStr); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "onGetServie:Exception " + e.toString()); } } else { Toast.makeText(this, "未连接服务,无法获取消息", Toast.LENGTH_SHORT).show(); } } /** * 绑定服务 * @param v */ public void onBindServie(View v) { mClientUtils.bindService(); } /** * 解除绑定 * @param v */ public void onUnBindServie(View v) { mClientUtils.unBindService(); } /** * 连接状态回调 */ private ConnectListener mConnectListener = new ConnectListener() { @Override public void onBind() { tv_state.setText(" 服务正在绑定中…… "); } @Override public void onDisconnected() { btnGet.setEnabled(false); tv_state.setText(" 服务断开连接 "); btn_bind.setEnabled(true); btn_unbind.setEnabled(false); } @Override public void onConnected(boolean success) { if (success) { tv_state.setText(" 服务绑定成功 "); btn_bind.setEnabled(false); btn_unbind.setEnabled(true); btnGet.setEnabled(true); } else { btnGet.setEnabled(false); tv_state.setText(" 服务绑定失败 "); mClientUtils.unBindService(); btn_bind.setEnabled(true); btn_unbind.setEnabled(false); } } @Override public void onUnbind() { btn_bind.setEnabled(true); btn_unbind.setEnabled(false); tv_state.setText(" 服务已解除绑定 "); mTextView.setText(""); } };}

另外还支持自定义Service 的方式 具体查看SimpleService类 Message的使用方式与自定义Binder的形式类似,大部分使用方式几乎相同

#分析 手写Binder

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

这个方法 一般情况下 都是返回true的,也只有返回true的时候才有意义,如果返回false了 就代表这个方法执行失败,onTransact 这个方法 就是运行在Binder线程池中的,一般就是客户端发起请求,然后android底层代码把这个客户端发起的,请求 封装成3个参数 来调用这个onTransact方法,第一个参数code 就代表通信的标志位,data就是方法参数(客户端传递过来的数据),reply就是方法返回值(通过这个方法可以向客户端中返回数据)。

自定义Binder为

/** * description : 自定义Binder实现消息传递 * autour : 姜春雨@沈阳 * date : 17-3-24 上午10:33 * mail : 1055655886@qq.com */ public class IPCBinder extends Binder { /** * 处理消息 * @param code 识别码 * @param data 调用transact的对象传送过去的参数 * @param reply 调用onTransact的对象返回的参数 * @param flags Java里面默认的native方法都是阻塞的,当不需要阻塞的时候设置为IBinder.FLAG_ONEWAY,否则设置为0 * @return * @throws RemoteException */ @Override protected boolean onTransact(final int code, final Parcel data, final Parcel reply, final int flags) throws RemoteException { data.enforceInterface(Contant.DESCRIPTOR); Bundle bundle = dealMessage(code,data.readBundle()); reply.writeNoException(); reply.writeBundle(bundle); return true; } /** * 获取当前Service,用于与Service通信 * @return */ public BaseIPCService getService(){ return BaseIPCService.this; } }

暂时还未找到如何实现异步通信

客户端发送消息

private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.d(TAG, "--- onServiceDisconnected --- "); connect = false; if (mConnectListener != null) { mConnectListener.onDisconnected(); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub if (service == null) { connect = false; Log.d(TAG, "--- onServiceConnected failed service == null ---"); if (mConnectListener != null) { mConnectListener.onConnected(false); } } else { Log.d(TAG, "--- onServiceConnected sucessed ---"); connect = true; if (mConnectListener != null) { mConnectListener.onConnected(true); } mIBinder = service; } } };

连接成功后通过可以获取到Binder对象 发送消息使用 mIBinder.transact(code, _data, _reply, 0);

/** * 向服务端发送消息 * @param code 消息类型 * @param bundle 消息体 * @return 返回值为服务器的返回 * @throws Exception */ public Bundle send(int code, Bundle bundle) throws Exception { if (mIBinder == null) { throw new NullPointerException("IBinder is Null"); } Bundle result = null; Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeBundle(bundle); mIBinder.transact(code, _data, _reply, 0); _reply.readException(); result = _reply.readBundle(); } catch (Exception e) { e.printStackTrace(); throw new Exception(e); } finally { _reply.recycle(); _data.recycle(); return result; } }

#Message通信 服务端的onBind是这么写的:

public IBinder onBind(Intent intent) { return mMessenger.getBinder(); }

那么点进去:

public IBinder getBinder() { return mTarget.asBinder(); }

可以看到返回的是mTarget.asBinder();

mTarget是哪来的呢?

HandlerThread mHandlerThread = new HandlerThread("BaseMsgIPCService"); mHandlerThread.start(); Handler mHandler= new Handler(mHandlerThread.getLooper()){ @Override public void handleMessage(Message msgfromClient) { super.handleMessage(msgfromClient); } }; mMessenger= new Messenger(mHandler); public Messenger(Handler target) { mTarget = target.getIMessenger(); }

原来是Handler返回的,我们继续跟进去

final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } }

mTarget是一个MessengerImpl对象,那么asBinder实际上是返回this,也就是MessengerImpl对象; 客户端 客户端首先通过onServiceConnected拿到sevice(Ibinder)对象,这里没什么特殊的,我们平时的写法也是这样的,只不过我们平时会这么写: IMessenger.Stub.asInterface(service)拿到接口对象进行调用; 而,我们的代码中是 mService = new Messenger(service); 跟进去,你会发现:

public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }

和我们平时的写法一模一样! 到这里就可以明白,客户端与服务端通信,实际上和我们平时的写法没有任何区别,通过编写aidl文件,服务端onBind利用Stub编写接口实现返回;客户端利用回调得到的IBinder对象,使用IMessenger.Stub.asInterface(target)拿到接口实例进行调用。 (2)服务端与客户端通信 那么,客户端与服务端通信的确没什么特殊的地方,我们完全也可以编写个类似的aidl文件实现;那么服务端是如何与客户端通信的呢? 还记得,客户端send方法发送的是一个Message,这个Message.replyTo指向的是一个mMessenger,我们在Activity中初始化的。 那么将消息发送到服务端,肯定是通过序列化与反序列化拿到Message对象,我们看下Message的反序列化的代码:

# Messageprivate void readFromParcel(Parcel source) { what = source.readInt(); arg1 = source.readInt(); arg2 = source.readInt(); if (source.readInt() != 0) { obj = source.readParcelable(getClass().getClassLoader()); } when = source.readLong(); data = source.readBundle(); replyTo = Messenger.readMessengerOrNullFromParcel(source); sendingUid = source.readInt(); }

主要看replyTo,调用的是Messenger.readMessengerOrNullFromParcel

public static Messenger readMessengerOrNullFromParcel(Parcel in) { IBinder b = in.readStrongBinder(); return b != null ? new Messenger(b) : null; } public static void writeMessengerOrNullToParcel(Messenger messenger, Parcel out) { out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder() : null); }

通过上面的writeMessengerOrNullToParcel可以看到,它将客户端的messenger.mTarget.asBinder()对象进行了恢复,客户端的message.mTarget.asBinder()是什么? 客户端也是通过Handler创建的Messenger,于是asBinder返回的是:

public Messenger(Handler target) { mTarget = target.getIMessenger(); } final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } } public IBinder getBinder() { return mTarget.asBinder(); }

那么asBinder,实际上就是MessengerImpl extends IMessenger.Stub 中的asBinder了。

#IMessenger.Stub@Override public android.os.IBinder asBinder(){return this;}

那么其实返回的就是MessengerImpl对象自己。到这里可以看到message.mTarget.asBinder()其实返回的是客户端的MessengerImpl对象。 最终,发送给客户端的代码是这么写的:

msgfromClient.replyTo.send(msgToClient);public void send(Message message) throws RemoteException { mTarget.send(message); }

这个mTarget实际上就是对客户端的MessengerImpl对象的封装,那么send(message)(屏蔽了transact/onTransact的细节),这个message最终肯定传到客户端的handler的handleMessage方法中。 Message源码分析部分摘抄自鸿洋_的博客

IPCCommunication github地址

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot 集成短信和邮件的配置示例详解
下一篇:计算机组成原理2(PCI总线结构框图)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~