转载:http://www.cnblogs.com/herenzhiming/articles/5074487.html
本文原创作者:Cloud Chou.
1.前言
Binder service入门系列:
Binder service入门–创建native binder service:
http://www.cloudchou.com/android/post-332.html
Binder service入门—Framework binder service:
http://www.cloudchou.com/android/post-447.html
Binder service入门—应用层binder service:
http://www.cloudchou.com/android/post-458.html
本篇将综合先前介绍的native binder service,framework binder service,应用层binder service等知识,讲述如何使用native 的client,framework层的client,应用层的client测试native binder service。
2.程序构成
因为编译native的binder service,framework层的client都需要在源码环境下编译,故此本篇讲述的工程需要在源码环境下编译。
整个工程可以在github上下载:
https://github.com/cloudchou/NativeBinderJavaClientDemo
程序由4个部分组成:
1) native_bserver 创建并注册native binder service的本地服务端
2) native_bclient 测试native binder service的本地客户端
3) fclient和fclient.jar测试native binder service的框架层客户端
4) NativeBinderServiceTest 测试native binder service的应用层客户端
3.程序源码构成
源程序目录结构如下所示:
顶层Android.mk只是简单包含各个子目录的Android.mk,BServer目录存放本地服务端和本地客户端源码,FClient存放框架层客户端源码,NatviveBinderServiceTest存放应用层客户端源码。
本地服务端和本地客户端
1) BServer的Android.mk源码如下所示:
LOCAL_PATH := $(call my-dir)
#生成binder service的本地服务端
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE := native_bserver
LOCAL_SRC_FILES := \
ICloudManager.cpp \
TestServer.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
#生成binder service的本地客户端
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder
LOCAL_MODULE := native_bclient
LOCAL_SRC_FILES := \
ICloudManager.cpp \
TestClient.cpp
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
2) binder service接口ICloudManager(ICloudManager.h):
namespace android
{
class ICloudManager : public IInterface
{
public:
DECLARE_META_INTERFACE(CloudManager); // declare macro
virtual void test()=0;
virtual void print(const char* str)=0;
virtual int add(int a, int b)=0;
};
enum
{
TEST = IBinder::FIRST_CALL_TRANSACTION+1,
PRINT = IBinder::FIRST_CALL_TRANSACTION+2,
ADD = IBinder::FIRST_CALL_TRANSACTION+3,
};
class BpCloudManager: public BpInterface<ICloudManager> {
public:
BpCloudManager(const sp<IBinder>& impl);
virtual void test();
virtual void print(const char* str);
virtual int add(int a, int b);
};
}
3) 实现实现ICloudManager接口的方法(ICloudManager.cpp)
namespace android
{
IMPLEMENT_META_INTERFACE(CloudManager, "com.cloud.test.ICloudManager");
}
4) 实现服务端(TestServer.cpp)
namespace android
{
//binder service 实体类
class BnCloudManager : public BnInterface<ICloudManager>
{
public:
virtual status_t
onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
virtual void test();
virtual void print(const char* str);
virtual int add(int a, int b);
};
status_t
BnCloudManager::onTransact(uint_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch (code)
{
case TEST:
{
CHECK_INTERFACE(ICloudManager, data, reply);
test();
reply->writeInt32(0);
return NO_ERROR;
}
break;
case PRINT:
{
CHECK_INTERFACE(ICloudManager, data, reply);
String16 str = data.readString16();
String8 str8 = String8(str);
print(str8.string());
reply->writeInt32(0);
return NO_ERROR;
}
break;
case ADD:
{
CHECK_INTERFACE(ITest, data, reply);
int a;
int b;
data.readInt32(&a);
data.readInt32(&b);
int c = add(a,b);
reply->writeInt32(0);
reply->writeInt32(c);
return NO_ERROR;
}
break;
default:
break;
}
return NO_ERROR;
}
void
BnCloudManager::test() {
printf("Now server receive requset from client: [call test]\n");
}
void
BnCloudManager::print(const char* str) {
printf("Now server receive requset from client: [call print %s]\n", str);
}
int
BnCloudManager::add(int a, int b) {
printf("Now server receive requset from client: [call add %d %d]\n", a, b);
return a + b;
}
}
int
main() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
//注册binder service
sm->addService(String16("cloudservice"), new BnCloudManager());
printf("Native binder server starts to work\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
5) 实现客户端(TestClient.cpp)
namespace android
{
BpCloudManager::BpCloudManager(const sp<IBinder>& impl) :
BpInterface<ICloudManager>(impl) {
}
void
BpCloudManager::test() {
printf("Client call server test method\n");
Parcel data, reply;
data.writeInterfaceToken(ICloudManager::getInterfaceDescriptor());
remote()->transact(TEST, data, &reply);
int code = reply.readExceptionCode();
printf("Server exepction code: %d\n", code);
}
void
BpCloudManager::print(const char* str) {
printf("Client call server print method\n");
Parcel data, reply;
data.writeInterfaceToken(ICloudManager::getInterfaceDescriptor());
data.writeString16(String16(str));
remote()->transact(PRINT, data, &reply);
int code = reply.readExceptionCode();
printf("Server exepction code: %d\n", code);
}
int
BpCloudManager::add(int a, int b) {
printf("Client call server add method\n");
Parcel data, reply;
data.writeInterfaceToken(ICloudManager::getInterfaceDescriptor());
data.writeInt32(a);
data.writeInt32(b);
remote()->transact(ADD, data, &reply);
int code = reply.readExceptionCode();
int result;
reply.readInt32(&result);
printf("Server exepction code: %d\n", code);
return result;
}
}
int
main() {
sp<IServiceManager> sm = defaultServiceManager();
//查询服务
sp<IBinder> binder = sm->getService(String16("cloudservice"));
//转换接口
sp<ICloudManager> cs = interface_cast<ICloudManager>(binder);
//测试接口方法
cs->test();
cs->print("Hello world");
int result=cs->add(2,3);
printf("client receive add result from server : %d\n",result);
return 0;
}
框架层客户端
1) Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
#生成fclient.jar
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := fclient
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
#生成fclient
include $(CLEAR_VARS)
LOCAL_MODULE := fclient
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/bin
LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
LOCAL_SRC_FILES := fclient
include $(BUILD_PREBUILT)
2) 定义接口类(ICloudManager.java)
public interface ICloudManager extends IInterface {
//接口描述字符串
static final java.lang.String DESCRIPTOR = "com.cloud.test.ICloudManager";
void test() throws RemoteException;
void print(String str) throws RemoteException;
int add(int a, int b) throws RemoteException;
static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
}
3) 定义接口代理类(CloudManagerProxy.java)
public class CloudManagerProxy implements ICloudManager {
private android.os.IBinder mRemote;
public CloudManagerProxy(android.os.IBinder remote) {
mRemote = remote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void print(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_print, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public int add(int a, int b) throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int result = 0;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
mRemote.transact(TRANSACTION_add, _data, _reply, 0);
_reply.readException();
result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return result;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public void test() throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_test, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
4) 客户端(FClient.java)
public class FClient {
/**
* Command-line entry point.
*
* @param args
* The command-line arguments
* @throws RemoteException
*/
public static void main(String[] args) throws RemoteException {
System.out.println("==========Client starts===========");
IBinder binder = ServiceManager.getService("cloudservice");
ICloudManager manager = new CloudManagerProxy(binder);
System.out.println("========== client call server test ===========");
manager.test();
System.out.println("========== client call server print ===========");
manager.print("Hello world");
System.out.println("========== client call server add ===========");
int result = manager.add(2, 3);
System.out.println("manager.add(2, 3)=" + result);
}
}
5) 客户端脚本fclient
# Script to start "am" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/fclient.jar
exec app_process $base/bin com.cloud.test.FClient "$@"
应用层客户端
先前我们有讲到在应用层是不能直接使用ServiceManager这个类的,因为Sdk并未包含该类,应用层只能通过bind service去使用binder service,但是我们的native service并不是使用应用层的Service子类创建的,这样看来貌似应用层不能使用native的binder service。
这里介绍一个技巧,其实我们的应用在运行时可以使用系统隐藏的类,比如ServiceManager,SystemProperties,只是编译 时Sdk并未提供这些类,我们若使用这些类就无法编译。但是我们可以创建这些类所在的包,并创建这些类,在类里定义我们要使用的那些方法,我们就可以通过 编译了。比如ServiceManager这个类,我们就可以为之创建android.os这个package,并在这个package下创建 ServiceManager类,定义我们需要的方法getService。也许读者会担心运行时使用的ServiceManger类就是我们创建的 ServiceManager类,但实际上运行时使用的ServiceManager类是framework.jar里的ServiceManager 类,这是因为classloader在查找类时优先使用系统的类。
1) Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := NativeBinderServiceTest
#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))
2) 我们创建的ServiceManager源码
public class ServiceManager {
public static IBinder getService(String name) {
return null;
}
}
3) 定义接口ICloudManager
public interface ICloudManager extends IInterface {
static final java.lang.String DESCRIPTOR = "com.cloud.test.ICloudManager";
void test() throws RemoteException;
void print(String str) throws RemoteException;
int add(int a, int b) throws RemoteException;
static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
}
4) 定义代理类CloudManagerProxy
public class CloudManagerProxy implements ICloudManager {
private android.os.IBinder mRemote;
public CloudManagerProxy(android.os.IBinder remote) {
mRemote = remote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void print(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_print, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public int add(int a, int b) throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int result = 0;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
mRemote.transact(TRANSACTION_add, _data, _reply, 0);
_reply.readException();
result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return result;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public void test() throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_test, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
5) 测试用的Activity(TestAc.java)
public class CloudManagerProxy implements ICloudManager {
private android.os.IBinder mRemote;
public CloudManagerProxy(android.os.IBinder remote) {
mRemote = remote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void print(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_print, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public int add(int a, int b) throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int result = 0;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(a);
_data.writeInt(b);
mRemote.transact(TRANSACTION_add, _data, _reply, 0);
_reply.readException();
result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return result;
}
@Override
public IBinder asBinder() {
return mRemote;
}
@Override
public void test() throws RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(TRANSACTION_test, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
4.测试
上传程序:
adb push native_bclient /system/bin
adb push native_bserver /system/bin
adb push fclient /system/bin
adb push fclient.jar /system/framework
adb shell chmod 755 /system/bin/native_bserver
adb shell chmod 755 /system/bin/native_bclient
adb shell chmod 755 /system/bin/fclient
使用native_client测试:
使用框架层的client测试:
使用应用层的client测试:
服务端:
客户端: