Binder实用指南(二) - 实战篇
本章的內(nèi)容主要說明如何在JavaFramework層和Native層自定義Client-Server組件,并且使用Binder進(jìn)行通信。
一、Native Binder
源碼目錄結(jié)構(gòu):
alps/frameworks/native/cmds/NativeBinderDemo/
| 123456 | |-NativeBinderDemo|---ClientDemo.cpp: 客戶端程序|---ServerDemo.cpp:服務(wù)端程序|---IMyService.h:自定義的MyService服務(wù)的頭文件|---IMyService.cpp:自定義的MyService服務(wù)|---Android.mk:源碼build文件 |
1.1 服務(wù)端
alps/frameworks/native/cmds/NativeBinderDemo/ServerDemo.cpp
獲取ServiceManager,注冊service.myservice服務(wù)到ServiceManager,啟動(dòng)服務(wù)。
| 123456789 | int main() {sp < IServiceManager > sm = defaultServiceManager(); //獲取service manager引用sm->addService(String16("service.myservice"), new BnMyService()); //注冊名為"service.myservice"的服務(wù)到service managerProcessState::self()->startThreadPool(); //啟動(dòng)線程池IPCThreadState::self()->joinThreadPool(); //把主線程加入線程池 return 0;} |
1.2 客戶端
alps/frameworks/native/cmds/NativeBinderDemo/ClientDemo.cpp
獲取ServiceManager,拿到service.myservice服務(wù),再進(jìn)行類型轉(zhuǎn)換成IMyService,最后調(diào)用遠(yuǎn)程方法sayHello()
| 123456789 | 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對象轉(zhuǎn)換為強(qiáng)引用類型的IMyServicecs->sayHello();//利用binder引用調(diào)用遠(yuǎn)程sayHello()方法 return 0;} |
1.3 MyService
alps/frameworks/native/cmds/NativeBinderDemo/IMyService.h
申明IMyService,申明BpMyService(Binder客戶端),申明BnMyService(Binder的服務(wù)端)。
| 123456789101112131415161718192021222324252627282930313233343536373839404142 | 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();}; //申明服務(wù)端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();};} |
alps/frameworks/native/cmds/NativeBinderDemo/IMyService.cpp
| 123456789101112131415161718192021222324252627282930313233343536373839404142 | namespace android{IMPLEMENT_META_INTERFACE(MyService, "android.demo.IMyService"); //使用宏,完成MyService定義 //客戶端BpMyService::BpMyService(const sp<IBinder>& impl) :BpInterface<IMyService>(impl) {} // 實(shí)現(xiàn)客戶端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());} //服務(wù)端,接收遠(yuǎn)程消息,處理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;} // 實(shí)現(xiàn)服務(wù)端sayHello方法 void BnMyService::sayHello() { printf("BnMyService::sayHello\n");};} |
1.4 Android.mk
| 12345678910111213141516171819202122232425262728 | LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)LOCAL_SHARED_LIBRARIES := \libcutils \libutils \libbinder LOCAL_MODULE := ServerDemoLOCAL_SRC_FILES := \IMyService.cpp \ServerDemo.cpp LOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE) include $(CLEAR_VARS)LOCAL_SHARED_LIBRARIES := \libcutils \libutils \libbinderLOCAL_MODULE := ClientDemoLOCAL_SRC_FILES := \IMyService.cpp \ClientDemo.cppLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE) |
1.5 原理圖
1.6 運(yùn)行
編譯:
mm alps/frameworks/native/cmds/NativeBinderDemo目錄,然后到alps/out/target/product/{Project}/system/bin/會(huì)生成ClientDemo和ServerDemo
執(zhí)行:
| 123 | adb remountadb push ServerDemo /system/binadb push ClientDemo /system/bin |
開兩個(gè)窗口分別執(zhí)行下面兩個(gè)命令便可以看到結(jié)果了:
adb shell system/bin/ServerDemo?,?adb shell system/bin/ClientDemo
二、JavaFramework Binder
源碼目錄結(jié)構(gòu):
alps/frameworks/base/cmds/FrameworkBinderDemo/
| 12345678 | |-Server端|---ServerDemo.java:可執(zhí)行程序|---IMyService.java: 定義IMyService接口|---MyService.java:定義MyService|-Client端|---ClientDemo.java:可執(zhí)行程序|---IMyService.java: 與Server端完全一致|---MyServiceProxy.java:定義MyServiceProxy |
2.1 Server端
(1)ServerDemo.java
可執(zhí)行程序
| 123456789101112 | public class ServerDemo { public static void main(String[] args) {System.out.println("MyService Start"); //準(zhǔn)備Looper循環(huán)執(zhí)行Looper.prepareMainLooper(); //設(shè)置為前臺(tái)優(yōu)先級(jí)android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); //注冊服務(wù)ServiceManager.addService("MyService", new MyService());Looper.loop();}} |
(2)IMyService.java
定義sayHello()方法,DESCRIPTOR屬性
| 12345 | 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
| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 | public class MyService extends Binder implements IMyService{ public MyService() { this.attachInterface(this, DESCRIPTOR);} public IBinder asBinder() { return this;} /** 將MyService轉(zhuǎn)換為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;} /** 服務(wù)端,接收遠(yuǎn)程消息,處理onTransact方法 **/ 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()方法 **/ public void sayHello(String str) {System.out.println("MyService:: Hello, " + str);}} |
(4) Android.mk
| 12345678910111213141516 | LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := $(call all-subdir-java-files)LOCAL_MODULE := ServerDemo LOCAL_MODULE_TAGS := optionalinclude $(BUILD_JAVA_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := ServerDemoLOCAL_MODULE_TAGS := optionalLOCAL_MODULE_PATH := $(TARGET_OUT)/binLOCAL_MODULE_CLASS := UTILITY_EXECUTABLESLOCAL_SRC_FILES := ServerDemoinclude $(BUILD_PREBUILT) |
(5) ServerDemo
| 123 | base=/systemexport CLASSPATH=$base/framework/ServerDemo.jarexec app_process $base/bin com.shun.frameworkBinder.ServerDemo "$@" |
2.2 Client端
(1)ClientDemo.java
可執(zhí)行程序
| 12345678910 | public class ClientDemo { public static void main(String[] args) throws RemoteException {System.out.println("Client start");IBinder binder = ServiceManager.getService("MyService"); //獲取名為"MyService"的服務(wù)IMyService myService = new MyServiceProxy(binder); //創(chuàng)建MyServiceProxy對象myService.sayHello("binder"); //通過MyServiceProxy對象調(diào)用接口的方法System.out.println("Client end");}} |
(2)IMyService.java
與Server端的IMyService是一致,基本都是拷貝一份過來。
(3)MyServiceProxy.java
| 1234567891011121314151617181920212223242526272829303132 | 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()方法 **/ 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();}} public IBinder asBinder() { return mRemote;}} |
(4) Android.mk
| 123456789101112131415 | LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := $(call all-subdir-java-files)LOCAL_MODULE := ClientDemo LOCAL_MODULE_TAGS := optionalinclude $(BUILD_JAVA_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := ClientDemoLOCAL_MODULE_TAGS := optionalLOCAL_MODULE_PATH := $(TARGET_OUT)/binLOCAL_MODULE_CLASS := UTILITY_EXECUTABLESLOCAL_SRC_FILES := ClientDemoinclude $(BUILD_PREBUILT) |
(5) ClientDemo
| 123 | base=/systemexport CLASSPATH=$base/framework/ClientDemo.jarexec app_process $base/bin com.shun.frameworkBinder.ClientDemo "$@" |
2.3 原理圖
2.4 運(yùn)行
編譯:
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。
執(zhí)行:
| 12345 | adb remountadb push ServerDemo /system/binadb push ClientDemo /system/binadb push ServerDemo.jar /system/framework/adb push ClientDemo.jar /system/framework/ |
開兩個(gè)窗口分別執(zhí)行下面兩個(gè)命令便可以看到結(jié)果了:
adb shell system/bin/ServerDemo , adb shell system/bin/ClientDemo
原文地址:?https://maoao530.github.io/2016/12/25/android-binder-02/
與50位技術(shù)專家面對面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Binder实用指南(二) - 实战篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Binder实用指南(一) - 理解篇
- 下一篇: 理解和使用systrace