使用AIDL实现进程间通信

转载请注明出处,点击此处 查看更多精彩内容。

AIDL(Android Interface Definition Language) 是一种IDL语言,用于生成可以在Android设备上两个进程之间进行进程间通信(IPC)的代码。

以下的文件创建过程是基于Android Studio。

使用AIDL实现进程间通信步骤:

1. 创建.aidl文件

该文件结构类似与Java中的接口,定义了可用的方法和数据的接口。
右键点击程序包 --> new --> AIDL --> AIDL File 创建IMyAidlInterface.aidl文件,这时Android Studio会自动创建一个和java同级的目录aidl,并在此目录下生成包和.aidl文件。如图:
.aidl文件所在目录结构
现在定义一个求和的方法,修改后的IMyAidlInterface文件如下:

package ***.***.***;

interface IMyAidlInterface {

    int sum(int a, int b);

}

2. 生成.aidl文件对应的.java文件

通过 Build --> Rebuild Project 重新构建项目生成.aidl文件对应的.java文件,如图所示:
对应的.java文件所在目录结构

3. 创建共享Service

创建一个Service用于和其他进程共享数据和方法

    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;

    public class MyService extends Service {

        public MyService() {
        }

        @Override
        public IBinder onBind(Intent intent) {
           return mBinder;
        }

        IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {

            @Override
            public int sum(int a, int b) throws RemoteException {
                return a+b;
            }

        };

    }

Stub是生成IMyAidlInterface.java时自动生成的一个抽象内部类,继承自Binder。
由于在其他进程中并不能知道这个Service的名字,所以启动这个Service的时候需要使用隐式的Intent,因此需要给Service添加过滤器:

    <service
        android:name=".MyService"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.mm.action.aidl" />
        </intent-filter>
    </service>

然后在启动Service的时候使用"com.mm.action.aidl"作为Action即可。

4. 启动共享Service

    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取定义的接口
            IMyAidlInterface aidlInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                // 调用接口中的方法
                System.out.println(aidlInterface.sum(100, 3));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    // 使用bindService启动Service
    bindService(new Intent("com.mm.action.aidl"), connection, BIND_AUTO_CREATE);

有了以上的这些配置,就能先运行当前项目测试一下了,如果能正确打印数字的和,则以上配置就没有问题了。

5. 在其他项目中共享Service

新建一个项目,拷贝上面的.aidl文件到项目的同名目录下,然后Rebuild一下生成对应的.java文件,然后根据上面启动Service的方法启动即可。发布应用时,共享Service的APK要使用同一个签名,否则无法正常共享。

6. 传递复杂对象

6.1

使用AIDL可以直接传递基本数据类型(int long float double)、String、List和Map,如果要传递复杂对象,需要使该对象实现Parcelable接口,并创建同名的.aidl文件。
现在我们创建Person.aidl和Person.java
Person.aidl:

package ***;

parcelable Person;

Person.java :

    import android.os.Parcel;
    import android.os.Parcelable;

    /**
     * Created by shichaohui on 15/11/4.
     */
    public class Person implements Parcelable {

        String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

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

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

        public Person() {
        }

        protected Person(Parcel in) {
            this.name = in.readString();
        }

        public static final Creator<Person> CREATOR = new Creator<Person>() {
            public Person createFromParcel(Parcel source) {
                return new Person(source);
            }
    
            public Person[] newArray(int size) {
                return new Person[size];
            }
        };
    }
6.2

修改IMyAidlInterface.aidl,添加一个获取Person的方法,修改后的IMyAidlInterface.aidl文件:

    import com.***.androidtest.Person;

    interface IMyAidlInterface {

        int sum(int a, int b);

        Person getPerson();
    }

这里一定要记得import Person.java所在的包,不然会构建失败。

6.3

修改MyService,实现getPerson()方法:

    public class MyService extends Service {

        ...

        IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {

           ...

            @Override
            public Person getPerson() throws RemoteException {
                Person person = new Person();
                person.setName("nammmmme");
                return person;
            }

        };

    }

最后就可以和使用sum()方法一样使用getPerson()方法了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值