Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android源碼環境內置已編譯好的模塊apk_so_jar_bin

android源碼環境內置已編譯好的模塊apk_so_jar_bin

編輯:關於Android編程

0、前言

作為android開發人員,經常面對這樣的問題:網上下載的apk預制到系統,第三方oem提供編譯好的庫或者jar包等,你要將這些編制到你的系統中該如何做,那麼這就不得不要去熟悉android編譯環境,即一系列以LOCAL_XXX這樣的變量。其實我們實際上碰到的編譯MODULE就那麼幾樣,下面我一一列出,可能不全面但是夠用了。  

1、第三方jar靜態編譯

源碼環境使用第三方jar,需要關注三個LOCAL_XXX: LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES值格式為 別名:庫相對路徑 LOCAL_STATIC_JAVA_LIBRARIES BUILD_MULTI_PREBUILT第三方包,編譯類型為BUILD_MULTI_PREBUILT 其中zxing-1.6-core.jar放在apk源碼目錄的libs目錄下 Android.mk如下:
LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
#LOCAL_JAVA_LIBRARIES := ScannerAPI  telephony-common telephony-msim 
LOCAL_STATIC_JAVA_LIBRARIES :=zxing android-support-v4 android-support-v13
LOCAL_SRC_FILES :=$(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := SetInput2
LOCAL_CERTIFICATE := platform   #簽名為platform


include $(BUILD_PACKAGE)


include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=zxing:libs/zxing-1.6-core.jar
include $(BUILD_MULTI_PREBUILT)

2、可執行程序bin

比如我們想內置某些已編譯好的busybox工具 Android.mk如下:
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE        := busybox
LOCAL_MODULE_TAGS   := optional
LOCAL_MODULE_CLASS  := EXECUTABLES
LOCAL_SRC_FILES     := busybox
LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/system/xbin
include $(BUILD_PREBUILT)

3、不帶so的apk

我在源碼環境內置apk時發現有的可以運行,有的不能運行(說缺少lib64下的庫),所以我分開說明如何內置這2中apk。 RAR工具解壓apk沒有lib文件夾的就是不帶so的apk,最簡單。 Android.mk如下:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := rsota
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS  := APPS
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/app
LOCAL_CERTIFICATE := platform   
LOCAL_MODULE_SUFFIX := .apk

include $(BUILD_PREBUILT)

 

4、帶so的apk

解壓apk,發現lib文件夾含有xxx.so就是帶so的apk,一般這些so默認是32位的,當前我們使用的大量的設備都是64位cpu,apk一運行就曝出找不到lib64類型的庫,我們只需要讓他調用apk解壓的那些32位的so庫就行了。  

4.1、so庫架構類型

這裡穿插下關於lib下so的一些故事。如下是youku.apk中lib目錄下的: \ 從這個圖可以看出,這個youku.apk支持3種類型的cpu架構:arm,mips,x86,如果這裡只有armeabi,那麼是絕對不能正常安裝到x86的android設備上的(比如使用x86架構的聯想K900,好像還是科比代言,賣的好慘,反正我沒看到有人用)。如果要提高多架構兼容,就得放入多架構的庫,壞處就是apk好大啊吃手機內存啊,所以X86架構的手機好不好賣不是google決定的啊,是apk廣大開發者決定的啊,沒軟件用,誰屌你,所以X86架構一般只能在幾百塊的水平打醬油,Windows Phone也是沒軟件用的例子。話說到這跑題了,我們繼續庫的類型。lib目錄下一般包含著幾種類型:armeabi,armeabi-v7a,arm64-v8a,mips,x86。不過我們只關注arm的。 armeabi是普通老的32位arm,armeabi-v7a是帶浮點運算及一些高級指令的32位arm,arm64-v8a是近幾年A53 A57架構的64位arm,具體淵源見如下文章 《armeabi-v7a armeabi arm64-v8a》 http://blog.csdn.net/mao520741111/article/details/50328669 現在市面上的基本都是32位apk,所以你基本看不到arm64-v8a庫,但是從android L版本後確實是64位虛擬機了,當然是兼容32位的啦,在64位虛擬機運行當然會默認去運行lib64類型的庫,而我們內置帶so(內置一般都是32位的so)的apk就是要強制讓apk去用現有的32位so,方法如下:

4.2、帶so庫apk例子

1)解包拿出lib下的armeabi或者armeabi-v7a下的xxx.so(最終內置到系統相對於apk目錄的lib/arm下) 2)Android.mk既要內置apk還要copy庫 注意預置模塊,用到BUILD_PREBUILT  

