安卓进程通讯之aidl

安卓进程通讯之aidl

通过bindservice可以启动远程service并在onServiceConnected拿到远程service传来的 IBinder,但是如何把IBinder转换成对应的接口类型呢?这里就要使用aidl。
这里以图书管理为例讲解aidl。
首先,确定远程service需要提供的功能。
1,获取图书列表;
2,往图书列表中加入一本书;
3,注册新书到货的观察者;
4,注销新书到货观察者;

先声明 Book实体类,这里注意,跨进程传输的对象必须实现parcel接口

public class Book implements Parcelable{
private int id;
private String name;

    @Override
public String toString() {
    return "Book [id=" + id + ", name=" + name + "]";
}

    public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

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

    public Book(int id, String name) {
    super();
    this.id = id;
    this.name = name;
}

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }
public static final Parcelable.Creator<Book> CREATOR=new Creator<Book>() {

    @Override
    public Book[] newArray(int size) {
        // TODO Auto-generated method stub
        return new Book[size];
    }

    @Override
    public Book createFromParcel(Parcel source) {
        // TODO Auto-generated method stub
        return new Book(source);
    }
};
private Book(Parcel parcel){
    this.id=parcel.readInt();
    this.name=parcel.readString();
}
}

同时创建文件Book.aidl声明Book类是parcelable

package com.example.aidlbookmanager;
parcelable Book;

监听新书回调接口OnNewBookListener
该不能是普通java接口,需要是aidl接口才可以。
创建OnNewBookListener.aidl文件,文件内容如下

package com.example.aidlbookmanager;
import com.example.aidlbookmanager.Book;

interface OnNewBookListener{
void onNewBook(in Book book);
}

这里需要引入Book包,在onNewBook方法里的in表示方向,对远程service而言是从客户端传入的.

创建IBookManager.aidl文件,内容如下

package com.example.aidlbookmanager;
import com.example.aidlbookmanager.Book;
import com.example.aidlbookmanager.OnNewBookListener;
 interface IBookManager{
 List<Book> getBookList();
 void addBook(in Book book);
 void register(OnNewBookListener listener);
 void unregister(OnNewBookListener listener);
 }

创建完成后会在在gen下生成对应的IBookManager.java文件

创建IBookManager的实现类,并重写抽象方法

public class MyBinder extends IBookManager.Stub{
/**
     * 图书列表 线程安全
     */
    private CopyOnWriteArrayList<Book> bookList=new CopyOnWriteArrayList<Book>();
    /**
     * 观察者列表 对象不能跨进程传递 删除观察者需要用到此列表
     */
    private RemoteCallbackList<OnNewBookListener> listenerList=new RemoteCallbackList<OnNewBookListener>();

        @Override
        public List<Book> getBookList() throws RemoteException {
            // TODO Auto-generated method stub
            Log.i("TAG", "getBookList thread is "+Thread.currentThread().getName());
            return bookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            // TODO Auto-generated method stub
            bookList.add(book);
        }

        @Override
        public void register(OnNewBookListener listener) throws RemoteException {
            // TODO Auto-generated method stub
            listenerList.register(listener);

        }

        @Override
        public void unregister(OnNewBookListener listener)
                throws RemoteException {
            // TODO Auto-generated method stub
            listenerList.unregister(listener);
        }

    }

这里是多个进程访问通一个数据,需要用到安全的CopyOnWriteArrayList来做线程同步,
接口集合不能用List,因为跨进程是不能传输对象的,对象跨进程传输的本质的序列化和反序列化,虽然在客户端在注册和注销上传递的是同一个对象,但是在远程service这边收到的是不同的对象,就会导致不能正常删除观察者,使用RemoteCallbackList可以解决这一问题。

创建远程service
在onbind中返回MyBinder的实例即可

@Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return new MyBinder();
    }

客户端代码
首先把服务器端的aidl文件放到自己项目中,注意包名一致
通过 bindService(intent, conn,BIND_AUTO_CREATE )既可以连接远程服务器
在连接成功后,会回调ServiceConnection实现类的 onServiceConnected方法 ,在使用IBookManager.Stub的asInterface方法把IBinder转换成对应的接口类型就可以正常使用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值