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

原文地址: https://maoao530.github.io/2016/12/25/android-binder-02/

Binder实用指南(二) - 实战篇相关推荐

  1. WPF实用指南二:移除窗体的图标

    原文:WPF实用指南二:移除窗体的图标 WPF没有提供任何功能来移除窗体上的icon图标.一般的做法是设置一个空白的图标,如下图1: 这种做法在窗体边框与标题之间仍然会保留一片空白. 比较好的做法是使 ...

  2. Scikit-Learn TensorFlow机器学习实用指南(二):一个完整的机器学习项目【上】

    机器学习实用指南(二):一个完整的机器学习项目[上] 作者:LeonG 本文参考自:<Hands-On Machine Learning with Scikit-Learn & Tens ...

  3. Binder实用指南(一) - 理解篇

    这是关于Android Binder机制的一篇文章,Binder是Android里面非常重要的组成,也是最难理解的一块知识点,学习Binder最好的方法是深入源码阅读,因为Binder相关的知识错综复 ...

  4. 2022黑马Redis跟学笔记.实战篇(二)

    2022黑马Redis跟学笔记.实战篇 二 实战篇Redis 开篇导读 4.1短信登录 4.1.1. 搭建黑马点评项目 一.导入黑马点评项目 二.导入SQL 三.有关当前模型 四.导入后端项目 相关依 ...

  5. Android10.0 Binder通信原理(二)-Binder入门篇

    摘要:本节主要来讲解Android10.0 Binder的设计原理,如何设计一个Binder通信 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分 ...

  6. App项目实战之路(二):API篇

    原创文章,转载请注明:转载自Keegan小钢 并标明原文链接:http://keeganlee.me/post/practice/20160812 微信订阅号:keeganlee_me 写于2016- ...

  7. 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)

    基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二) 转载于:https://github.com/Meowv/Blog 上篇文章完成了两个接口:文章列表页.文章详 ...

  8. 微信小程序|开发实战篇之二

    开发实战篇之二 前言 1.零碎知识点和优化点 1.1 ES6模板字符串 1.2 ES6扩展运算符 1.3 独立更新like组件状态 1.4 自定义组件支持hidden 2.音乐music组件开发 2. ...

  9. Ceres Solver: 高效的非线性优化库(二)实战篇

    Ceres Solver: 高效的非线性优化库(二)实战篇 接上篇: Ceres Solver: 高效的非线性优化库(一) 如何求导 Ceres Solver提供了一种自动求导的方案,上一篇我们已经看 ...

最新文章

  1. TLD(Tracking-Learning-Detection)学习与源码理解之(二)
  2. 定时任务重启后执行策略_C语言操作时间函数time.ctime,实现定时执行某个任务小例子...
  3. react java_独眼巨人React组织了Java 8库的寒武纪爆发
  4. sublime c 语言 编译,默认情况下,将程序编译为Sublime Text 3中的c 14
  5. 【jvm】jvm 执行模式设置
  6. 赛锐信息:在云中交付SAP解决方案
  7. 迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}...
  8. php多个表查询的方法_php+mysql+ajax实现单表多字段多关键词查询的方法
  9. PHP 缓存 内存,PHP memcache 内存缓存 数据库查询 应用 高洛峰 细说PHP
  10. 物流企业matlab效率,基于DEA原理的物流企业综合效率评价
  11. 利用YYLabel 进行图文混排+高度计算
  12. 优启通制作系统u盘_如何用优启通制作U盘启动盘
  13. 微信对账单 java_java下载微信对账单,实现与微信实收对账和日清日结对账
  14. 费曼和西蒙的学习方法分享
  15. 第二讲:项目运行环境 事业环境因素 (EEF) 和组织过程资产 (OPA)
  16. Photon网络中Player中存取数据
  17. Windows 7 新功能选集
  18. 电子驻车系统(卡钳式)
  19. 脉脉林凡:职场社交突破点在于行业间的融合
  20. 原生js插件(超详细)

热门文章

  1. HTML中的div标签
  2. Python学习笔记: Python 标准库概览二
  3. CUDA Libraries简介
  4. JVM_垃圾收集器与内存分配策略01
  5. 链表反转相关的题(C++模板)
  6. Ubuntu 16.04网速慢解决方法
  7. [云炬商业计划书阅读分享]校园快递创业计划书
  8. 《蓝桥小记》 2018-04-01
  9. 小米wifi每天晚上准时断网_小米路由器遭恶意抹黑 官方回应:抵制这种下三滥...
  10. 串口通信模块3:串口通信编程基础(读写、关闭)