zoukankan      html  css  js  c++  java
  • 解析 Aidl 文件

    之前介绍过Android进程间通信(IPC)的使用,写过一些Demo。但仅仅是拿来用,并没有深入分析aidl是怎样可以做到进程间通信的。

    当创建 ITelephony.aidl文件时,aidl会为我们在gen目录中创建相应的文件。

    package com.android.internal.telephony;

    public interface ITelephony extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    //继承binder 实现所定义的aidl文件内的接口 //静态抽象类 服务端用 //Stub重载实现了OnTransact()方法,这样他就可以根据Proxy发来的客服端的请求, //进行解析并且调用对应请求的函数接口 public static abstract class Stub extends android.os.Binder implements com.android.internal.telephony.ITelephony { private static final java.lang.String DESCRIPTOR = "com.android.internal.telephony.ITelephony"; /** Construct the stub at attach it to the interface. */ //stub构造方法 public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.example.aidl.IRemoteService interface, generating a proxy if needed. 如果需要生成一个代理,为com.android.internal.telephony.itelephony接口铸造一个IBinder对象 */ //当bindService之后(绑定服务),客户端会得到一个Binder引用,是Binder,不是接口的实例, //然后就会用 aidl定义的接口.Stub.asInterface函数,去对这是不是跨进程的情况进行统一 //也就是不管你是在同一进程还是不同进程,在拿到Binder引用后, //调用 aidl定义的接口.Stub.asInterface(IBinder obj) //即可得到一个接口的实例


    //判断Ibinder是否为空
    //为空则返回空
    //若不为空且是aidl接口的实例 则返回true
    //调用 proxy()方法 并将IBinder传入

    public static com.android.internal.telephony.ITelephony asInterface(
    android.os.IBinder obj) {
    if ((obj == null)) {
    return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.android.internal.telephony.ITelephony))) {
    return ((com.android.internal.telephony.ITelephony) iin);
    }
    return new com.android.internal.telephony.ITelephony.Stub.Proxy(obj);
    }
    //返回自身类里包含的Binder对象实例
    public android.os.IBinder asBinder() {
    return this;
    }
    
    //根据Proxy发来的客服端的请求,
    //进行解析并且调用对应请求的函数接口
    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_endCall: {
    data.enforceInterface(DESCRIPTOR);
    boolean _result = this.endCall();
    reply.writeNoException();
    reply.writeInt(((_result) ? (1) : (0)));
    return true;
    }
    case TRANSACTION_answerRingingCall: {
    data.enforceInterface(DESCRIPTOR);
    this.answerRingingCall();
    reply.writeNoException();
    return true;
    }
    }
    return super.onTransact(code, data, reply, flags);
    }
    
    //这是一个静态类 他是一个服务端在客户端的代理 供客户端使用 
    // 调用asbinder方法 将定义的aidl文件内的方法发送给服务端
    private static class Proxy implements
    com.android.internal.telephony.ITelephony {
    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 boolean endCall() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    boolean _result;
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_endCall, _data, _reply, 0);
    _reply.readException();
    _result = (0 != _reply.readInt());
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    return _result;
    }
    
    // 挂断电话
    
    @Override
    public void answerRingingCall() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_answerRingingCall, _data,
    _reply, 0);
    _reply.readException();
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    }
    
    static final int TRANSACTION_endCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_answerRingingCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    
    public boolean endCall() throws android.os.RemoteException;
    
    // 挂断电话
    
    public void answerRingingCall() throws android.os.RemoteException;
    }
    
     
    
     
    
     
    
     

    其实,AIDL接口幕后是仰赖着IBinder界面的。所以,我们的应用程序可以选择使用IBinder接口,也可以使用AIDL接口。

    如果采取IBinder接口,就不必使用aidl.exe工具去产calInterface.java接口定义文件了,其接口类别较单纯一些。但是由于

    IBinder接口只提供单一函数(即transact()函数)来进行远距沟通,呼叫起来比较不方便。例如,当Calculator类别有多个函

    数时,myActivity要如何呼叫它们呢? 可以呼叫IBinder接口的transact()函数,再转而呼叫Calculator的各个函数。由于

    它并不太方便,所以Android提供Proxy/Stub结构的AIDL接口来化解这个问题。

     

     

     

     

     

     

     

     

     

     

     

     

    ---恢复内容结束---

  • 相关阅读:
    Python基础(一)
    计算机编程和编程语言
    初始Markdown
    Python模块
    Python递归以及面向过程编程
    Python推导式和匿名函数
    Python学闭包函数和装饰器
    Python函数的特点
    Python文件高级应用和如何使用函数
    Python字符编码和文件处理
  • 原文地址:https://www.cnblogs.com/mydomainlistentome/p/4694234.html
Copyright © 2011-2022 走看看