binder实用指南-实战篇(代码片段)

火山石 火山石     2022-12-05     421

关键词:

本章的内容主要说明如何在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/会生成ClientDemoServerDemo

执行:

 

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编写... 查看详情