Android10.0 Binder通信原理(七)-Framework binder示例

摘要:本节主要来讲解Android10.0 Binder在Framework中的示例

阅读本文大约需要花费15分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

  1. Android系统架构
  2. Android是怎么启动的
  3. Android 10.0系统启动之init进程
  4. Android10.0系统启动之Zygote进程
  5. Android 10.0 系统启动之SystemServer进程
  6. Android 10.0 系统服务之ActivityMnagerService
  7. Android10.0系统启动之Launcher(桌面)启动流程
  8. Android10.0应用进程创建过程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及启动流程
  10. Android 10.0 PackageManagerService(二)权限扫描
  11. Android 10.0 PackageManagerService(三)APK扫描
  12. Android 10.0 PackageManagerService(四)APK安装流程

《日志系统篇》

  1. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
  2. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
  3. Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
  4. Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入门篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++实例分析
  5. Android10.0 Binder通信原理(五)-Binder驱动分析
  6. Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击

1.Demo示例说明

Server进程目录结构:

Server
├─src
│  └─com
│       └─android
│               └─server
│                   ├─Server.java
│                   ├─MyService.java
│                   └─IMyService.java
├─Android.mk
└─serverTest

Client进程目录结构:

Client
├─src
│  └─com
│       └─android
│               └─client
│                   ├─Client.java
│                   ├─MyServiceProxy.java
│                   └─IMyService.java
├─Android.mk
└─clientTest

2. Demo 创建

2.1 Server端创建服务,提供接口

文件说明:

文件

说明

Server.java

Server入口

MyService.java

服务实体

IMyService.java

服务接口

Android.mk

编译文件

serverTest

可执行程序,保存在/system/bin中,

用来运行JAVA进程

[Server.java] 服务入口

package com.android.server;
import android.os.Looper;
import android.os.ServiceManager;

public class Server {
    public static void main(String args[]){
        System.out.println("Server service Start");
        Looper.prepareMainLooper(); //开启循环执行
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
           /*注册服务*/
        ServiceManager.addService("MyTestService", new MyService());
        Looper.loop();
    }
}

[MyService.java] 服务实体

package com.android.server;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.IInterface;
import android.os.RemoteException;

public class MyService extends Binder implements IMyService{ 
    private String value;
    public MyService() {
        attachInterface(this, IMyService.descriptor);
    }

    @Override
    public IBinder asBinder() {
        return this;
    }

    public static IMyService asInterface(IBinder obj) {
        if ((obj == null)) {
            return null;
        }

        IMyService in = (IMyService)obj.queryLocalInterface(IMyService.descriptor);
        if (in != null) {
            return in;
        }

        return null;
    }

       /*接收远程消息,进行处理*/
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
            case SET_VALUE_TRANSACTION: {
                data.enforceInterface(IMyService.descriptor);
                String str = data.readString(); //收到Client的数据
                setValue(str);
                reply.writeNoException();
                return true;
            }
            case GET_VALUE_TRANSACTION: {
                data.enforceInterface(IMyService.descriptor);
                String str = getValue();
                reply.writeNoException();
                reply.writeString(str); //把返回的数据写入Parcel,Client会进行接收
                return true;
            }

        }
        return super.onTransact(code, data, reply, flags);
    }

       /*服务的实现方法*/
     @Override
    public void   setValue(String str)  throws RemoteException {
        System.out.println("Client calling : setValue is " + str);
        this.value = str;
    }

        @Override
    public String getValue() throws RemoteException {
        System.out.println("Client calling : getValue is " + value);
        return value;
    }
}

[IMyService.java] 接口

package com.android.server;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;

public interface IMyService extends IInterface {
    static final  String descriptor = "com.android.server";
    public void   setValue(String str) throws RemoteException;
    public String getValue() throws RemoteException;

    static final int SET_VALUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
    static final int GET_VALUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
}

[Android.mk] 编译文件

LOCAL_PATH:= $(call my-dir)

#1.编译成serverTest.jar,编译到/system/framework中
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := serverTest
include $(BUILD_JAVA_LIBRARY)

