现在的位置: 首页 > 综合 > 正文

【内核研究】Binder服务端设计

2017年02月09日 ⁄ 综合 ⁄ 共 1208字 ⁄ 字号 评论关闭

设计Server端很简单,从代码的角度来讲,只要基于Binder类新建一个Server类即可。以下以设计一个MusicPlayerService类为例。

假设该Service仅提供两个方法:start(String filePath)和stop(),那么该类的代码可以如下:

public class MusicPlayerService extends Binder {
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        return super.onTransact(code, data, reply, flags);
    }

    public void start(String filePath) {

    }

    public void stop() {
        
    }
}

当要启动该服务时,只需要初始化一个MusicPlayerService对象即可。比如可以在主Activity里面初始化一个MusicPlayerService,然后运行,此时可以在ddms中发现多了一个线程,如图所示。

如果不创建MusicPlayerService,则只有2个Binder对象对应的线程。

http://blog.csdn.net/manoel/article/details/39500351

定义了服务类后,接下来需要重载onTrasact()方法,并从data变量中读出客户端传递的参数,比如start()方法所需要的filePath变量。

然而,这里有个问题,服务端如何知道这个参数在data变量中的位置?因此,这就需要调用者和服务者双方有个约定。

这里假定客户端在传入的包裹data中放入的第一个数据就是filePath变量,那么,onTransact()的代码可以如下所示:

        switch (code) {
            case 1000:
                data.enforceInterface("MusicPlayerService");
                String filePath = data.readString();
                start(filePath);
                // replay.writeXXX();
                break;
        }

code变量用于标识客户端期望调用服务端的哪个函数,因此,双方需要约定一组int值,不同的值代表不同的服务端函数,该值和客户端的transact()函数中第一个参数code的值是一致的。这里假定1000是双方约定要调用start()函数的值。

enforceInterface()是为了某种校验,它与客户端的writeInterfaceToken()对应。

readString()用于从包裹中取出一个字符串。取出filePath变量后,就可以调用服务端的start()函数了。

如果该IPC调用的客户端期望返回一些结果,则可以在返回包裹reply中调用Parcel提供的相关函数写入相应的结果

抱歉!评论已关闭.