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

2023-10-26

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

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

《系统启动篇》

Android系统架构
Android是怎么启动的
Android 10.0系统启动之init进程
Android10.0系统启动之Zygote进程
Android 10.0 系统启动之SystemServer进程
Android 10.0 系统服务之ActivityMnagerService
Android10.0系统启动之Launcher(桌面)启动流程
Android10.0应用进程创建过程以及Zygote的fork流程
Android 10.0 PackageManagerService(一)工作原理及启动流程
Android 10.0 PackageManagerService(二)权限扫描
Android 10.0 PackageManagerService(三)APK扫描
Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》

Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​
《Binder通信原理》:

Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
Android10.0 Binder通信原理(二)-Binder入门篇
Android10.0 Binder通信原理(三)-ServiceManager篇
Android10.0 Binder通信原理(四)-Native-C\C++实例分析
Android10.0 Binder通信原理(五)-Binder驱动分析
Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
Android10.0 Binder通信原理(七)-Framework binder示例
Android10.0 Binder通信原理(八)-Framework层分析
Android10.0 Binder通信原理(九)-AIDL Binder示例
Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
Android10.0 Binder通信原理(十一)-Binder总结

《HwBinder通信原理》

HwBinder入门篇-Android10.0 HwBinder通信原理(一)
 HIDL详解-Android10.0 HwBinder通信原理(二)
HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
HwServiceManager篇-Android10.0 HwBinder通信原理(五)
Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》