#2.编译成serverTest进程,最终放入到/system/bin中,源文件是当前目录下的serverTest
include $(CLEAR_VARS)
LOCAL_MODULE := serverTest
LOCAL_SRC_FILES := serverTest
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)

[serverTest] 可执行文件,最终会拷贝到/system/bin中

#!/system/bin/sh
# Script to start "serverTest" on the device
#
base=/system
export CLASSPATH=$base/framework/serverTest.jar
exec app_process $base/bin com.android.server.Server "$@"

2.2 Client端获取服务,数据通信

文件说明:

文件

说明

Client.java

Client入口

MyServiceProxy.java

服务代理

IMyService.java

服务接口

Android.mk

编译命令

clientTest

可执行程序,保存在/system/bin中,

用来运行JAVA进程

[Client.java]  Client 入口

package com.android.client;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;

public class Client {

    public static void main(String[] args) throws RemoteException {
        System.out.println("Client start");
           //获取服务
        IBinder binder = ServiceManager.getService("MyTestService");
        //创建MyServiceProxy对象
        IMyService myService = new MyServiceProxy(binder);
           //通过MyServiceProxy对象调用接口的方法
        myService.setValue("Hello binder!");
        String str = myService.getValue();
        System.out.println("The value from server binder is " + str);
        System.out.println("Client end");
    }
}

[MyServiceProxy.java] 服务代理

package com.android.client;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

public class MyServiceProxy implements IMyService {
    private IBinder mRemote;

    public MyServiceProxy(IBinder remote) {
        mRemote = remote;
    }

    public String getInterfaceDescriptor() {
        return IMyService.descriptor;
    }

     /*接口方法实现*/
    @Override
    public void setValue(String str) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        try {
            data.writeInterfaceToken(IMyService.descriptor);
            data.writeString(str);        //把str数据写入Parcel,服务端会进行解析
            mRemote.transact(SET_VALUE_TRANSACTION, data, reply, 0);  //发送的code:SET_VALUE_TRANSACTION
            reply.readException();
        } finally {
            reply.recycle();
            data.recycle();
        }
    }

    @Override
    public String getValue() throws RemoteException {
        String str;
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        try {
            data.writeInterfaceToken(IMyService.descriptor);
            mRemote.transact(GET_VALUE_TRANSACTION, data, reply, 0); //发送的code:GET_VALUE_TRANSACTION
            reply.readException();
            str = reply.readString();        //读取服务端发来的内容
        } finally {
            reply.recycle();
            data.recycle();
        }
        return str;
    }

    @Override
    public IBinder asBinder() {
        return mRemote;
    }

}

[Android.mk] 编译文件

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := clientTest
include $(BUILD_JAVA_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := clientTest
LOCAL_SRC_FILES := clientTest
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)

[clientTest] 可执行程序

#!/system/bin/sh
# Script to start "clientTest" on the device
#
base=/system
export CLASSPATH=$base/framework/clientTest.jar
exec app_process $base/bin com.android.client.Client "$@"

3. 编译验证

3.1编译方式:

  1. 把上述代码文件夹push到 /frameworks/base/cmds/ 中
  2. source build.sh xxx                   #注:xxx为编译项目名
  3. cd /frameworks/base/cmds/
  4. mmm server
  5. mmm client


3.2结果验证:

  1. adb push ..../out/target/..../system/framework/serverTest.jar /system/framework
  2. adb push ..../out/target/..../system/framework/clientTest.jar /system/framework
  3. adb push ..../out/target/..../system/bin/serverTest. /system/bin
  4. adb push ..../out/target/..../system/bin/clientTest. /system/bin
  5. 开启两个cmd终端,执行adb shell
  6.  server端执行:/system/bin/serverTest

      

     7.Client端执行:/system.bin/clientTest 

      

运行结果:

Client:

Server:

我的微信公众号:IngresGe

发布了23 篇原创文章 · 获赞 55 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/yiranfeng/article/details/105313042