例子一

(apk,so和Android.mk在一個目錄下):

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional eng
LOCAL_MODULE := LiangdusIME
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS  := APPS
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_SUFFIX := .apk
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE        := libLDWWIme
LOCAL_MODULE_CLASS  := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_MULTILIB		:= 32
LOCAL_MODULE_TAGS   := optional
LOCAL_SRC_FILES     := libLDWWIme.so
LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/system/priv-app/LiangdusIME/lib/arm
include $(BUILD_PREBUILT)

  例子一有點缺點,要在$(product).mk中進行如下添加PRODUCT_PACKAGES +=LiangdusIMElibLDWWIme,在庫比較少的時候沒問題,多的時候,就比較麻煩了。比如一個apk有10個庫,那麼Android.mk都要要寫10個module,$(product).mk也要寫上這10個module名,麻煩死了,按道理就是一個apk,就寫一個LOCAL_MODULE,其他的庫應該有某種簡單辦法依賴一起內置,是的確實有那就是BUILD_MULTI_PREBUILT.  

例子二

目錄結構為 ---Android.mk
---SeuicService.apk
---armeabi-v7a
|---libctp_jni.so
|---libkeypad_jni.so
---arm64-v8a
|---libctp_jni.so
|---libkeypad_jni.so  
LOCAL_PATH := $(call my-dir)

#====== so lab =====
include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := armeabi-v7a/libctp_jni.so
LOCAL_MULTILIB := 32
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)

include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := armeabi-v7a/libkeypad_jni.so
LOCAL_MULTILIB := 32
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)

include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := arm64-v8a/libctp_jni.so
LOCAL_MULTILIB := 64
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)

include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := arm64-v8a/libkeypad_jni.so
LOCAL_MULTILIB := 64
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)

# ====  app ========================
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := SeuicService
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := PRESIGNED     #預簽名過了,不需在簽名了
LOCAL_MODULE_PATH := $(TARGET_OUT)/app
LOCAL_REQUIRED_MODULES := \        #本模塊加入系統,我需要的依賴模塊也必須加入
		libkeypad_jni \
	        libctp_jni
LOCAL_SRC_FILES := SeuicService.apk

include $(BUILD_PREBUILT)
其中LOCAL_REQUIRED_MODULES表示預置SeuicService這個模塊時,會先去執行依賴的模塊,就是內置so庫。這樣執行的結果是SeuicService.apk放到了android系統的system/app下,armeabi-v7a的2個so庫內置到了android系統的system/lib/下,arm64-v8a的2個so放到了system/lib64/下,apk不管運行在32還是64位虛擬機都能正常。 例子二的區別是so庫誰都能用,例子一的so庫只有自己能用。  

例子三

目錄結構為 ---Android.mk
---Chrome.apk
---lib
|---armeabi-v7a
|---crazy.libchrome.so
|---libchrome.1847.114.so
|---crazy.libchrome.align
|---libchrome.1916.122.so
|---libchrome.1916.138.so
|---libchrome.1916.141.so
|---libchrome.1985.122.so
|---libchrome.1985.128.so
|---libchrome.1985.131.so
|---libchrome.1985.135.so
|---libchrome.2062.117.so
|---libchrome.2125.102.so
|---libchrome.2125.114.so
|---libchrome.2171.37.so
|---libchrome.2171.59.so
|---libchromium_android_linker.so
|---libchromeview.so  
LOCAL_PATH := $(call my-dir)

