进程间通讯之 —— AIDL

最近做的项目中有需要到进程间通讯,之后通过比对之后选择了 AIDL 作为进程之间的通讯协议。下面简单记录一下关于 AIDL 这方面的一些开发调研与经验。

官方文档: https://developer.android.com/guide/components/aidl#Calling

调研的技术点:

  1. 支持多种数据类型。如:int,String,基本数据类型,实现 Parcelabel 对象等等。
  2. 可以实现一个进程同时对接多个 APK。
  3. 传递对象
  4. 对象.java  对象.aidl 这两个文件需要在同一个包名下。

具体的操作流程:

服务端 Server:

  • 在清单文件中注册服务。
     <service android:name="com.example.edwardadmin.service.RmoteService">
            <intent-filter>
                <action android:name="android.intent.action.RESPOND_AIDL_MESSAGE"></action>
            </intent-filter>
        </service>
  • 在文件夹创建 AIDL File

                

  • 自动生成的 interface.aidl 
// 需要手动导入对象的包名
interface IRomteAidlInterface {
    /**
     * 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);
    //基本类型
    String getPersonUserName();

    String getPersonUserAge();
    //设置接口
    void setPersonInfo(String name,String age);
    //获取对象
    Person getPerson();
}
  • 创建服务 server

public class RmoteService extends Service {

    private static final String TAG = "RmoteService";

    private Person mPerson;
    private String mUserName;
    private String mUserAge;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind Service success!");
        mPerson = new Person("test test ", "24");
        return new RomteBinder();
    }

    // 实现定义的 Stub 接口
    class RomteBinder extends IRomteAidlInterface.Stub {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public String getPersonUserName() throws RemoteException {
            mUserName = mPerson.getmUserName();
            Log.d(TAG, "Person mUserName = " + mUserName);
            return mUserName;
        }

        @Override
        public String getPersonUserAge() throws RemoteException {
            mUserAge = mPerson.getmUserAge();
            Log.d(TAG, "Person mUserAge = " + mUserAge);
            return mUserAge;
        }

        @Override
        public void setPersonInfo(String name, String age) throws RemoteException {
            mPerson = new Person(name, age);
        }

        @Override
        public Person getPerson() throws RemoteException {
            return new Person("对象name","对象age");
        }

    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}
  • 传输对象类型,必须实现 Parcelable 接口

 因为在 AIDL 传输对象数据时,是要进行序列化和反序列化。所以需要实现 Parcelable 接口。

public class Person implements Parcelable {

    private String mUserName;
    private String mUserAge;

    public Person(String username, String userage) {
        mUserName = username;
        mUserAge = userage;
    }

    public String getmUserName() {
        return mUserName;
    }

    public String getmUserAge() {
        return mUserAge;
    }

    @Override
    public String toString() {
        return super.toString();
    }

    protected Person(Parcel in) {
        mUserName = in.readString();
        mUserAge = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mUserName);
        dest.writeString(mUserAge);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}
  •  实体类的必须和 aidl 放在同样的包名下

           

客户端 Client

  • 把服务端的 aidl 部分拷贝到客户端,同样的目录结构。
  • 绑定服务,需要服务端的服务类路径,以及进程的包名

    private void bindService() {
        Intent serviceIntent = new Intent();
        serviceIntent.setAction(BIND_SERVICE_ACTION);
        serviceIntent.setComponent(new ComponentName("com.example.edwardadmin.aidlserver", "com.example.edwardadmin.service.RmoteService"));
        bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
        Log.d(TAG, "bindService");
    }
  • 在服务绑定成功之后,生成  IRomteAidlInterface
    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            iRomteAidlInterface = IRomteAidlInterface.Stub.asInterface(iBinder);
            Log.i(TAG, "onServiceConnected: " + componentName);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            iRomteAidlInterface = null;
            Log.i(TAG, "onServiceDisconnected: ");
        }
    };
  • 通过 IRomteAidlInterface 对象以及定义的 Stub 接口,进行通讯。

好了,AIDL 通讯就简单介绍到这里,具体如何定义接口就需要看需求了。

扫描二维码关注公众号,回复: 9058554 查看本文章
发布了48 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jacksinrow/article/details/86677386