在應用開(kāi)發(fā)過(guò)程中,常常需要引入第三方JAR包,或將自己的一些代碼打包為JAR包以供其他應用使用,以下將描述這些操作的過(guò)程。需要注意的是,本文所述方法皆是在源碼平臺下的操作。
1.引入第三方JAR包
圖1 測試程序根目錄
如圖1,在應用AppsAut中需要引入第三方JAR包:appsaut.jar,我們將其放到libs目錄中,Android.mk文件應如下編寫(xiě):
圖2 Android.mk的編寫(xiě)
圖中帶有紅色下劃線(xiàn)的第6行,第17行及第20行代碼為引入第三方JAR包的核心代碼,其含義如下。
第6行:指定變量LOCAL_STATIC_JAVA_LIBRARIES的值,其值appsaut代表了所需引入的JAR包,appsaut只是一個(gè)別名,可任取,但必須要與第17中的保持一致;
第17行:為L(cháng)OCAL_PREBUILT_STATIC_JAVA_LIBRARIES賦值。其中冒號前的appsaut要與第6行LOCAL_STATIC_JAVA_LIBRARIES的值相同,而冒號后則為此JAR 包的路徑:即應用根目錄libs目錄中的appsaut.jar文件;
第20行:調用BUILD_MULTI_PREBUILT命令對appsaut.jar進(jìn)行預編譯。
經(jīng)過(guò)以上三步,即可將JAR包appsaut.jar編譯到最終的APK包中。在此需要說(shuō)明的是,第三方appsaut.jar包為L(cháng)OCAL_STATIC_JAVA_LIBRARIES,即.class文件歸檔后得到的JAR包,而B(niǎo)UILD_MULTI_PREBUILT命令的作用則是將靜態(tài)JAVA類(lèi)庫壓縮到.dex文件中--這是在android系統中所使用的JAVA包。
注意:如果系統中存在與第三方JAR包相同的包,則此時(shí)我們的操作會(huì )失敗。
2.編譯自己的JAR包之一(失?。?div style="height:15px;">
在平臺中編譯自己的JAR包,我們將源碼目錄appsaut存放在/external中。其目錄結構如下:
圖3 appsaut目錄結構
源碼存放于src目錄,通過(guò)編寫(xiě)Android.mk及appsaut.xml文件引導JAR包的編譯,最終生成的JAR包不僅在平臺中可用,同時(shí)可導入到手機系統/system/framework中,成為系統文件以供其他程序調用。
[plain]
view plaincopyprint?LOCAL_PATH := $(call my-dir)
# the custom dex'ed emma library ready to put on a device.
# ============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := appsaut
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
#build the permission xml
#=============================================================
#MAKE_XML
include $(CLEAR_VARS)
LOCAL_MODULE := appsaut.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
代碼段1 appsaut模塊的Android.mk文件
以上代碼為工程appsaut的Android.mk的內容。此段代碼完成兩件事情:編譯JAR包與其對應的xml文件。代碼01~07為變量賦值,第8行的代碼通過(guò)調用命令BUILD_JAVA_LIBRARY將appsaut目錄中的代碼編譯為JAR包,此命令的執行會(huì )在out/target/common/obj/JAVA_LIBRARIES/下生成目錄appsaut_intermediates,此目錄下便存放著(zhù)編譯生成的JAR和dex文件;同時(shí),系統還會(huì )將目錄JAR包復制到out/target/product/<product-name>/system/framework/路徑下,如此以來(lái),最終燒寫(xiě)到手機里的系統中的system/framework中便會(huì )存在此JAR包。
但是僅存在JAR包是不夠的,還需要與之對應的權限文件:即appsaut目錄下的appsaut.xml文件,此文件的內容如下所示:
[plain]
view plaincopyprint?<?xml version="1.0" encoding="UTF-8"?>
<permissions>
<library name="com.test.appsaut" file="/system/framework/appsaut.jar"/>
</permissions>
代碼段2 appsaut.jar所對應的權限文件appsaut.xml
此文件中的標簽<library>聲明了一個(gè)JAR包,其中name指定了其名稱(chēng),而file則指定了其存放路徑。Android.mk文件中的代碼10~19通過(guò)對appsaut.xml的編譯,最終將其生成到out/target/product/<product-name>/system/etc/permissions/中,這樣運行在手機里的程序能夠在此文件的引導下使用我們編譯的JAR包:appsaut.jar。與此同時(shí),應用端的Android.mk文件中需要通過(guò)語(yǔ)句LOCAL_JAVA_LIBRARIES := appsaut.jar聲明所使用的JAR包;而AndroidManifest.xml中則要添加如下語(yǔ)句:
<uses-library name="com.test.appsaut"><uses-library>
來(lái)聲明引用的JAR包。遺憾的是,盡管如此折騰了一番,結果卻測試失敗,將以上的JAR包,XML文件及APP應用PUSH到機器上,運行APP,無(wú)法找到JAR包中的類(lèi)??赡苁俏冶救说脑虬?,終歸是沒(méi)有解決,OK,無(wú)奈之下不得不另謀他法,于是便有了下文。
3.將自己的代碼編入android.jar包
將手機ROOT后,進(jìn)入到system/framework目錄,可以看到存在framework.jar文件,此JAR包即android框架層的核心API,我們可以將自己的代碼編入此JAR包從而成為系統API,如此則可由上層APP任意調用我們的代碼--事實(shí)上是擴展了系統的API。
首先,將我們的代碼存放到android源碼的frameworks/base目錄下,需要注意的是,代碼的目錄結構必須為mylib/java/android/mylib(假設我們的代碼均由JAVA寫(xiě)成);
其次,修改build/core/pathmap.mk文件,在變量FRAMEWORKS_BASE_SUBDIRS后添加我們的代碼,如下圖所示:
圖4 將代碼編入android.jar
最后,編譯framework.jar(命令為:mmm frameworks/base),并將其替換掉手機中的system/framework/framework.jar,我們自己的代碼便成為了系統API。
4.將自己的代碼編入ext.jar
3中的方法固然可行,但總覺(jué)得不妥--除非我們真的是在定制系統,否則將自己的代碼放置到external目錄下編譯方為上策。在瀏覽frameworks/base/Android.mk時(shí),無(wú)意中看到了如下內容:
圖5 編譯ext.jar的代碼
顯然,在生成framework.jar的同時(shí)還將external下的部分代碼編譯生成了另一個(gè)JAR包:ext.jar(LOCAL_MODULE := ext),于是迅速進(jìn)入手機里的system/framework目錄,果然看到一個(gè)ext.jar文件,這就意味著(zhù)我們可以將自己的代碼放到external目錄中并編譯到ext.jar(從名字來(lái)看ext應該是extention的縮寫(xiě)吧,呵呵)
首先,將代碼放入external目錄,此時(shí)的目錄結構可任意,如mylib/src/com/test/mylib;
其次,在圖5所示代碼中,將我們的代碼路徑添加到變量ext_dirs中,如下圖所示:
圖6 將自己的代碼編入到ext.jar中
最后,重新編譯ext.jar(命令依然是mmm frameworks/base),并將得到的ext.jar替換掉手機中的system/framework/ext.jar。
注意:在編譯應用程序時(shí),如果此APP用到了ext.jar中的代碼,需要在A(yíng)ndroid.mk文件中引入此JAR包:LOCAL_JAVA_LIBRARIES := ext。
5.BUILD_JAVA_LIBRARY與BUILD_STATIC_JAVA_LIBRARY
在A(yíng)ndroid.mk中可通過(guò)調用include $(BUILD_JAVA_LIBRARY)和include $(BUILD_STATIC_JAVA_LIBRARY)來(lái)分別生成目標設備上的共享JAVA庫與靜態(tài)JAVA庫。二者的區別在于靜態(tài)JAVA庫是由.class文件打包而成JAR包,它在任何一個(gè)JAVA虛擬機上都可以運行;而共享JAVA庫則是在靜態(tài)庫的基礎上進(jìn)一步打包成的.dex文件,眾所周知,dex是在android系統上所使用的文件格式。
由以上結論可做出進(jìn)一步的推論:即Android.mk中變量LOCAL_JAVA_LIBRARIES所指定的為android系統使用的dex類(lèi)庫;而LOCAL_STATIC_JAVA_LIBRARIES變量所指定的則是.class文件打包而成的JAR文件:即靜態(tài)JAVA庫。
BUILD_STATIC_JAVA_LIBRARY會(huì )生成out/target/common/obj/JAVA_LIBRARIES/appsaut_intermediates目錄及其下的JAR文件;而B(niǎo)UILD_JAVA_LIBRARY生成此目錄的同時(shí)會(huì )將其中的JAR包復制到out/target/product/<product-name>/system/framework/中;除此之外,還存在BUILD_HOST_JAVA_LIBRARY命令則是在out/host/linux-x86/framework目錄下生成相應的JAR包。分別使用此三條命令執行的結果如下所示:注意其中帶有紅色下劃線(xiàn)的LOG信息。
圖4 BUILD_STATIC_JAVA_LIBRARY的LOG信息
圖5 BUILD_JAVA_LIBRARY的LOG信息
圖6 BUILD_HOST_JAVA_LIBRARY的LOG信息
6.平臺中添加預編譯的JAR文件
如果需要將已經(jīng)存在的JAR文件添加到整個(gè)編譯系統中,則相應的Android.mk文件需要如下配置(假設添加的JAR包為com.test.myjar):
圖7 平臺中添加預編譯的JAR包
注:
(1)如代碼所示,調用的命令為include $(BUILD_PREBUILT);
(2)此jar包為L(cháng)OCAL_JAVA_LIBRARIES,如代碼所示:LOCAL_MODULE_CLASS := JAVA_LIBRARIES,即dex歸檔文件。
(3)如果是STATIC_JAVA_LIBRARY是否也能如此添加?沒(méi)進(jìn)行相關(guān)驗證,不得而知。如有興趣,可自行驗證。
http://blog.csdn.net/sjz_iron/article/details/8348265