Android进阶之AIDL的使用详解

移动开发 作者: 2024-08-22 20:50:01
原文首发于微信公众号:jzman-blog,欢迎关注交流!AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口,在 Android 中,进程之间无法共享
  1. 创建.aildl 文件
  2. 具体的业务对象实现基于 .aidl 文件生成的接口
  3. 向客户端公开接口
  4. 客户端远程调用
  5. 验证 AIDL

创建.aildl 文件

  1. java 的 8 种数据类型:byte、short、int、long、float、double、boolean、char
  2. 除此之外支持 String、charSequence、List、Map
  3. 自定义数据类型
// IPersonAidlInterface.aidl
package com.manu.aidldemo;
// Declare any non-default types here with import statements
interface IPersonAidlInterface {
    //具体的业务
    void setName(String name);
    void setAge(int age);
    String getInfo();

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt,long aLong,boolean aBoolean,float aFloat,double aDouble,String aString);
}

具体的业务对象实现基于 .aidl 文件生成的接口

// Stub
public static abstract class Stub extends android.os.Binder implements com.manu.aidldemo.IPersonAidlInterface
// asInterface
public static com.manu.aidldemo.IPersonAidlInterface asInterface(android.os.IBinder obj){

    if ((obj==null)) {
        return null;
    }

    // 检索 Binder 对象是否是本地接口的实现
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

    if (((iin!=null)&&(iin instanceof com.manu.aidldemo.IPersonAidlInterface))) {
        return ((com.manu.aidldemo.IPersonAidlInterface)iin);
    }

    return new com.manu.aidldemo.IPersonAidlInterface.Stub.Proxy(obj);
}
// Binder
public class Binder implements IBinder {
    //...
}

//具体的业务
@Override 
public void setName(java.lang.String name) throws android.os.RemoteException{
    // 将数据序列化
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeString(name);
        // 这个方法会最终调用 onTransact 方法
        mRemote.transact(Stub.TRANSACTION_setName,_data,_reply,0);
        _reply.readException();
    }
    finally {
        _reply.recycle();
        _data.recycle();
    }
}
@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_setName:
        {
            //...
            // 最终调用了 Stub 里面的业务方法
            this.setName(_arg0);
            //...
        }
    }
}
/**
 * Created by jzman
 * Powered by 2018/3/8 0008.
 */
public class IPersonImpl extends IPersonAidlInterface.Stub {
    private String name;
    private int age;

    @Override
    public void setName(String name) throws RemoteException {
        this.name = name;
    }

    @Override
    public void setAge(int age) throws RemoteException {
        this.age = age;
    }

    @Override
    public String getInfo() throws RemoteException {
        return "My name is "+name+",age is "+age+"!";
    }

    @Override
    public void basicTypes(int anInt,String aString) throws RemoteException {

    }
}

向客户端公开接口

// Service
public class PersonService extends Service {
    public PersonService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new IPersonImpl();
    }
}
<service
    android:name=".PersonService"
    android:enabled="true"
    android:exported="true"
    android:process=":remote">
</service>

客户端远程调用

// Client
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private IPersonAidlInterface iPersonAidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void bindServiceClick(View view) {
        Log.i(TAG,"绑定服务...");
        Intent intent = new Intent(this,PersonService.class);
        // 绑定服务时自动创建服务
        bindService(intent,conn,Context.BIND_AUTO_CREATE);
    }

    public void unbindServiceClick(View view) {
        Log.i(TAG,"解绑服务...");
        unbindService(conn);
    }

    public void callRemoteClick(View view) {
        Log.i(TAG,"远程调用具体服务...");
        try {
            iPersonAidlInterface.setName("Tom");
            iPersonAidlInterface.setAge(10);
            String info = iPersonAidlInterface.getInfo();
            System.out.println("这是远程调用的服务信息:"+info);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name,IBinder service) {
            // 根据实际情况返回 IBinder 的本地对象或其代理对象
            iPersonAidlInterface = IPersonAidlInterface.Stub.asInterface(service);
            System.out.println("具体的业务对象:"+iPersonAidlInterface);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // Service 意外中断时调用
        }
    };
}

验证 AIDL

1. 相同进程
2. 不同进程

最后

原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_66865.html