编译系统入门篇-Android10.0编译系统(一)
编译环境初始化-Android10.0编译系统(二)
make编译过程-Android10.0编译系统(三)
Image打包流程-Android10.0编译系统(四
Kati详解-Android10.0编译系统(五)
Blueprint简介-Android10.0编译系统(六)
Blueprint代码详细分析-Android10.0编译系统(七)
Android.bp 语法浅析-Android10.0编译系统(八)
Ninja简介-Android10.0编译系统(九)
Ninja提升编译速度的方法-Android10.0编译系统(十)
Android10.0编译系统(十一)

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 入口

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编译方式:
把上述代码文件夹push到 /frameworks/base/cmds/ 中
source build.sh xxx                   #注:xxx为编译项目名
cd /frameworks/base/cmds/
mmm server
mmm client

3.2结果验证:
adb push ..../out/target/..../system/framework/serverTest.jar /system/framework
adb push ..../out/target/..../system/framework/clientTest.jar /system/framework
adb push ..../out/target/..../system/bin/serverTest. /system/bin
adb push ..../out/target/..../system/bin/clientTest. /system/bin
开启两个cmd终端,执行adb shell
 server端执行:/system/bin/serverTest
      

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

运行结果:

Client:

 

Server:

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android10.0 Binder通信原理(七)-Framework binder示例 的相关文章

随机推荐

  • VHDL棋类竞赛设计(一)

    设计要求 竞赛计时分两个阶段 每方50秒的规定用时和每方每步8秒的读秒 1 可分别显示甲乙双方规定用时阶段的已用时间和读秒阶段 8秒 的倒计时 2 设置两路输入模拟双方落子 在规定用时阶段 一路信号有效时会暂停本方计时并继续对方计时 而在读
  • 当easyui datagrid无数据时,显示特定值。如:没有数据

    lt html gt lt head gt lt meta charset UTF 8 gt lt title gt Basic DataGrid jQuery EasyUI Demo lt link rel stylesheet type
  • golang context使用reflect遍历获取所有的key和value

    golang中我们经常和context打交道 context实际上可以保存值 源码参见 usr local go src context context go context包中实际上有好几种私有的context类型 type emptyC
  • SpringCache笔记

    SpringCache 一 简介 1 缓存介绍 Spring 从 3 1 开始就引入了对 Cache 的支持 定义了 org springframework cache Cache 和 org springframework cache C
  • Python中float类型、float32类型和float64类型的表示精度,所需内存及其之间的转换

    1 表示精度和所需内存 float类型和float64类型是一样的 都需要64个bits 而float32需要32个bits 精度方面 float类型和float64类型在十进制中可以有16位 而float32类型在十进制中有8位 如下 g
  • 哔哩哔哩 API

    常用查看技巧 UP主所有视频 https www bilibili com medialist play 这里写uid from space 最新投稿的视频 https www bilibili com newlist html API 参
  • 完美解决Missing artifact com.oracle:ojdbc6:jar:11.2.0.4

    今天运行Tomcat项目时 在加载maven依赖的时候报了Missing artifact com oracle ojdbc6 jar 11 2 0 4的错 意思是说我缺少了com oracle ojdbc6 jar 11 2 0 4的依赖
  • 基于axios的二次封装

    1 axios的封装前言 axios是一个基于 promise 的 HTTP 库 目前 在vue react框架中也还是备受青睐 根据不同项目的业务 也有许多种不同的封装方法 但不同的应用场景 导致封装的代码风格不一 我这里想总结下封装的思
  • IDEA项目及字体样式和初始化等习惯配置

    前言 内容较多 按需检索 0 IDEA常用快捷键 1 主题设置 黑白 2 字体大小设置 3 全局编码 字符集改为utf 8 3 1 文件编码设置 3 2 新建项目字符集设置 3 3 单个文件编码设置 idea面板右下角 4 Maven配置
  • 如何设置环境变量

    首先强烈推荐一款免费的c 的IDE code block 免费的且自带了MinGW编译器 自己可以设置字体及大小 一般设置成12号比较合适 直接在界面上的Setting gt Editor 在右上角上有一个choose 然后就可以选择字体
  • 书城管理系统(前端)

    OK 兄弟们 测试上传图片的后端接口 测试分页条件查询后端接口 测试根据id查询后端接口 测试新增一本书的后端接口 测试修改一本书的后端接口 之前写好的后端接口 用postman测试一下 没有问题的话我们就试试开发前端 准备工作 用vue创
  • MYSQL 时间处理

    1 MySQL 获得当前时间戳函数 current timestamp current timestamp mysql gt select current timestamp current timestamp current timest
  • BERT使用过程中的碰到的那些报错

    BERT是谷歌2018年提出的语言模型 在十几个任务上达到了state of art 在这里本人在使用过程中总结了一下遇到的错误 BERT推荐在TPU上运行 但是资源有限在GPU上跑也行 不行也能在cpu上跑 ps就是有些慢 官方BERT的
  • RPA机器人成为金融银行业转型的重要推手

    当前 金融科技迅猛发展 金融业监管和合规要求不断提升 为了应对挑战 抓住机遇 银行业作为国民经济体系重要的组成部分和核心产业 早已开始探索科技赋能金融之路 当前银行业面临的难题 成熟的银行都会在其内部部署多个业务平台 管理系统 以实现业务流
  • arduino控制步进电机

    一 实物连接 二 代码实现 const int IN1 11 const int IN2 10 const int IN3 9 const int IN4 8 正转顺序 const char tab1 0x01 0x03 0x02 0x06
  • 【spring源码探索】一分钟搞懂RefreshScope的作用及实现原理

    前文 下述文章完全为个人阅读源码的随笔记录 如有错误 欢迎大家指出 过程 过程很坎坷 而且大家应该都不想看了吧 简而言之就是先写个测试DEMO 然后各种DEBUG 结论 这次先直接上结论 然后再通过测试DEMO给出验证 最后再去跟代码 Re
  • 怎样在Android访问php取回json数据

    1 代码 php代码 1 array array 2 username gt 杨铸 3 password gt 123456 4 user id gt 1 5 6 echojson encode array 2 代码 java代码 01 p
  • C语言算平均数,让用户输入一系列的正整数,输入-1表示输入结束,算出这些数字的平均数

    include
  • JAVA怎么替换html标签呢???

    之前遇见个需求 让我在下载文件时 把content里面的富文本存储的内容下载下来 但是又不能有html标签 那个我们怎们处理呢 废话不多说 上代码 StringBuffer stringBuffer new StringBuffer Str
  • Android10.0 Binder通信原理(七)-Framework binder示例

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系