自定义Native层Binder服务
实现Client调用Service的 int add(int x,int y),x,y由Client提供。
参考 binder使用
- ClientDemo.cpp: 客户端程序
- ServerDemo.cpp:服务端程序
- IMyService.h:自定义的MyService服务的头文件
- IMyService.cpp:自定义的MyService服务
- Android.mk:源码build文件
实现framework层binder server ,使用aidl编写接口类,实现native层对应的binder client端
- 首先,在java层注册一个binder server
1 编写aidl文件
在/home/android/frameworks/base/core/java/android/os/ITestService.aidl源码目录下新建ITestService.aidl文件。
package android.os;
interface ITestService
{
int add(int x , int y); //业务函数
}
aidl文件会被自动编译成对应的ITestService.java接口文件
2 修改Adnroid.mk文件,编译aidl文件
修改/home/android/frameworks/base/Android.mk文件
在** LOCAL_SRC_FILES += \ ** 的结尾加上
core/java/android/os/ITestService.aidl
也就是刚刚编写的aidl文件的文件地址
在编译的时候,接口文件会输出到 /home/android/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/ITestService.java
其中只有 add()方法需要实现,节省了大量工作
3 编写java层的service
新建
/home/android/frameworks/base/services/java/com/android/server/TestService.java
package com.android.server;
import android.os.ITestService;
public class TestService extends ITestService.Stub{
public TestService() {
super();
System.out.println("[snake_xing_TestService.java]================init TestService");
}
public int add(int x,int y) {
int sum = x+y;
System.out.println("[snake_xing_TestService.java]================call add() ");
return sum;
}
}
4 在 /home/android/frameworks/base/services/java/com/android/server/SystemServer.java中添加服务
在startOtherServices()函数中
TestService testService = null; /*Myservice*/
/*MyService*/
Slog.i("snake_xing_SystemServer===========", "addMyservice");
testService = new TestService();
ServiceManager.addService("mytestservice", testService);
/*end*/
仿照telephonyRegistry这个服务添加即可。
build源码(system)
5 进入adb shell ** 检查服务 **是否启动
snake@snakepc:~$ adb shell
root@ASUS_Z00L_93:/ # service list | grep my
0 mytestservice1: [android.os.ITestService1]
** 72 mytestservice: [android.os.ITestService] //这个就是刚刚add的service **
root@ASUS_Z00L_93:/ #
6 修改本地Binder代码
Client端
sp < IBinder > binder = sm->getService(String16("mytestservice"));
改为自己定义的服务名字
IMyService.cpp
IMPLEMENT_META_INTERFACE(MyService, "android.os.ITestService");
name 要改为生成的/home/android/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/ITestService.java
里面定义的 DESCRIPTOR
private static final java.lang.String DESCRIPTOR = "android.os.ITestService";
在ITestService.java文件中,也就是生层的接口文件中的
ITestService.java中的onTransact函数如下:
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt(); //读出第一个数字
int _arg1;
_arg1 = data.readInt(); //读出第二个数字
int _result = this.add(_arg0, _arg1); //计算和
reply.writeNoException(); //写入数字noexception也就是0
reply.writeInt(_result); //写入x+y 的值
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
所以在 BpMyService::add 中 reply.readInt32(); 两次就好
int BpMyService::add(int a,int b) {
printf("BpMyService::add\n");
Parcel data,reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
remote()->transact(HELLO, data, &reply);
reply.readInt32(); //这里读到的是 0 表示返回正确
int sum = reply.readInt32(); //这里读到的才是 a+b的和
printf("get num from service: %d + %d = %d \n",a,b,sum);
return sum;
}
接下来运行Client
root@ASUS_Z00L_93:/ # ./system/bin/ClientDemo
BpMyService::add
get num from service: 12 + 10 = 22
the sum is : 22
root@ASUS_Z00L_93:/ #
native Binder客户端代码
ClientDemo.cpp: 客户端程序:
#include "IMyService.h"
int main() {
sp < IServiceManager > sm = defaultServiceManager();
sp < IBinder > binder = sm->getService(String16("mytestservice"));
if (binder == NULL)
{
printf("binder is NULL\n");
}
sp cs = interface_cast < IMyService > (binder);
if (cs == NULL)
{
printf("cs is NULL\n");
}
int sum = cs->add(12,10);
printf("the sum is : %d\n",sum);
return 0;
}
MyService.h:自定义的MyService服务的头文件
#ifndef MY_SERVICE_DEMO
#define MY_SERVICE_DEMO
#include
#include
#include
#include
#include
#include
#include
#include
using namespace android;
namespace android
{
class IMyService : public IInterface
{
public:
DECLARE_META_INTERFACE(MyService);
virtual int add(int a,int b)=0;
};
enum
{
HELLO = 1,
};
class BpMyService: public BpInterface {
public:
BpMyService(const sp& impl);
virtual int add(int a,int b);
};
}
#endif
IMyService.cpp:自定义的MyService服务
#include "IMyService.h"
namespace android
{
IMPLEMENT_META_INTERFACE(MyService, "android.os.ITestService");
BpMyService::BpMyService(const sp& impl) :
BpInterface(impl) {
}
int BpMyService::add(int a,int b) {
printf("BpMyService::add\n");
Parcel data,reply;
data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
remote()->transact(HELLO, data, &reply);
reply.readInt32();
int sum = reply.readInt32();
printf("get num from service: %d + %d = %d \n",a,b,sum);
return sum;
}
}
Android.mk:源码build文件
LOCAL_PATH := $(call my-dir)
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)