從零開始怎麼寫android native service
Android service對于從事android開發的人都不是一個陌生的東西,很多人可能會覺得服務很簡單。服務是簡單,因為複雜的别人做了,是以才會覺得簡單。我們先梳理一下服務的分類,首先有本地服務跟系統服務的區分,而在APP裡寫的服務大多就成為Java服務或者應用服務。
/****************************************************************************************************/
聲明:本博内容均由http://blog.csdn.net/edsam49原創,轉載請注明出處,謝謝!
/*****************************************************************************************************/
做APP的人寫個應用服務相對來說是最簡單的,因為extends了一個service後幾個簡單的接口就可以跑起來了,寫完這種服務可能也隻是對服務一知半解,因為值錢的service類Google的人已經幫你寫好了,這是你的福氣為你帶來了便利,當然也可能會麻痹你:),但是做APP的人會有能解決問題是首要任務了,有時間還是對它了解更清楚點比較好,在此不再讨論這個。
做裝置做系統的人,經常可能會去寫系統服務,也就是framework下面的服務,systemserver裡面注冊的服務,寫這種服務一般來說比較少,隻有做裝置系統的才會這樣幹,才有機會有完成的系統代碼,可以在裡面自由遨遊,筆者三年前寫過一個,可以看看【自己動手從零開始寫一個完整的android Service】http://blog.csdn.net/edsam49/article/details/8163639
那剩下的一個是本地服務,也就是native service,這種服務我們了解的系統裡面多媒體、audio system都是寫成了本地服務,這樣寫的好處就是運作的效率更高一點,因為C/C++先天性就比JAVA的運作效率要高一點。筆者就是由于長期主要從事的都是底層開發的,我們有時有這麼一種需求,又要運作效率高,又要好移植,主要是考慮推廣寫東西給廣大客戶,那麼我就寫一個本地服務,這樣是最獨立的了,效率也最高了,那一個本地服務到底怎麼寫呢?大多數的人寫過的服務以java服務居多,真正寫本地服務的不多,本地服務相對來說又是更複雜一點的。是以決定從零開始自己動手寫一個本地service,下面就大概描述一下過程。
本地服務有四大塊,服務接口(IService),服務代理(也就是BpService),服務stub(也就是BnService),服務實體(Service);下面筆者的執行個體就以demoNativeService來開啟,力求簡單,裡面就寫了兩個接口;
首先定義好服務接口IdemoNativeService,IdemoNativeService服務接口的父類是IInterface,在裡面主要是要聲明一下接口,在DECLARE_META_INTERFACE(demoNativeService),代碼如下:
當然定義好了IdemoNativeService的頭檔案,就需要去實操了,先來搞定BpdemoNativeService,它的父類是BpInterface<IdemoNativeService>,這裡面主要是涉及資料的跨程序用到的parcel,讀啊,寫啊,按套路來,也不難,也有AIDL工具可以使用,幫你轉出來,再稍微修改一下就可以了,裡面有一個很重要的remote,這個和remote就是幕後功臣啊,它儲存了服務執行個體的對象啊,它是來之BpRefBase的一個成員,生成服務的時候,會得到指派,定義完了以後,很重要的一個程式就是要IMPLEMENT_META_INTERFACE(demoNativeService,"android.hardware.IdemoNativeService");這個宏是非常重要的,跟前面那個DECLARE是對應的,前面聲明,後面實作,當然我們帶的參數跟的名字是必須一緻的,這樣才能正常溝通嘛!
接着需要寫服務stub了,BndemoNativeService的父類是BnInterface<IdemoNativeService>,有沒有發現BndemoNativeService跟BpdemoNativeService,都會基于接口類IdemoNativeService,這樣溝通起來的接口就唯一了,就具備了對話的可能;
到這就輪到了大塊頭service實體demoNativeService了,demoNativeService是基于BndemoNativeService,在demoNativeService裡面定義了一個instantiate()接口用于添加service到servicemanager裡面去,注意demoNativeService()跟析構函數~demoNativeService()需要寫成private的,免得别人可以new出對象來。在裡面重寫了onTransact,一旦BpdemoNativeService有風吹草動,就會關聯到BndemoNativeService,因為服務實體重寫了onTransact,是以實際就會先執行到demoNativeService::onTransact這裡來,在這裡面處理不了,可以再轉給BpdemoNativeService的onTransact或者直接到BBinder的onTransact;
寫完了服務,那我們就再寫一個可執行檔案來生成一下,裡面startThreadPool生成線程池,然後再調用joinThreadPool來監聽變化;
寫到這,可以說服務已經可以跑起來了,那我們怎麼驗證呢,最快的辦法還是寫一個可執行檔案去測一下它的接口,看通沒通就知道了;
下面就是筆者測試的列印,如下:
寫到這,如果要給應用調用的話,還需要寫Client,JNI,JNI及以上在此不再讨論了,我們就簡易來看看client怎麼處理吧,其實有點類似上面那個可執行檔案的寫法,這裡可能就是有一個對象的概念,可以保持,大概如下:
羅哩羅嗦寫了這麼多,請大家拍磚,輕拍一下:)