Android AIDL 进程间通信

来源:互联网 发布:域名访问升级中 编辑:程序博客网 时间:2024/06/09 14:48

最近温习了AIDL的相关知识,写在这里,记录下来.

首先,先说下跨进程通信的方式有哪些。进程间的通信我们可以使用Messenger,可以在Intent中附加extras来传递信息,或者通过共享文件的方式来共享数据,还可以使用Binder方式来跨进程通信,也可以使用ContentProvider来进行跨进程的数据传递,通过网络的话使用socket也可以实现跨进程通信。

本章博客主要使用AIDL这种方式来进行进程间的通信,AIDL可以处理大量的并发请求,这是通过Messenger不能实现的。Messenger主要是为了传递信息的,如果调用服务端的方法的话,它也是不能做到的。但是可以使用AIDL来调用服务端的方法。

步骤:

1.服务端:

建立一个Service来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。

2.客户端:

通过bindService()绑定客户端,将服务端返回的Binder对象转化成AIDL接口所属的类型,就可以在客户端调用AIDL中的方法了。

3.创建AIDL文件:

AIDL文件支持的数据类型:

基本数据类型、
String和CharSequence、
List:只支持ArrayList、
Map:只支持HashMap
parcelable:所有实现了parcelable接口的对象、
AIDL:所有AIDL接口本身也可以在AIDL文件中使用

注:如果AIDL文件中用到了自定义的parcelable对象,那么,必须新建一个和它同名的AIDL文件,并在其中声明它为parcelable类型



具体实现:

创建bean类

package org.superzhao.aidltest;import android.os.Parcel;import android.os.Parcelable;public class User implements Parcelable {    private int userid;    private String username;    public User(int userid, String username) {        this.userid = userid;        this.username = username;    }    protected User(Parcel in) {        userid = in.readInt();        username = in.readString();    }    public static final Creator<User> CREATOR = new Creator<User>() {        @Override        public User createFromParcel(Parcel in) {            return new User(in);        }        @Override        public User[] newArray(int size) {            return new User[size];        }    };    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(userid);        dest.writeString(username);    }    @Override    public String toString() {        return "userid:" + userid +  ", username:" + username;    }}



创建AIDL文件:

IUserManager.aidl

// IUserManager.aidlpackage org.superzhao.aidltest;// Declare any non-default types here with import statementsimport org.superzhao.aidltest.User;interface IUserManager {     List<User> getUserList();     void addUser(in User user);}

user.aidl

// User.aidlpackage org.superzhao.aidltest;   parcelable User;


注:在创建完成aidl文件后,记得点击同步按钮或者clean project,否则在service端不能调用aidl中的方法,因为找不到。

Service端的实现:

package org.superzhao.aidltest;public class UserManagerService extends Service {    private static final String TAG = "UMS";    //在这个boolean值变化期间,不允许任何的插入操作,保持操作的原子性    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);    //CopyOnWriteArrayList是支持并发读写的List,自动进行线程同步    private CopyOnWriteArrayList<User> mUserList = new CopyOnWriteArrayList();    private CopyOnWriteArrayList<IOnNewUserArrivedListener> mListenerList = new CopyOnWriteArrayList();    @Override    public void onCreate() {        super.onCreate();        mUserList.add(new User(1,"jobs"));        mUserList.add(new User(2,"Mike"));    }//实现Stub中的抽象方法    private Binder mBinder = new IUserManager.Stub(){       //返回所有的用户        @Override        public List<User> getUserList() throws RemoteException {            return mUserList;        }        //添加用户        @Override        public void addUser(User user) throws RemoteException {            mUserList.add(user);        }    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }}

注:AIDL方法实在服务端的Binder线程池中执行的,因此当多个客户端同时连接的时候,会存在多个线程同时访问的情形,所以要在AIDL方法中处理线程同步,CopyOnWriteArrayList可以进行自动的线程同步。



客户端的实现:

package org.superzhao.aidltest;public class UserManagerActivity extends Activity {    private static final String TAG = "UMA";    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            IUserManager userManager = IUserManager.Stub.asInterface(service);            try {                mRemoteUserManager = userManager;                List<User> list = userManager.getUserList();                Log.i(TAG,"query list" + list.getClass().getCanonicalName());                Log.i(TAG,"query User list" + list.toString());                User user = new User(3,"Tom");                userManager.addUser(user);                List<User> newList = userManager.getUserList();                Log.i(TAG,"query User newList" + newList.toString());            } catch (RemoteException e) {                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name)         {        }    }; @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent(this,UserManagerService.class);        bindService(intent,mConnection,BIND_AUTO_CREATE);    }  @Override    protected void onDestroy() {       unbindService(mConnection);        super.onDestroy();    }}

总结一下:

使用AIDL的大致流程:

首先创建一个Service和一个AIDL接口,接着创建一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象,然后客户端就可以绑定服务端的Service,建立连接后就可以访问远程服务端的方法了。

0 0
原创粉丝点击