Binder service入门—Framework binder service

http://www.cloudchou.com/android/post-447.html

Binder service入门—Framework binder service

1.前言

Binder service入门系列:

上一篇介绍了natvie binder Service,本篇将介绍如何创建框架层binder service,并交给ServiceManager管理,客户端通过ServiceManager获取binder service的引用,然后测试binder service。

2.程序构成

Framework程序的开发必须要在源码开发环境下,本示例在vendor目录下建立了子目录shuame,然后把工程放在该目录下。

整个工程都可以在github上下载:https://github.com/cloudchou/FrameworkBinderTest

程序由服务端和客户端组成,服务端包括启动服务端的shell脚本bserver和放在framework目录的bserver.jar,客户端包括启动客户端的shell脚本bclient和放在framework目录的bclient.jar。

服务端 Android.mk如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
LOCAL_PATH:= $(call my-dir)
#生成framwork目录下的库bserver.jar
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := bserver 
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
#生成system/bin目录下的shell脚本bserver 
include $(CLEAR_VARS)
LOCAL_MODULE := bserver
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_SRC_FILES := bserver
include $(BUILD_PREBUILT)

客户端Android.mk如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LOCAL_PATH:= $(call my-dir)
 
#生成framwork目录下的库bclient.jar
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := bclient 
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
 
#生成system/bin目录下的shell脚本bclient
include $(CLEAR_VARS)
LOCAL_MODULE := bclient
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_SRC_FILES := bclient
include $(BUILD_PREBUILT)

3.程序源码构成

程序源码构成如下图所示:

framework_fbs

整个程序由服务端和客户端两部分组成,分别放在bserver和bclient目录,顶层目录只有一个Android.mk,该Android.mk的内容如下所示:

1
2
#包含所有子目录的makefiles,这样在顶层目录就可以编译所有模块
include $(call all-subdir-makefiles)

ICloudManager:服务端和客户端共用同一个接口文件ICloudManager.java,这里通过软链接实现共用,该接口声明了binder service供外界调用的方法。

CloudManager:binder service实体类,接收客户端的调用,进行相关逻辑处理后返回结果给客户端

BServer: 创建CloudManage对象,并调用ServiceManager注册binder service

CloudManagerProxy: binder service引用类,其实是binder service在客户端的代理,客户端通过该类调用服务端的操作

BClient: 测试binder service的客户端,先通过ServiceManager获取binder对象,然后再利用它创建CloudManagerProxy对象,通过CloudManagerProxy对象调用服务端的操

