Android中跨进程通信方式之使用AIDL

首先创建一个User.java文件,实现Parcelable接口以用来进程间的对象传递

package com.example.aidl;

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

public class User implements Parcelable{
    private String username;
    private String password;
    public User(){
    }
    public User(String username, String password) {
        super();
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(username);
        dest.writeString(password);
    }
    public static final Parcelable.Creator<User> CREATOR = new Creator<User>() {

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }

        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }
    };
    private User(Parcel source){
        username = source.readString();
        password = source.readString();
    }
    @Override
    public String toString() {
        return username + "-" +password;
    }

}

然后创建User.aidl文件,声明User对象。如果AIDL中用到了自定义的Parcelable对象,一定要创建与之同名的aidl文件,并对它进行声明。

package com.example.aidl;

import com.example.aidl.User;

parcelable User;

parcelable User是对User对象的声明,它的类型是parcelable,不管User.java和User.aidl在没在一个包中,都要导包import com.example.aidl.User。

最后暴露客户端需要的方法接口IUserManager.aidl

package com.example.aidl;

import com.example.aidl.User;

interface IUserManager{
    List<User> findUser();
    void addUser(in User user);
}

这里具体说明一下AIDL中支持的数据类型
1、基本数据类型
2、String
3、List中的ArrayList,当然ArrayList中的元素也要是AIDL中支持数据类型
4、Map中的HashMap,当然key和value也要是AIDL中支持数据类型
5、Parcelable
6、AIDL接口本身

在IUserManager.aidl中我们暴露了两个方法给客户端,方法的定义与普通的接口基本一致,但是如果该方法有参数,参数除了基本数据类型,其他类型都要加in、out、inout,in表示输入型参数,out表示输出型参数,inout表示输入输出型参数。

当客户端是其它应用时,只需将aidl包完整拷入客户端程序即可,所以我们为了方便、不出错,将aidl相关的放入一个包下,这是符合开发规范的。

当IUserManager.aidl文件写完时,gen目录下会出现IUserManager.java文件。本文暂不对IUserManager.java进行深究,先讨论用法,下文对此进行深究。

此时创建远程Service,

    private CopyOnWriteArrayList<User> users = new CopyOnWriteArrayList<User>();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    private Binder mBinder = new IUserManager.Stub() {

        @Override
        public List<User> findUser() throws RemoteException {
            return users;
        }

        @Override
        public void addUser(User user) throws RemoteException {
            if(!users.contains(user)){
                users.add(user);
            }
        }
    }

创建IUserManager的静态内部类Stub对象作为Binder对象返回给绑定Service的Binder,并且实现接口中的两个方法给客户端调用。

客户端需要做的就是绑定此Service,即可调用服务端暴露给客户端的方法。

Intent intent = new Intent();
                intent.setClass(MainActivity.this, AIDLService.class);
                bindService(intent, connAIDL, Context.BIND_AUTO_CREATE);

connAIDL

        private ServiceConnection connAIDL = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            userManager = IUserManager.Stub.asInterface(service);
            try {
                List<com.example.aidl.User> users = userManager.findUser();

                System.out.println(users);
                userManager.addUser(new com.example.aidl.User("wangwu", "789"));
                users = userManager.findUser();
                System.out.println(users);

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    };

userManager = IUserManager.Stub.asInterface(service)是以绑定的Service返回的Binder对象创建IUserManager对象,该对象便可调用服务端暴露给客户端的方法。
userManager.findUser();
userManager.addUser(new com.example.aidl.User(“wangwu”, “789”));

注意:客户端调用服务端暴露的方法时,客户端线程会挂起,等待服务端方法运行,服务端的方法是运行在Binder线程池中的,因此不需要对这些方法开新的子线程异步执行,服务端方法运行结束时,返回给客户端,客户端线程才能继续运行。所以一旦服务端的方法需要长时间时,客户端必须在子线程中调用,防止ANR。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值