查看原文
其他

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

IngresGe IngresGe 2021-11-05

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

《Android取经之路》系列文章:

《系统启动篇》

Android取经之路——启动篇

Android系统架构

Android是怎么启动的

Android系统启动之init进程(一)

Android系统启动之init进程(二)

Android 10.0系统启动之init进程(三)

Android 10.0系统启动之init进程(四)

Android 10.0系统启动之Zygote进程(一)

Android 10.0系统启动之Zygote进程(二)

Android 10.0系统启动之Zygote进程(三)

Android 10.0系统启动之Zygote进程(四)

Android 10.0系统启动之SystemServer进程(一)

Android 10.0系统启动之SystemServer进程(二)

Android 10.0系统服务之AMS启动流程

Android 10.0系统启动之Launcher(桌面)启动流程

Android 10.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数据如何完成定向打击


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 := serverTestinclude $(BUILD_JAVA_LIBRARY)
#2.编译成serverTest进程,最终放入到/system/bin中,源文件是当前目录下的serverTestinclude $(CLEAR_VARS)LOCAL_MODULE := serverTestLOCAL_SRC_FILES := serverTestLOCAL_MODULE_PATH := $(TARGET_OUT)/binLOCAL_MODULE_CLASS := EXECUTABLESLOCAL_MODULE_TAGS := optionalinclude $(BUILD_PREBUILT)

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

#!/system/bin/sh# Script to start "serverTest" on the device#base=/systemexport CLASSPATH=$base/framework/serverTest.jarexec 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 := clientTestinclude $(BUILD_JAVA_LIBRARY)
include $(CLEAR_VARS)LOCAL_MODULE := clientTestLOCAL_SRC_FILES := clientTestLOCAL_MODULE_PATH := $(TARGET_OUT)/binLOCAL_MODULE_CLASS := EXECUTABLESLOCAL_MODULE_TAGS := optionalinclude $(BUILD_PREBUILT)

[clientTest] 可执行程序
#!/system/bin/sh# Script to start "clientTest" on the device#base=/systemexport CLASSPATH=$base/framework/clientTest.jarexec 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:
 



: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存