Android IPC进程间通信(从应用层源码分)《一》
来源:互联网 发布:阿里云如何注销 编辑:程序博客网 时间:2024/06/15 17:22
在Android系统中,里面涉及到大量的进程间通信(IPC),现在我想自己写一篇关于我对IPC的理解,理解有不对的地方还希望大家给指点出来,IPC我打算分两篇来写,第一篇主要介绍怎么自己写一个进程间通信及AIDL,第二篇就从应用层源码分析,进程间是怎么绑定Binder进行进程间通信的。
首先我们要知道Binder这个概念,到底什么事Binder,其实说简单点,它就是进程与进程间进行通信的一个桥梁。
在通常的情况下,我们写一个AIDL,首先会定义一个AIDL接口,我们就叫他CalculateInterface.aidl类,里面定义了
package com.example.aidl.calculate;interface CalculateInterface { double doCalculate(double a, double b); }
然后他就会在工程目录的gen下面产生一个同样类的名词.Java文件,点进去如下:
package com.example.aidl.calculate;public interface CalculateInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.example.aidl.calculate.CalculateInterface { private static final java.lang.String DESCRIPTOR = "com.example.aidl.calculate.CalculateInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an * com.example.aidl.calculate.CalculateInterface interface, generating a * proxy if needed. */ public static com.example.aidl.calculate.CalculateInterface asInterface( android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.example.aidl.calculate.CalculateInterface))) { return ((com.example.aidl.calculate.CalculateInterface) iin); } return new com.example.aidl.calculate.CalculateInterface.Stub.Proxy( obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_doCalculate: { data.enforceInterface(DESCRIPTOR); double _arg0; _arg0 = data.readDouble(); double _arg1; _arg1 = data.readDouble(); double _result = this.doCalculate(_arg0, _arg1); reply.writeNoException(); reply.writeDouble(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.example.aidl.calculate.CalculateInterface { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public double doCalculate(double a, double b) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); double _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeDouble(a); _data.writeDouble(b); mRemote.transact(Stub.TRANSACTION_doCalculate, _data, _reply, 0); _reply.readException(); _result = _reply.readDouble(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_doCalculate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public double doCalculate(double a, double b) throws android.os.RemoteException;}
每一个AIDL生成的java文件,都必须有一个纯根(Stud)和一个代理类Proxy,在进程通讯中,Proxy主要负责发送数据,Stub主要负责接收数据,打一个比方,我们客户端发送数据的时候,是通过客户端的Proxy发送数据给服务端,然后服务端在Stub中就会回调onTransact方法,将数据读取出来,调用相应的方法,这样就完成了两个进程的通讯。
接下来我们自己写一个AIDL,不需要写AIDL文件和生成的代码,这样可以更好的看清楚两个进程是怎么发送数据和接受数据的。
我们首先新建一个接口,我取名叫IBookManager,继承IInterface这个接口,和写AIDL这个接口有点像,这里面也是写
public interface IBookManager extends IInterface{ //这是进程通讯的域名 static final String DESCRIPTOR = "com.example.aidl.calculate.IBookManager"; //给接口里面的方法定义一个ID,因为进程通讯里面,服务端是不认识我们所传的方法名,只认识ID,通过ID查找相应的方法。 static final int TRANSACTION_getBook = IBinder.FIRST_CALL_TRANSACTION+1; //接口方法 public double getBook(double a1,double a2) throws RemoteException; //BookManagerImpl相当于AIDL中的纯根(Stub) public class BookManagerImplStub extends Binder implements IBookManager{ //初始化绑定信息 public BookManagerImplStub() { this.attachInterface(this, DESCRIPTOR); } //这个相当于Stub中的代理类 //官方解释:一个内部对象到一个com.example.aidl.calculateIBookManager接口,生成一个 //如果需要代理。 public static IBookManager asInterface(IBinder iBinder){ if(iBinder == null){ return null; } //这里是判断是否在同一个进程,如果在就把自身给反回,如果不是就交给Prixy代理类 android.os.IInterface iin = iBinder.queryLocalInterface(DESCRIPTOR); if((iin != null) && (iin instanceof IBookManager)){ return (IBookManager)iin; } return new Proxy(iBinder); } @Override public IBinder asBinder() { return this; } @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION:{ reply.writeString(DESCRIPTOR); return true; } //这个就是在服务端接受到的消息ID,通过消息ID查找相应的方法 case TRANSACTION_getBook:{ data.enforceInterface(DESCRIPTOR); //这些取数据底层都是使用NDK,C/C++写的。 double a1; a1 = data.readDouble(); double a2; a2 = data.readDouble(); //这里是得到值回调getBook方法 double result = this.getBook(a1, a2); reply.writeNoException(); reply.writeDouble(result); return true; } } return super.onTransact(code, data, reply, flags); } @Override public double getBook(double a1, double a2) throws RemoteException { return a1 + a2; } //这个类部类中很重要的成员,负责发送数据 public static class Proxy implements IBookManager{ private IBinder iBinder; public Proxy(IBinder iBinder){ this.iBinder = iBinder; } @Override public IBinder asBinder() { return iBinder; } @Override public double getBook(double a1, double a2) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); double result = 0; try { //验证通讯的Token,为了安全 data.writeInterfaceToken(DESCRIPTOR); //写入数据 data.writeDouble(a1); data.writeDouble(a2); iBinder.transact(TRANSACTION_getBook, data, reply, 0); reply.readException(); result = reply.readDouble(); } catch (Exception e) { reply.recycle(); data.recycle(); } return result; } } }}
这代码咋一看,怎么和自动生成的代码一摸一样,确实是一摸一样,这里只是为了让大家看得更清楚一点,代码里面的注释还是写的比较详细,相信大家也能看懂,现在我说下怎么使用吧,把IBookManager这个接口类在客户端和服务端要保证一摸一样。
客户端使用的方法。
public class MainActivity extends Activity { private Button btnCalculate; private EditText etNum1; private EditText etNum2; private TextView tvResult; private IBookManager mService; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IBookManager.BookManagerImplStub.asInterface(service); try { //在客户端链接服务端成功了,设置一个死亡代理,就是当服务端死亡之后会回调这么方法 service.linkToDeath(recipient, 0); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent("com.example.aidldemoserver.BookService"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); etNum1 = (EditText) findViewById(R.id.et_num_one); etNum2 = (EditText) findViewById(R.id.et_num_two); tvResult = (TextView) findViewById(R.id.tv_result); btnCalculate = (Button) findViewById(R.id.btn_cal); btnCalculate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { logE("开始远程运算"); try { double num1 = Double.parseDouble(etNum1.getText().toString()); double num2 = Double.parseDouble(etNum2.getText().toString()); String answer = "计算结果:" + mService.getBook(num1, num2); tvResult.setText(answer); } catch (RemoteException e) { } } }); }}
服务端的使用方法:
public class BookService extends Service { private static final String TAG = "CalculateService"; @Override public IBinder onBind(Intent arg0) { return implStub; } @Override public void onCreate() { super.onCreate(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); } public IBookManager.BookManagerImplStub implStub = new IBookManager.BookManagerImplStub(); }
大致的流程就介绍到这里,有说得不对的地方还希望大家给指点出来,我会继续努力的,下篇我将从源码中介绍进程是怎么通信的。
Android IPC进程间通信(从应用层源码分)《二》
- Android IPC进程间通信(从应用层源码分)《一》
- Android IPC进程间通信(从应用层源码分)《二》
- android进程间通信ipc Messenger (一)
- Android系统分析之进程间通信IPC源码分析
- android-IPC进程间通信
- android IPC进程间通信
- Android IPC 进程间通信
- Android IPC 进程间通信
- Android IPC 进程间通信
- Android进程间通信IPC
- IPC-进程间通信(一)Messager
- android进程间通信(IPC)之AIDL
- Android进程间通信IPC机制Binder
- Android的IPC(进程间通信)机制
- Android IPC 进程间通信实现理解
- Android AIDL进程间通信(IPC)
- IPC——android进程间通信
- Android AIDL IPC实现进程间通信
- docker 详细使用教程
- UiAutomator2.0
- 安鑫 阿里、腾讯、百度,谁将成为互联网的老大
- spring boot下配置spring security笔记(请面试官进来看看)
- 用fragment减少activity
- Android IPC进程间通信(从应用层源码分)《一》
- JAVA实现万年历
- Centos7 关闭防火墙
- 【转】Qt之界面实现技巧
- Linux常用命令
- 优化 SQL SELECT 语句性能的 6 个简单技巧
- Mac如何开启关闭隐藏文件
- iOS 获取当前正在显示的ViewController
- a04#安装office 64位2013基础版提示机器存在32位office卸载未完全