实现Framework binder service的步骤

  • 1) 定义binder service接口ICloudManager以及binder service的描述字符串,并为接口里的每个方法声明对应的操作常量:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    public interface ICloudManager extends IInterface {
      //binder sevice的描述字符串
      static final java.lang.String DESCRIPTOR = "com.cloud.test.BServer";
      //操作
      public void print(String str) throws RemoteException ;
      public int add(int a, int b) throws RemoteException ;
      //操作常量
      static final int TRANSACTION_print = 
             (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
      static final int TRANSACTION_add = 
            (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    声明binder service接口时必须从IInterface继承,IInterface接口如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    public interface IInterface
    {
        /**
         * Retrieve the Binder object associated with this interface.
         * You must use this instead of a plain cast, so that proxy objects
         * can return the correct result.
         */
        public IBinder asBinder();
    }

    IInterface声明了asBinder方法,用于转为Binder对象。

  • 2) 实现binder service实体类CloudManager
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    public class CloudManager extends Binder implements ICloudManager {  
       public CloudManager() {
          //保存 binder service描述字符串
          this.attachInterface(this, DESCRIPTOR);
       }
     
       @Override
       public IBinder asBinder() {
          return this;
       }
     
      //静态方法 转为ICloudManager接口对象
       public static com.cloud.test.ICloudManager asInterface(
             android.os.IBinder obj) {
          if ((obj == null)) {
             return null;
          }
          android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
          if (((iin != null) && 
              (iin instanceof com.cloud.test.ICloudManager))) {
             return ((com.cloud.test.ICloudManager) iin);
          }
          return null;
       }
     
      //接收客户端的调用,根据不同的操作码进行不同的处理,然后返回结果给客户端
       @Override
       protected boolean onTransact(int code, Parcel data, 
                                Parcel reply, int flags)
             throws RemoteException {
          switch (code) {
          case INTERFACE_TRANSACTION: {
             reply.writeString(DESCRIPTOR);
             return true;
          }
          case TRANSACTION_print: {
             data.enforceInterface(DESCRIPTOR);
             String str = data.readString();
             print(str);
             reply.writeNoException();
             return true;
          }
          case TRANSACTION_add: {
             data.enforceInterface(DESCRIPTOR);
             int a = data.readInt();
             int b = data.readInt();
             int c = add(a, b);
             reply.writeNoException();
             reply.writeInt(c);
             return true;
          }
          }
          return super.onTransact(code, data, reply, flags);
       }
     
       @Override
       public void print(String str) {
          System.out.println(str);
       }
     
       @Override
       public int add(int a, int b) {
          return a + b;
       }

    注意必须从Binder继承,并实现ICloudManager接口

  • 3) 实现服务端 BServer,创建CloudManager对象,并通过ServiceManager注册服务
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    public class BServer {
       public static void main(String[] args) {
          System.out.println("Cloud Manager Service Starts");
            //准备Looper
          Looper.prepareMainLooper();         
          android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            //注册binder service
          ServiceManager.addService("CloudService", new CloudManager());
            //进入Looper死循环,
          Looper.loop();
       }
     
    }
  • 4) 实现服务端脚本bserver
    1
    2
    3
    4
    
    base=/system
    export CLASSPATH=$base/framework/bserver.jar
    #调用app_process启动BServer
    exec app_process $base/bin com.cloud.test.BServer "$@"
  • 5) 实现binder service引用类CloudManagerProxy
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
    public class CloudManagerProxy implements ICloudManager {
       private android.os.IBinder mRemote;
        //保存通过ServiceManager查询服务得到的IBinder对象
       public CloudManagerProxy(android.os.IBinder remote) {
          mRemote = remote;
       }
     
       public java.lang.String getInterfaceDescriptor() {
          return DESCRIPTOR;
       }
     
       @Override
       public void print(String str) throws RemoteException {
          android.os.Parcel _data = android.os.Parcel.obtain();
          android.os.Parcel _reply = android.os.Parcel.obtain();
          try {
             _data.writeInterfaceToken(DESCRIPTOR);
             _data.writeString(str);
             mRemote.transact(TRANSACTION_print, _data, _reply, 0);
             _reply.readException();
          } finally {
             _reply.recycle();
             _data.recycle();
          }
       }
     
       @Override
       public int add(int a, int b) throws RemoteException {
          android.os.Parcel _data = android.os.Parcel.obtain();
          android.os.Parcel _reply = android.os.Parcel.obtain();
          int result=0;
          try {
             _data.writeInterfaceToken(DESCRIPTOR);
             _data.writeInt(a);
             _data.writeInt(b);
             mRemote.transact(TRANSACTION_add, _data, _reply, 0);
             _reply.readException();
             result=_reply.readInt();
          } finally {
             _reply.recycle();
             _data.recycle();
          }
          return result;
       }
     
       @Override
       public IBinder asBinder() {
          return mRemote;
       }
     
    }

    接口方法的实现实际上是通过调用IBinder对象的transact方法将调用参数传递给服务端,然后读取服务端返回的结果,再返回给接口方法的调用者。

  • 6) 实现客户端BClient
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    public class BClient { 
     
       /** 
        * 
        * @param args
        *            The command-line arguments
        * @throws RemoteException
        */
       public static void main(String[] args) throws RemoteException {
          System.out.println("==========Client starts===========");
           //通过ServiceManager查询服务获得IBinder对象
          IBinder binder = ServiceManager.getService("CloudService");
            //创建CloudManagerProxy对象
          ICloudManager manager = new CloudManagerProxy(binder);
            //通过CloudManagerProxy对象调用接口的方法
          manager.print("Hello world");
          int result = manager.add(2, 3);
          System.out.println("manager.add(2, 3)=" + result);
       }
    }
  • 7) 实现客户端脚本bclient
    1
    2
    3
    4
    
    base=/system
    export CLASSPATH=$base/framework/bclient.jar
    #调用app_process启动Bclient
    exec app_process $base/bin com.cloud.test.BClient "$@"

4.测试

编译时若提示错误,缺少framwork之类的jar,可先用mka framework编译framework,编译好之后再使用mm进行模块编译。

编译好之后将相关文件上传至手机并修改权限:

1
2
3
4
5
6
adb push bserver /system/bin
adb push bclient /system/bin
adb push bserver.jar /system/framework
adb push bclient.jar /system/framework
adb shell chmod 755 /system/bin/bserver
adb shell chmod 755 /system/bin/bclient

测试:

framework_test

id="uyan_ifr_2250251" scrolling="no" frameborder="0" src="http://api.v2.uyan.cc/v4/comment/?uid=1832578&frameid=2250251&du=&su=www.cloudchou.com%2F%3Fp%3D447&pic=http%3A%2F%2Fwww.cloudchou.com%2Fwp-content%2Fuploads%2F2014%2F04%2Fframework_fbs-1024x470.png&url=http%3A%2F%2Fwww.cloudchou.com%2Fandroid%2Fpost-447.html&title=Binder%20service%E5%85%A5%E9%97%A8%E2%80%94Framework%20binder%20service%20-%20Cloud%20Chou%27s%20Tech%20Blog&t=1477379136006" style="height: 1915px; width: 626px; display: block !important; border-width: 0px !important; border-style: none !important; overflow: hidden !important;">



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值