linux进程间通讯 aidl,极简开发 -- 进程间通讯框架非AIDL(IPCCommunication)

进程间通信

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

为什么要写这个框架

曾经听过一个人说过,程序中尽量使用通用组件或者框架,这样可以尽量的少写代码,这样有两个好处,一是少写代码就意味着少犯错误,二是可以多出喝咖啡的时间 ;

使用

手写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

5753377a9669

Binder.png

这个图是盗用别人的嘿嘿;

首先Activity通过调用bindService去绑定一个远程的服务(Service),绑定成功后返回一个IBinder对象。这时候双方就算是建立了连接了。

建立连接之后,双方就可以通过持有的IBinder进行通信。Activity使用IBinder的transact方法去给底层的Binder Driver(Linux层)发送消息间接调用底层的IBinder的execTransact方法。

而execTransact导致的结果就是调用onTransact方法。那么这时候事件的处理就可以在该环节进行了。

上层主要使用 这个方法进行通信 处理消息;

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的反序列化的代码:

# Message

private 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源码分析部分摘抄自鸿洋_的博客

欢迎大家follow,star,如果发现bug,希望您能够及时联系我

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值