android native service編寫及兩個服務程式通訊
題外話:由於同事諮詢,口頭講解的話1對1,但不方便多方傳播及繼承性,因此特意寫此文章講解一番。
1、android service簡要說明:
Android Service :又稱為 Java Service ,是實現在框架層裡的 Service ,使用Java語言編寫。
Native Service :又稱為 System Service ,是實現在 Runtime 層裡的 Service 。使用C++語言編寫。
對於這兩種service來說,兩個對等service通訊都是利用binder,只不過一種利用*.aidl,一種利用IInterface
編寫序列化程式碼而已,本質是一樣的,本書先介紹native service的編寫及兩個native service
如何通訊的過程:
2、native service的特點
A、因為底層核心服務是 Android 框架裡最接近 Linux/Driver 的部分。為了充分發揮硬體裝置
的差異化特性,核心服務是讓上層 Java 應用程式來使用 Driver/HW Device 特色的重要管道。
B、在開機過程中,就可以啟動核心服務 ( 例如漢字輸入法服務等 ) ,讓眾多應用程式來共享之。
C、由於共享,所以能有效降低程式的大小及統一的介面變化 。
3、如何實現一個native service
要點如下:
a、核心服務通常在獨立的程式 (Process) 裡執行。
b、必須提供 IBinder 介面,讓其它程式可以進行跨程式的繫結 (Binding) 和呼叫。
c、因為共享,所以必須確保多執行緒安全 (Thread-safe) 。
d、以 C++ 類別定義,誕生其物件,透過 SM 之協助,將該物件參考值傳給 IServiceManager::addService() 函式,就加入到 Binder Driver 裡了。
e、應用程式可透過 SM 之協助而遠距繫結該核心服務,此時 SM 會回傳 IBinder 介面給應用程式。
f、應用程式可透過 IBinder::transact() 函式來與核心服務互傳資料。
下面以具體例項講解一下具體的每個步驟如何實現完成
先說明一個測試例子的模組結構:
serviceTestA 是一個普通的過程,提供兩個整數的剩法及除法運算
serviceTestB 是一個普通的過程,提供兩個整數的加法及減法運算
TestService 是一個測試程式的程式,主要驗證兩個服務程式的介面函式,其中的程式碼可以
放在任何一個程式進行訪問呼叫
a、編寫服務程式
serviceTestA.h 標頭檔案定義:
#ifndef __SERVICE_TEST_A__
#define __SERVICE_TEST_A__
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/threads.h>
namespace android{
//繼承BBinder類,從而提供IBinder 介面
class serviceTestA:public BBinder
{
public:
serviceTestA();
virtual ~serviceTestA();
static int instantiate(); //建立唯一類例項
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
private:
// protected by mLock 多執行緒安全
mutable Mutex mLock;
};
}
#endif /* __SERVICE_TEST_A__ */
serviceTestA.cpp 實現檔案:
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>
namespace android {
enum{
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM ,
};
int serviceTestA::instantiate() {
LOGI("serviceTestA instantiate");
int r = defaultServiceManager()->addService(String16("service.TestA"),
new serviceTestA());
LOGI("serviceTestA r = %d/n", r);
return r;
}
serviceTestA::serviceTestA() {
LOGI("serviceTestA created");
}
serviceTestA::~serviceTestA(){
LOGI("serviceTestA destroyed");
}
status_t serviceTestA::onTransact(uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags){
LOGI("serviceTestA::onTransact code = %d",code);
Mutex::Autolock _l(mLock);
switch(code){
case CALCULATE_MUL_NUM:{
int a = data.readInt32();
int b = data.readInt32();
int sum = a * b ;
LOGI("sum mul value = %d",sum);
reply->writeInt32(sum);
return NO_ERROR;
}break;
case CALCULATE_DIV_NUM:{
int a = data.readInt32();
int b = data.readInt32();
int sum = a / b ;
LOGI("sum p value = %d",sum);
reply->writeInt32(sum);
return NO_ERROR;
}break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
return 0;
}
}
Android.mk 檔案:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= serviceTestA.cpp
LOCAL_SHARED_LIBRARIES:= libutils libutils libbinder
LOCAL_C_INCLUDES := $(TOP)/frameworks/base/include
LOCAL_MODULE:= libServiceTestA
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
這裡生成libServiceTestA動態庫,方例升級服務程式
編寫獨立的程式程式:
它的用途是:誕生一個 serviceTestA 類別之物件,然後將該物件參考存入 Binder Driver 裡。
#include <sys/types.h>
#include <unistd.h>
#include <cutils/log.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>
using namespace android;
int main(int argc,char *argv[]){
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
serviceTestA::instantiate(); // 這是重點。。。。
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
Android.mk 檔案:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main.cpp
LOCAL_SHARED_LIBRARIES:= libutils libServiceTestA
LOCAL_MODULE:= serviceTestA
include $(BUILD_EXECUTABLE)
www.2cto.com
這裡最重要的是呼叫:serviceTestA::instantiate();
其先執行到 new serviceTestA() ,就誕生一個 serviceTestA 類別之物件;
接著,呼叫 defaultServiceManager() 函式取得 SM 的 IServiceManager 介面;
再呼叫 IServiceManager::addService() 將該物件參考存入 Binder Driver 裡,並且同時存入
到ServiceManager中註冊並管理,如此其它程式才能通過ServiceManager::getService找到相應服務程式
以上程式碼同理,serviceTestB服務程式也一樣的這樣建立,不再複述。
b、測試服務程式
testService.cpp編寫:
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <serviceTestA/serviceTestA.h>
#include <serviceTestB/serviceTestB.h>
using namespace android;
enum{
CALCULATE_ADD_NUM = 0,
CALCULATE_SUB_NUM ,
};
enum{
CALCULATE_MUL_NUM = 0,
CALCULATE_DIV_NUM ,
};
int main(int argc,char *argv[]){
sp<IBinder> TestAbinder;
sp<IBinder> TestBbinder;
Parcel data, reply;
int sum=0;
LOGI("testService main is call...");
sp<IServiceManager> sm = defaultServiceManager();
while(1){
TestAbinder = sm->getService(String16("service.TestA"));
LOGE("TestA::getAddService %p/n",sm.get());
if (TestAbinder == 0) {
LOGE("TestAService not published, waiting...");
usleep(1000000);
continue;
}
else{
LOGI("TestA::getAddService success...");
break;
}
}
while(1){
TestBbinder = sm->getService(String16("service.TestB"));
LOGE("TestB::getAddService %p/n",sm.get());
if (TestBbinder == 0) {
LOGE("TestBService not published, waiting...");
usleep(1000000);
continue;
}
else{
LOGI("TestB::getAddService success...");
break;
}
}
//測試兩個service中的函式
data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestAbinder->transact(CALCULATE_MUL_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_ADD_NUM value = %d",sum);
data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestAbinder->transact(CALCULATE_DIV_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_SUB_NUM value = %d",sum);
data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestBbinder->transact(CALCULATE_ADD_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_MUL_NUM value = %d",sum);
data.writeInt32(1000);
data.writeInt32(200);
LOGI("BpAddService::create remote()->transact()/n");
TestBbinder->transact(CALCULATE_SUB_NUM,data,&reply);
sum = reply.readInt32();
LOGI("CALCULATE_DIV_NUM value = %d",sum);
return 0;
}
這裡最重要的就是通過defaultServiceManager得到預設的sm,然後通過getService得到sp<IBinder>物件,即可操作相應服務程式的介面函式,整個過程還是相當清晰的。
最後附上測試的結果列印:
# ./TestService
./TestService
# logcat
logcat
--------- beginning of /dev/log/main
I/ ( 1379): testService main is call...
E/ ( 1379): TestA::getAddService 0xa680/n
I/ ( 1379): TestA::getAddService success...
E/ ( 1379): TestB::getAddService 0xa680/n
I/ ( 1379): TestB::getAddService success...
I/ ( 1379): BpAddService::create remote()->transact()/n
I/ ( 1371): serviceTestA::onTransact code = 0
I/ ( 1371): sum mul value = 200000
I/ ( 1379): CALCULATE_MUL_NUM value = 200000
I/ ( 1379): BpAddService::create remote()->transact()/n
I/ ( 1371): serviceTestA::onTransact code = 1
I/ ( 1371): sum p value = 5
I/ ( 1379): CALCULATE_DIV_NUM value = 5
I/ ( 1379): BpAddService::create remote()->transact()/n
I/ ( 1374): serviceTestB::onTransact code = 0
I/ ( 1374): sum add value = 1200
I/ ( 1379): CALCULATE_ADD_NUM value = 1200
I/ ( 1379): BpAddService::create remote()->transact()/n
I/ ( 1374): serviceTestB::onTransact code = 1
I/ ( 1374): sum sub value = 800
I/ ( 1379): CALCULATE_SUB_NUM value = 800
結果表明完全正確
相關文章
- C# Windows Service 服務程式的編寫C#Windows
- 【Azure 應用服務】一個 App Service 同時部署執行兩個及多個 Java 應用程式(Jar包)APPJavaJAR
- React Native與Android通訊互動React NativeAndroid
- Flutter如何和Native通訊-Android視角FlutterAndroid
- [譯] React Native 與 iOS 和 Android 通訊React NativeiOSAndroid
- gRPC 的增刪改查系列之service服務端介面編寫RPC服務端
- Android native程式間通訊例項-binder結合共享記憶體Android記憶體
- Android系統服務編寫例項-Binder(Java層AIDL)AndroidJavaAI
- 畫江湖之 PHP 多程式開發 【通過訊號寫一個類似 nginx services 服務】PHPNginx
- 案例十:shell編寫nginx服務啟動程式Nginx
- Service Mesh大咖訪談:使用服務網格的微服務通訊與治理微服務
- 重新認識React Native和Android的通訊原理React NativeAndroid
- Flutter 的渲染邏輯及和 Native 通訊Flutter
- Flutter與Native通訊示例及原始碼分析Flutter原始碼
- Android跨程式通訊Android
- Android 多程式通訊Android
- grpc套路服務端編寫RPC服務端
- 4-AIII–Service跨程式通訊:aidlAI
- [MDP.NetCore] 使用AzureAD+服務主體,快速建立兩個服務之間的Service身分認證NetCore
- react-native-tencent-im-ui 騰訊雲即時通訊 IM 服務的react-native,使用原生ui版本得sdkReactUI
- Android多程式通訊之幾個基本問題Android
- Android 多程式通訊之幾個基本問題Android
- Android 程式之間通訊Android
- [Android]程式通訊Andromeda框架Android框架
- 微服務的服務間通訊與服務治理微服務
- 用 TypeScript 編寫一個 React 服務端渲染庫(1)TypeScriptReact服務端
- 用 Go 編寫一個簡單的 WebSocket 推送服務GoWeb
- systemd 編寫服務管理指令碼指令碼
- 建立工程,編寫一個介面有兩個按鈕的程式,通過定時器控制這兩個按鈕上的文字變化。定時器
- 如何編寫高效的Android程式碼Android
- 用PHP編寫Android應用程式PHPAndroid
- 寫一個RPC服務RPC
- Android程式間通訊詳解Android
- vscode原始碼分析【七】主程式啟動訊息通訊服務VSCode原始碼
- Android入門教程 | 四大元件之Service(前臺服務,後臺服務)Android元件
- 兩行程式碼 寫個代理行程
- flutter 與native通訊初探Flutter
- Android多程式之手動編寫Binder類Android