Binder框架(1)

    Binder工作在linux层,是一个不需要硬件的驱动,从线程角度看,Binder代码运行在内核态,客户端程序使用Binder是通过系统调用完成的。

    Binder是一种整体架构,包含服务端接口,Binder驱动,客户端接口三个模块。

1. 服务端

    一个Binder服务端实际上就是一个Binder类的对象,该对象一旦创建,内部就启动一个隐藏线程。该线程会接收Binder驱动发送的消息,收到消息后,会执行到Binder对象的onTransact()函数,并按照该函数的参数执行不同的服务代码。

    因此,要实现一个Binder服务,就必须重载onTransact()方法。onTransact()函数的主要工作就是把onTransact函数的参数转换成服务函数的参数。onTransact()参数的来源是客户端调用transact()函数时输入的,因此,若transact()有固定格式的输入,那么onTransact()就有固定格式的输出。

2. Binder驱动

    Binder驱动是Android在内核中为完成进程间通信而专门设置的一个虚拟设备/dev/binder。任意一个服务端Binder对象被创建时,同时会在Binder驱动中创建一个mRemote对象,该对象的类型也是Binder类。客户端药访问远程服务时,都是通过mRemote对象。mRemote对象也重载了transact()方法,重载的内容主要包括:

  • 以线程间消息通信的模式,向服务端发送客户端传递过来的参数。
  • 挂起当前线程,当前线程正是客户发送线程,并等待服务端线程执行完指定服务函数后通知。
  • 接收服务端程序的通知,然后继续执行客户端线程,并返回到客户端代码区。

3. 客户端(应用程序端)

    客户端要想访问远程服务,必须获取远程服务在Binder对象中的mRemote引用。客户端获得mRemote后,就可以直接调用其transact方法了。

4. Binder例子

(1) Service端实现

    只要基于Binder类新建一个Service类,然后重载onTransace()函数就可以了。

    public class MusicPlayerService extends Binder {

        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) {

            switch (code) {      // code用于标识客户端期望调用服务端的哪个函数,由双方约定。该值与客户端的transact()函数中的第一个参数code的值是一致的(可以通过SDK中的aidl工具实现)。

                case PLAY: {

                     data.enforceInterface("MusicPlayerService");     // 为了某种校验,它与客户端的writeInterfaceToKen()对应。

                     String filePath = data.readString();                 // 从客户端读出传递过来的参数。参数在data变量中的位置需要客户端和服务端双方约定。

                     start(filePath);

                }

                    break;

                default:

                    break;

            }

        }

         public void start(String filePath) {

         }

         public void stop() {

         }

    }

(2) 客户端实现

    服务分为系统服务和客户端服务。系统服务指可以通过getSystemService()来获取的服务,客户端服务指应用程序提供的自定义服务。

    客户端如何获取Binder对象?

    AmS提供了startService()函数用于启动客户端服务。对于客户端来说,可以使用以下两个函数来和一个服务建立连接:

    i) public ComponentName startService(Intent intent);

       该函数用于启动intent指定的服务,服务启动后,客户端暂时还没有服务端的Binder引用,因此此时还不能调用任何服务的功能。

    ii) public boolean bindService(Intent Service, ServiceConnection conn, int flags);

        该函数用于绑定一个服务,第二个参数是interface类,它的定义为:

        public interface ServiceConnection {

            public void onServiceConnected(ComponentName name, IBinder service);

            public void onServiceDisconnected(ComponentName name);

        }

    当客户端请求AmS启动某个Service之后,该Service如果正常启动,那么AmS会远程调用ActivityThread类中的ApplicationThread对象,调用的参数中会包含Service的Binder引用,然后在ApplicationThread中会回调bindService的conn接口。

    因此,客户端可以在onServiceConnected方法中哦功能将其中的参数service保存为一个全局变量,从而在客户端的任何地方都可有随时调用该远程服务了。

posted on 2015-03-16 19:16  Jackwen  阅读(412)  评论(0编辑  收藏  举报