今天来写两个 Binder 的例子,一个 native 层,一个 Framework 层。
目录:
- native 层使用 Binder
- Framework 层使用 Binder
1. native 层使用 Binder
- 1.1 源码目录
ClientDemo.cpp:客户端程序
ServerDemo.cpp:服务端程序
IMyService.h:自定义的 MyService 服务的头文件
IMyService.cpp:自定义的 MyService 服务
Android.mk:源码 build 文件
- 1.2 IMyService.h
//
// Created by Mr.Kuang on 2019/3/4.
//
#ifndef BINDERAIDLDEMO_IMYSERVICE_H
#define BINDERAIDLDEMO_IMYSERVICE_H
namespace android {
class IMyService : public IInterface {
public:
// 使用宏,申明MyService
DECLARE_META_INTERFACE(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 //BINDERAIDLDEMO_IMYSERVICE_H
主要功能:
- 声明 IMyService。
- 声明 BpMyService (Binder 客户端)。
- 声明 BnMyService (Binder 的服务端)。
- 1.3 IMyService.cpp
//
// Created by Mr.Kuang on 2019/3/4.
//
#include "IMyService.h"
namespace android {
// 使用宏,完成 MyService 定义
IMPLEMENT_META_INTERFACE(MyService, "android.demo.IMyService");
// 客户端
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) {
// 收到 HELLO 命令的处理流程
case 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 ServerDemo.cpp
//
// Created by Mr.Kuang on 2019/3/4.
//
#include "IMyService.h"
int main() {
// 获取service manager 引用
sp<IServiceManager> sm = defaultServiceManager();
// 注册名为 "service.myservice" 的服务到 service manager
sm->addService(String16("service.myservice"), new BnMyService());
// 启动线程池
ProcessState::self()->startThreadPool();
// 把主线程加入线程池
IPCThreadState::self()->joinThreadPool();
return 0;
}
将名为 "service.myservice" 的 BnMyService 服务添加到 ServiceManager,并启动服务。
- 1.5 ClientDemo.cpp
//
// Created by Mr.Kuang on 2019/3/4.
//
#include "IMyService.h"
int main() {
// 获取service manager引用
sp<IServiceManager> sm = defaultServiceManager();
// 获取名为 "service.myservice" 的 binder 接口
sp<IBinder> binder = sm->getService(String16("service.myservice"));
// 将 biner 对象转换为强引用类型的 IMyService
sp<IMyService> cs = interface_cast<IMyService>(binder);
// 利用binder引用调用远程sayHello()方法
cs->sayHello();
return 0;
}
获取名为 "service.myservice" 的服务,再进行类型转换,最后调用远程方法 sayHello()。
- 1.6 原理图
- 1.7 运行
1. 编译生成:利用 Android.mk 编译上述代码,在 Android 的源码中,通过 mm 编译后,可生成两个可执行文件ServerDemo,ClientDemo。
2. 将这 ServerDemo,ClientDemo 可执行文件 push 到手机。
adb push ServerDemo /system/bin adb push ClientDemo /system/bin
如果 push 不成功,那么先执行 adb remount,再执行上面的指令;如果还不成功,可能就是权限不够。
如果上述开启成功,通过开启两个窗口运行 (一个运行 client 端,另一个运行 server 端)。
3. adb shell,进入 shell 模式。然后分别执行:/system/bin/ServerDemo,/system/bin/ClientDemo。
2. Framework 层使用 Binder
上面是在 native 层实现了一个 Binder demo,现在用 Java 来实现一个 Binder demo。
- 2.1 源码目录
Server 端:
ServerDemo.java:可执行程序
IMyService.java:定义 IMyService 接口
MyService.java:定义 MyService
Client 端:
ClientDemo.java:可执行程序
IMyService.java:与 Server 端完全一致
MyServiceProxy.java:定义 MyServiceProxy
- 2.2 代码实现
public interface IMyService extends IInterface {
static final java.lang.String DESCRIPTOR = "io.kzw.frameworkBinder.MyServer";
public void sayHello(String str) throws RemoteException;
static final int TRANSACTION_say = android.os.IBinder.FIRST_CALL_TRANSACTION;
}
public class MyService extends Binder implements IMyService{
public MyService() {
this.attachInterface(this, DESCRIPTOR);
}
@Override
public IBinder asBinder() {
return this;
}
/** 将MyService转换为IMyService接口 **/
public static IMyService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iInterface = obj.queryLocalInterface(DESCRIPTOR);
if (((iInterface != null) && (iInterface instanceof IMyService))){
return ((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);
}
}
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();
}
}
public class MyServiceProxy implements IMyService {
// 代表 BpBinder
private android.os.IBinder mRemote;
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;
}
}
public class ClientDemo {
public static void main(String[] args) throws RemoteException {
System.out.println("Client start");
// 获取名为"MyService"的服务
IBinder binder = ServiceManager.getService("MyService");
// 创建MyServiceProxy对象
IMyService myService = new MyServiceProxy(binder);
// 通过MyServiceProxy对象调用接口的方法
myService.sayHello("binder");
System.out.println("Client end");
}
}
- 2.3 运行
首先将 ServerDemo,ClientDemo 以及可执行文件 ServerDemo.jar,ClientDemo.jar 都 push 到手机:
adb push ServerDemo /system/bin adb push ClientDemo /system/bin adb push ServerDemo.jar /system/framework adb push ClientDemo.jar /system/framework
如果 push 不成功,那么先执行 adb remount,再执行上面的指令;如果还不成功,可能就是权限不够。 如果上述开启成功,通过开启两个窗口运行 (一个运行 client 端,另一个运行 server 端)。