关键词:
本章的内容主要说明如何在JavaFramework层和Native层自定义Client-Server组件,并且使用Binder进行通信。
一、Native Binder
源码目录结构:
alps/frameworks/native/cmds/NativeBinderDemo/
1 2 3 4 5 6 | |-NativeBinderDemo |---ClientDemo.cpp: 客户端程序 |---ServerDemo.cpp:服务端程序 |---IMyService.h:自定义的MyService服务的头文件 |---IMyService.cpp:自定义的MyService服务 |---Android.mk:源码build文件 |
1.1 服务端
alps/frameworks/native/cmds/NativeBinderDemo/ServerDemo.cpp
获取ServiceManager,注册service.myservice服务到ServiceManager,启动服务。
1 2 3 4 5 6 7 8 9 | #include "IMyService.h" int main() sp < IServiceManager > sm = defaultServiceManager(); //获取service manager引用 sm->addService(String16("service.myservice"), new BnMyService()); //注册名为"service.myservice"的服务到service manager ProcessState::self()->startThreadPool(); //启动线程池 IPCThreadState::self()->joinThreadPool(); //把主线程加入线程池 return 0; |
1.2 客户端
alps/frameworks/native/cmds/NativeBinderDemo/ClientDemo.cpp
获取ServiceManager,拿到service.myservice服务,再进行类型转换成IMyService,最后调用远程方法sayHello()
1 2 3 4 5 6 7 8 9 | #include "IMyService.h" int main() sp < IServiceManager > sm = defaultServiceManager(); //获取service manager引用 sp < IBinder > binder = sm->getService(String16("service.myservice"));//获取名为"service.myservice"的binder接口 sp<IMyService> cs = interface_cast < IMyService > (binder);//将biner对象转换为强引用类型的IMyService cs->sayHello();//利用binder引用调用远程sayHello()方法 return 0; |
1.3 MyService
alps/frameworks/native/cmds/NativeBinderDemo/IMyService.h
申明IMyService,申明BpMyService(Binder客户端),申明BnMyService(Binder的服务端)。
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 | #ifndef MY_SERVICE_DEMO #define MY_SERVICE_DEMO #include <stdio.h> #include <binder/IInterface.h> #include <binder/Parcel.h> #include <binder/IBinder.h> #include <binder/Binder.h> #include <binder/ProcessState.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> using namespace android; namespace android class IMyService : public IInterface public: DECLARE_META_INTERFACE(MyService); //使用宏,申明MyService virtual void sayHello()=0; //定义方法 ; //定义命令字段 enum HELLO = 1, ; //申明客户端BpMyService class BpMyService: public BpInterface<IMyService> public: BpMyService(const sp<IBinder>& impl); virtual void sayHello(); ; //申明服务端BnMyService class BnMyService: public BnInterface<IMyService> public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual void sayHello(); ; #endif |
alps/frameworks/native/cmds/NativeBinderDemo/IMyService.cpp
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 | #include "IMyService.h" namespace android IMPLEMENT_META_INTERFACE(MyService, "android.demo.IMyService"); //使用宏,完成MyService定义 //客户端 BpMyService::BpMyService(const sp<IBinder>& impl) : BpInterface<IMyService>(impl) // 实现客户端sayHello方法 void BpMyService::sayHello() printf("BpMyService::sayHello\\n"); Parcel data, reply; data.writeInterfaceToken(IMyService::getInterfaceDescriptor()); remote()->transact(HELLO, data, &reply); printf("get num from BnMyService: %d\\n", reply.readInt32()); //服务端,接收远程消息,处理onTransact方法 status_t BnMyService::onTransact(uint_t code, const Parcel& data, Parcel* reply, uint32_t flags) switch (code) case HELLO: //收到HELLO命令的处理流程 printf("BnMyService:: got the client hello\\n"); CHECK_INTERFACE(IMyService, data, reply); sayHello(); reply->writeInt32(2015); return NO_ERROR; break; default: break; return NO_ERROR; // 实现服务端sayHello方法 void BnMyService::sayHello() printf("BnMyService::sayHello\\n"); ; |
1.4 Android.mk
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 | LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \\ libcutils \\ libutils \\ libbinder LOCAL_MODULE := ServerDemo LOCAL_SRC_FILES := \\ IMyService.cpp \\ ServerDemo.cpp LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \\ libcutils \\ libutils \\ libbinder LOCAL_MODULE := ClientDemo LOCAL_SRC_FILES := \\ IMyService.cpp \\ ClientDemo.cpp LOCAL_MODULE_TAGS := optional include $(BUILD_EXECUTABLE) |
1.5 原理图
1.6 运行
编译:
mm alps/frameworks/native/cmds/NativeBinderDemo目录,然后到alps/out/target/product/Project/system/bin/会生成ClientDemo
和ServerDemo
执行:
1 2 3 | adb remount adb push ServerDemo /system/bin adb push ClientDemo /system/bin |
开两个窗口分别执行下面两个命令便可以看到结果了:adb shell system/bin/ServerDemo
, adb shell system/bin/ClientDemo
二、JavaFramework Binder
源码目录结构:
alps/frameworks/base/cmds/FrameworkBinderDemo/
1 2 3 4 5 6 7 8 | |-Server端 |---ServerDemo.java:可执行程序 |---IMyService.java: 定义IMyService接口 |---MyService.java:定义MyService |-Client端 |---ClientDemo.java:可执行程序 |---IMyService.java: 与Server端完全一致 |---MyServiceProxy.java:定义MyServiceProxy |
2.1 Server端
(1)ServerDemo.java
可执行程序
1 2 3 4 5 6 7 8 9 10 11 12 | public class ServerDemo public static void main(String[] args) System.out.println("MyService Start"); //准备Looper循环执行 Looper.prepareMainLooper(); //设置为前台优先级 android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); //注册服务 ServiceManager.addService("MyService", new MyService()); Looper.loop(); |
(2)IMyService.java
定义sayHello()方法,DESCRIPTOR属性
1 2 3 4 5 | public interface IMyService extends IInterface static final java.lang.String DESCRIPTOR = "com.yuanhh.frameworkBinder.MyServer"; public void sayHello(String str) throws RemoteException ; static final int TRANSACTION_say = android.os.IBinder.FIRST_CALL_TRANSACTION; |
(3)MyService.java
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 | public class MyService extends Binder implements IMyService public MyService() this.attachInterface(this, DESCRIPTOR); @Override public IBinder asBinder() return this; /** 将MyService转换为IMyService接口 **/ public static com.yuanhh.frameworkBinder.IMyService asInterface( android.os.IBinder obj) if ((obj == null)) return null; android.os.IInterface iInterface = obj.queryLocalInterface(DESCRIPTOR); if (((iInterface != null)&&(iInterface instanceof com.yuanhh.frameworkBinder.IMyService))) return ((com.yuanhh.frameworkBinder.IMyService) iInterface); return null; /** 服务端,接收远程消息,处理onTransact方法 **/ @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_say: data.enforceInterface(DESCRIPTOR); String str = data.readString(); sayHello(str); reply.writeNoException(); return true; return super.onTransact(code, data, reply, flags); /** 自定义sayHello()方法 **/ @Override public void sayHello(String str) System.out.println("MyService:: Hello, " + str); |
(4) Android.mk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := ServerDemo LOCAL_MODULE_TAGS := optional include $(BUILD_JAVA_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := ServerDemo LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_OUT)/bin LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES LOCAL_SRC_FILES := ServerDemo include $(BUILD_PREBUILT) |
(5) ServerDemo
1 2 3 | base=/system export CLASSPATH=$base/framework/ServerDemo.jar exec app_process $base/bin com.shun.frameworkBinder.ServerDemo "$@" |
2.2 Client端
(1)ClientDemo.java
可执行程序
1 2 3 4 5 6 7 8 9 10 | public class ClientDemo public static void main(String[] args) throws RemoteException System.out.println("Client start"); IBinder binder = ServiceManager.getService("MyService"); //获取名为"MyService"的服务 IMyService myService = new MyServiceProxy(binder); //创建MyServiceProxy对象 myService.sayHello("binder"); //通过MyServiceProxy对象调用接口的方法 System.out.println("Client end"); |
(2)IMyService.java
与Server端的IMyService是一致,基本都是拷贝一份过来。
(3)MyServiceProxy.java
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 | public class MyServiceProxy implements IMyService private android.os.IBinder mRemote; //代表BpBinder public MyServiceProxy(android.os.IBinder remote) mRemote = remote; public java.lang.String getInterfaceDescriptor() return DESCRIPTOR; /** 自定义的sayHello()方法 **/ @Override public void sayHello(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_say, _data, _reply, 0); _reply.readException(); finally _reply.recycle(); _data.recycle(); @Override public IBinder asBinder() return mRemote; |
(4) Android.mk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_MODULE := ClientDemo LOCAL_MODULE_TAGS := optional include $(BUILD_JAVA_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := ClientDemo LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_OUT)/bin LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES LOCAL_SRC_FILES := ClientDemo include $(BUILD_PREBUILT) |
(5) ClientDemo
1 2 3 | base=/system export CLASSPATH=$base/framework/ClientDemo.jar exec app_process $base/bin com.shun.frameworkBinder.ClientDemo "$@" |
2.3 原理图
2.4 运行
编译:
mm alps/frameworks/base/cmds/FrameworkBinderDemo/目录,然后:
alps/out/target/product/Project/system/bin/ 生成ClientDemo和ServerDemo
alps/out/target/product/Project/system/framework/ 生成ClientDemo.jar和ServerDemo.jar。
执行:
1 2 3 4 5 | adb remount adb push ServerDemo /system/bin adb push ClientDemo /system/bin adb push ServerDemo.jar /system/framework/ adb push ClientDemo.jar /system/framework/ |
开两个窗口分别执行下面两个命令便可以看到结果了:
adb shell system/bin/ServerDemo , adb shell system/bin/ClientDemo
文章非常好,转自 http://maoao530.github.io/2016/12/25/android-binder-02/
androidframework实战课程-binder专题之servicemanager启动及运行篇(代码片段)
csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论android跨进程通信实战视频课程(加群获取优惠)目标:1、理解servicemanager的dns角色含义2、源码层面理解servicemanager做了什么路... 查看详情
androidframework实战课程-binder专题之servicemanager启动及运行篇(代码片段)
csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论android跨进程通信实战视频课程(加群获取优惠)目标:1、理解servicemanager的dns角色含义2、源码层面理解servicemanager做了什么路... 查看详情
千里马androidframework实战课程-应用程序app的binder启动篇(代码片段)
...一个学习专题zygote启动app进程时候,有简单讲过一下binder启动,但没有详细进行分析。这一节进行重点详细分析。AndroidFramework实战视频 查看详情
千里马androidframework实战课程-应用程序app的binder启动篇(代码片段)
...一个学习专题zygote启动app进程时候,有简单讲过一下binder启动,但没有详细进行分析。这一节进行重点详细分析。AndroidFramework实战视频 查看详情
实战篇:一行命令安装linux系统,超详细的vagrant上手指南(代码片段)
一行命令安装Linux演示:vagrantboxaddbento/oracle-7.9--providervirtualbox&&sudovagrantinitbento/oracle-7.9&&sudovagrantup通过上述演示,已成功安装Linux7.9,并且可以访问。前言最近发现了一款神器Vagrant 查看详情
实战篇:一行命令安装linux系统,超详细的vagrant上手指南(代码片段)
一行命令安装Linux演示:vagrantboxaddbento/oracle-7.9--providervirtualbox&&sudovagrantinitbento/oracle-7.9&&sudovagrantup通过上述演示,已成功安装Linux7.9,并且可以访问。前言最近发现了一款神器Vagrant 查看详情
jmeter--作为测试你必须知道实用技巧--实战篇(代码片段)
博主在这里说明一下,接口是免费的,不过需要自己注册,如自己有接口的可以跟着教学一步步来,没有的可以考虑考虑加博主微信qing_an_an,与大伙一起学习,绝对不是广告,都是经过筛... 查看详情
unity实战100例教程专栏《导航帖》,带你深入学习unity实战经验(代码片段)
目录📣前言⌚️引擎实用技能实战篇⌚️趣味小Demo篇⌚️接入平台SDK篇⌚️实用软件制作篇🎅总结🚀往期优质文章分享【游戏开发爱好者社区】活动进行中,每周打卡送书籍等礼品,期待你的加入📣前... 查看详情
unity实战100例教程专栏《导航帖》,带你深入学习unity实战经验(代码片段)
目录📣前言⌚️引擎实用技能实战篇⌚️趣味小Demo篇⌚️接入平台SDK篇⌚️实用软件制作篇🎅总结🚀往期优质文章分享【游戏开发爱好者社区】活动进行中,每周打卡送书籍等礼品,期待你的加入📣前... 查看详情
java技术专题「提升篇」guavacollections实战指南—挑战guava不一般的集合框架(代码片段)
简介GoogleGuavaCollections是一个对JavaCollectionsFramework增强和扩展的一个开源项目。由于它高质量API的实现和对Java特性的充分利用,使得其在Java社区受到很高评价。笔者主要介绍它的基本用法和功能特性。使用介绍GoogleGuavaCollecti... 查看详情
jvm技术专题内存问题分析和故障排查规划指南「实战篇」(代码片段)
使用dstat和top查看内存使用最高的应用使用dstat查到内存占用最高的是java应用,使用2253M内存,但是这台服务器跑了好几个java,具体哪个进程使用top看下资源情况使用top可以看到java应用整体内存使用率超过了70%,... 查看详情
jvm技术专题网络问题分析和故障排查规划指南「实战篇」(代码片段)
前提概要涉及到网络层面的问题一般都比较复杂,场景多,定位难,成为了大多数开发的噩梦,应该是最复杂的了。这里会举一些例子,并从tcp层、应用层以及工具的使用等方面进行阐述。超时超时错误大部... 查看详情
深入浅出java并发编程指南「剖析篇」fork/join框架的实战开发和原理探究指南(代码片段)
前提概述Java7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行。我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一个线程内完... 查看详情
spock单元测试框架实战指南七-动态mock(代码片段)
这篇讲解Spock自带的mock功能如何和powermock组合使用,发挥更强大的作用动态Mock静态方法(Spock Where +PowerMock)在上一篇的例子中使用powermock让静态方法返回一个指定的值,那能不能每次返回不同的值呢?我们先看下什么场景... 查看详情
jvm技术专题gc问题分析和故障排查规划指南「实战篇」(代码片段)
前提概要之前的JVM专题总共大致近50章节,问题介绍相关的JVM的原理分析,比较接近于理论化,并且也穿插这相关的GC问题排查和调优的技术功能实现,但是很多小伙伴都建议我多针对于实际优化角度和故障排查而... 查看详情
msil实用指南-局部变量的声明保存和加载(代码片段)
这一篇讲解方法内的局部变量是怎么声明、怎样保存、怎样加载的。声明局部变量声明用ILGenerator的DeclareLocal方法,参数是局部变量的数据类型,得到一个局部变量对应的创建类LocalBuilder。使用格式是LocalBuilderlocalBuilderx=ilGenerator... 查看详情
深入浅出学习透析nginx服务器的基本原理和配置指南「运维操作实战篇」(代码片段)
Nginx前提回顾Nginx是一个高性能的Web和反向代理服务器,它具有有很多非常优越的特性:Web服务器:相比Apache,Nginx使用更少的资源,支持更多的并发连接,体现更高的效率,这点使Nginx尤其受到虚拟主机提供商的... 查看详情
深入浅出java并发编程指南「实战篇」教你如何使用abstractqueuedsynchronizer实现自己的同步器组件(代码片段)
前提概要之前的文章中会涉及到了相关AQS的原理和相关源码的分析,所谓实践是检验真理的唯一标准!接下来就让我们活化一下AQS技术,主要针对于自己动手实现一个AQS同步器。定义MyLock实现LockDougLea大神在JDK1.5编写... 查看详情