我们先来看看的架构图像
文章插图
图片来自的源码官站:
从的框架图中我们可以看到,应用程序框架层和系统服务层之间就是通过IPC 进行通讯的,说机制前,我们先了解几个特点
【05、人人都会设计模式:代理模式--Proxy】 下两个进程通信的简易流程
PS: 以上图是便于理解所以抽象出来一张图,真实的比这个过程复杂的多,这牵扯到 java 层的,层的等等「这不是我们讨论的重点」,方便我们理解,我们可以认为客户端的进程拿到服务端的引用,所以就可以调用服务端进程的方法了
说了这么多,这跟代理有个毛关系呢,别急我们写一个 AIDL 的实例分析一下:
AIDL demo 简单的 UML
根据 uml 写代码
我们写一个简单的通过进程调用进程返回一个字符串功能,为了方便起见,我们直接在一个项目中创建「 开启在另一个进程中,开两个 APP 进行通信大家可以自行试一下,道理一模一样的」
interface CustomAIDL {String getStr() ;}
此时我们点击一下
图标构造一下项目,此时会在 app\build\\\aidl\debug\包名\.java 文件「把 AS 切换到视图下很容易找到」,这是 IDE 帮我们自动生成的
/*** @Description 创建一个远程服务* @Creator TigerChain(创建者)*/public class AIDLRemoteService extends Service {private final CustomAIDL.Stub aidl = new CustomAIDL.Stub() {@Overridepublic String getStr() throws RemoteException {return " 我是远程服务返回的 HELLO ";}} ;@Nullable@Overridepublic IBinder onBind(Intent intent) {return aide;}}
public class AidlActivity extends AppCompatActivity implements View.OnClickListener{private CustomAIDL customAIDL ;... 省略若干代码// 客户端连接服务private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {customAIDL = CustomAIDL.Stub.asInterface(service) ;Log.e("service:","onServiceConnected") ;isServerStarted = true ;}@Overridepublic void onServiceDisconnected(ComponentName name) {customAIDL = null ;Log.e("service:","onServiceDisconnected") ;isServerStarted = false ;}} ;@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.btn_bind_service:// 绑定服务bindService(new Intent(AidlActivity.this,AIDLRemoteService.class),serviceConnection, Context.BIND_AUTO_CREATE) ;break ;case R.id.btn_test_method:if(!isServerStarted){Toast.makeText(AidlActivity.this,"请先绑定服务先",Toast.LENGTH_SHORT).show();return ;}try {String str = customAIDL.getStr();Toast.makeText(AidlActivity.this,str,Toast.LENGTH_SHORT).show();} catch (RemoteException e) {e.printStackTrace();}break ;default:break ;}}... 省略若干代码}
我这里给服务定义了一个,那说明这个服务是运行在一个新进程中的
我们看一下当前项目进程情况
的确是两个进程「 和分别在两个进程中」,我们定义的也显示出来了,看一下结果
怎么样,两个进程之间完美的进行了通信了
通个毛呢?这和 proxy 有个啥关系呀「巴拉巴拉这么久」,不要急吗?软件开发有一条宗旨:先让它运行起来「我们先把 Demo 运行起来再说吗:咳咳又到了吃药的时间了」,我们来分析一下上面的调用过程
过程分析
// 这里的 IInterface 代表远程 Server 对象有什么能力public interface CustomAIDL extends android.os.Interface {/*** Local-side IPC implementation stub class.*/// 在 server 端调用public static abstract class Stub extends android.os.Binder implements designpattern.jun.com.designpattern.CustomAIDL {private static final java.lang.String DESCRIPTOR = "designpattern.jun.com.designpattern.CustomAIDL";/*** Construct the stub at attach it to the interface.*/public Stub() {this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an designpattern.jun.com.designpattern.CustomAIDL interface,* generating a proxy if needed.* 其中的 android.os.IBinder obj 对象是驱动给们的,这个就是我们绑定 service ,在 onServiceConnecttion 回调里面这个对象拿到一个远程的 Service */public static designpattern.jun.com.designpattern.CustomAIDL asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof designpattern.jun.com.designpattern.CustomAIDL))) {// client 和 Server 在同一个进程调用 后面 debug 可以验证return ((designpattern.jun.com.designpattern.CustomAIDL) win);}// cliet 和 Server 不在同一个进程调用代理对象 后面 debug 可以验证return new designpattern.jun.com.designpattern.CustomAIDL.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic 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_getStr: {data.enforceInterface(DESCRIPTOR);java.lang.String _result = this.getStr();reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}// 运行在客户端 server 进程的远程代理,实现对远程对象的仿问private static class Proxy implements designpattern.jun.com.designpattern.CustomAIDL {private android.os.Binder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}@Overridepublic java.lang.String getStr() throws android.os.RemoteException {// 读取服务端写过来的数据android.os.Parcel _data = http://www.kingceram.com/post/android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getStr, _data, _reply, 0);_reply.readException();_result = _reply.readString();} finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_getStr = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public java.lang.String getStr() throws android.os.RemoteException;}
- 【STM32】引脚配置—F1与F4系列
- 图论系列:图的表示
- 一年养50头猪赚多少钱,养50头母猪一年能挣多少钱
- 一、Java反射机制具体是什么
- 仙人掌怎么养成木质化
- 水培红掌怎么养才能开花
- 黄金香柳养殖方法和注意事项
- 番茄怎么种植
- 蔷薇有哪些病虫害,应如何防治
- 常绿灌木有哪些树种