# ====  app ========================
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := Chrome
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT)/app
LOCAL_POST_PROCESS_COMMAND := $(shell mkdir -p $(LOCAL_MODULE_PATH)/Chrome/lib/arm) 
LOCAL_POST_PROCESS_COMMAND := $(shell cp -r $(LOCAL_PATH)/lib/armeabi-v7a/* $(LOCAL_MODULE_PATH)/Chrome/lib/arm) 
LOCAL_SRC_FILES := Chrome.apk

include $(BUILD_PREBUILT)

這是自由度最大的的方法,這個LOCAL_POST_PROCESS_COMMAND太厲害了簡直為所欲為,因為它所引起的shell命令在make初期搜索Android.mk就執行了(我試過了可以多次加入執行)那個時候連system目錄等都還沒建立呢,這就是為什麼我先mkdir再去cp,不然cp在目錄沒生成的情況下是失敗的,而且注意了不報錯。所以這種使用方式,需要你預先知道你要干什麼,你得能預料結果,一般我就用mmm編譯然後到out目錄去驗證。  

5、源碼集成帶第三方so,jar的apk

這個是網上找到了
LOCAL_PATH:= $(call my-dir)  

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional  
LOCAL_STATIC_JAVA_LIBRARIES := libbaidumapapi  
LOCAL_SRC_FILES := $(call all-subdir-java-files)  
LOCAL_PACKAGE_NAME := MyMaps  
include $(BUILD_PACKAGE)  

##################################################  

include $(CLEAR_VARS)  

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libbaidumapapi:libs/baidumapapi.jar  
LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so  
LOCAL_MODULE_TAGS := optional  

include $(BUILD_MULTI_PREBUILT)  

6、其他預編譯

其他如各種配置文件的拷貝基本都是通過include $(BUILD_PREBUILT)或者include $(BUILD_MULTI_PREBUILT)來完成,比如   include $(CLEAR_VARS)
LOCAL_MODULE := com.seuic.misc.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)   基本就是修改LOCAL_MODULE名字,或者修改LOCAL_MODULE_CLASS(類型檢查,臨時文件存放等),以及修改LOCAL_MODULE_PATH放到哪。 其中LOCAL_MODULE_CLASS值有:APP,ETC,STATIC_LIBRARIES,EXECUTABLES,JAVA_LIBRARIES,SHARED_LIBRARIES等       另外,Android.mk它也是makefile,不要以為它就是特殊的文件,什麼都強制照搬,思維會定在如何去用LOCAL_XXX上面,如果你足夠熟悉,你可以更靈活點,當然可能不好看。     順便提下 1)上面看到LOCAL_MODULE_TAGS := optional都是要在$(PRODUCT).mk中將模塊名加入到PRODUCT_PACKAGES中的,否則make不編譯別找我。 2)將so提升為系統庫,就是對應so放到android系統的system/lib或者system/lib64下,這樣系統中任何java文件就有機會通過System.loadLibrary("yyy"); 加載libyyy.so,但是,但但是,這個so不是普通c用的so,是jni格式的so。 3)將jar提升為系統包,就是將jar放到android系統的system/framework下,且添加權限,添加權限有2中方法(假設jar文件名為scanner.jar其java包名為com.seuic.scanner,模塊名為scan)。 方法一:在$(PRODUCT).mk中添加PRODUCT_BOOT_JARS+=scan 方法二:在對應的*.rc中追加scanner.jar,用冒號分割,export BOOTCLASSPATH /system/framework/core.jar:scanner.jar,這個基本被方法一替代,不要再使用了,編譯會自動展開PRODUCT_BOOT_JARS,在系統的root目錄下生成init.environ.rc(內容全是export導出的環境變量) 方法三:這個方法獨立性比較好,建議用這個方法。


	

4)Android如何調用第三方SO庫
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved