应用Binder探索(上)

本文主要罗列demo代码,包括客户端Activity,服务端远程service、aidl及其Java接口文件,用来描述客户端和服务端应用binder交互流程。

大概简述一下此示例代码的功能,有一个名为BookManagerService的远程服务,它持有一个用于保存Book对象的list,并对外提供该list的get和add方法。而客户端Activity绑定服务并访问其接口。

  1. 客户端Activity在onCreate时绑定BookManagerService,连接成功即可生成IBookManager对象,通过该对象可以访问BookManagerService的对外接口。
  2.  BookManagerService设置了remote,是运行在另一个进程中的远程服务,在onCreate时为list加载两行数据,之后在onBind方法里返回serviceBinder对象。

首先是aidl文件:

//IBookManager.aidl
interface IBookManager {
     List<Book> getBookList();
     void addBook(in Book book);
}
//Book.aidl
parcelable Book;

其次是客户端Activity:

    private IBookManager mRemoteBookManager;
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            IBookManager bookManager = IBookManager.Stub.asInterface(service);
            mRemoteBookManager = bookManager;
            try {
               //mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient, 0);
                List<Book> list = bookManager.getBookList();
                Book newBook = new Book(3, "Android进阶");
                bookManager.addBook(newBook);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_book_manager);
        Intent intent = new Intent(this, BookManagerService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

最后是服务端BookManagerService:

    private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
    private Binder mBinder = new serviceBinder();
    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        mBookList.add(new Book(1, "Android"));
        mBookList.add(new Book(2, "Ios"));
    }

    public class serviceBinder extends IBookManager.Stub{
        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }@Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }
    }


程序属于在不同进程绑定一个服务,初次运行的大致流程是这样的:

  1. 客户端Activity进程向AMS发送一个绑定 BookManagerService服务的请求(其实这也是个binder请求,因为AMS运行在系统服务进程中);
  2. AMS例行检查,首先检查BookManagerService是否已经注册,哪个APP注册的(这些信息是在app安装时解析manifest获取的),然后检查启动BookManagerService的进程是否存在,因为BookManagerService设置了remote,所以此时进程是不存在的,于是会先把Service信息存下来,绑定请求押后,去创建一个新的进程。
  3. 新进程启动后,通知AMS准备就绪,AMS就会把刚才保存的Service信息发送给新进程去启动Service(例如oncreate),service启动完成后通知AMS。
  4. 接着AMS会把绑定的请求再发给BookManagerService,BookManagerService调用onbind,给AMS返回一个binder对象。
  5. AMS把binder对象返回给客户端Acitivty(onServiceConnected被调用)

        其实这些过程已经被android屏蔽了,应用上我们只需要关注两个对象,第一个是客户端Activity的onServiceConnected返回的BinderProxy对象,第二个是服务端BookManagerService的onBind返回的Binder对象。然而在应用上我们看到的是Stub和Proxy,Stub继承了Binder,而Proxy是BidnerProxy的包装类,不管BinderProxy还是Bidner都,它们实现了IBinder接口,可以用IBinder接收。

  1. IBookManager接口定义了getBookList和addBook方法,其中还继承了IInterface接口,多了个asBinder方法,接下的Stub和Proxy都实现了IBookManager接口。
  2. Stub类不仅继承了Bidner类还继承了IBookManager接口,而服务端BookManagerService的serviceBinder继承了Stub类,实现了getBookList和addBook方法(asBinder接口由Stub类实现),serviceBinder的对象mBinder被返回给AMS。
  3. 客户端Activity的onServiceConnected返回BinderProxy,通过IBookManager.Stub.asInterface方法包装成了Proxy对象,这样便可调用Proxy实现的getBookList和addBook方法,同时Proxy还实现了asBinder接口。

IBookManager接口:

public interface IBookManager extends IInterface {

    static final String DESCRIPTOR = "com.example.testbinder.IBookManager";
    static final int TRANSACTION_getBookList = (IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_addBook = (IBinder.FIRST_CALL_TRANSACTION + 1);

       public List<Book> getBookList()throws RemoteException;
       public void addBook(Book book)throws RemoteException;
}

Stub类:

public static abstract class Stub extends Binder implements IBookManager {
	public Stub() {
		this.attachInterface(this, DESCRIPTOR);
	}
	public static IBookManager asInterface(IBinder obj) {
		if ((obj == null)) {
			return null;
		}
		android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
		if (((iin != null) && (iin instanceof IBookManager))) {
			return ((IBookManager) iin);
		}
		return new IBookManager.Stub.Proxy(obj);
	}
	@Override
	public android.os.IBinder asBinder() {
		return this;
	}
	@Override
	public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
		switch (code) {
		case INTERFACE_TRANSACTION: {
			reply.writeString(DESCRIPTOR);
			return true;
		}
		case TRANSACTION_getBookList: {
			data.enforceInterface(DESCRIPTOR);
			List<Book> _result = this.getBookList();
			reply.writeNoException();
			reply.writeTypedList(_result);
			return true;
		}
		case TRANSACTION_addBook: {
			data.enforceInterface(DESCRIPTOR);
			Book _arg0;
			if ((0 != data.readInt())) {
				_arg0 = Book.CREATOR.createFromParcel(data);
			} else {
				_arg0 = null;
			}
			this.addBook(_arg0);
			reply.writeNoException();
			return true;
		}
		return super.onTransact(code, data, reply, flags);
	}
       @Override
    public List<Book> getBookList() throws RemoteException {
        // 待服务端实现        
               return null;
    }

    @Override
    public void addBook(Book book) throws RemoteException {
        // 待服务端实现    
       }   
 }

Proxy类:

private static class Proxy implements IBookManager {
	private IBinder mRemote;
	Proxy(IBinder remote) {
		mRemote = remote;
	}
	@Override
	public IBinder asBinder() {
		return mRemote;
	}
	public String getInterfaceDescriptor() {
		return DESCRIPTOR;
	}
	@Override
	public List<Book> getBookList()throws RemoteException {
		Parcel _data = Parcel.obtain();
		Parcel _reply = Parcel.obtain();
		List<Book> _result;
		try {
			_data.writeInterfaceToken(DESCRIPTOR);
			mRemote.transact(Stub.TRANSACTION_getBookList, _data,_reply, 0);
			_reply.readException();
			_result = _reply.createTypedArrayList(Book.CREATOR);
		} finally {
			_reply.recycle();
			_data.recycle();
		}
		return _result;
	}
	@Override
	public void addBook(Book book)throws RemoteException {
		Parcel _data = Parcel.obtain();
		Parcel _reply = Parcel.obtain();
		try {
			_data.writeInterfaceToken(DESCRIPTOR);
			if ((book != null)) {
				_data.writeInt(1);
				book.writeToParcel(_data, 0);
			} else {
				_data.writeInt(0);
			}
			mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
			_reply.readException();
		} finally {
			_reply.recycle();
			_data.recycle();
		}
	}
}	    

       

        在下一篇文章中,描述binder通信过程。








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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值