1. 程式人生 > >android APK手動編譯流程

android APK手動編譯流程

apk編譯過程中的流程。

1、首先編譯專案下的資原始檔,生成R.java檔案。因為資原始檔相對獨立,不會跟java檔案存在依賴,相反java檔案要以來資原始檔,因為我們在java檔案中通過R.string.xx來引用具體某個資源。編譯res資原始檔,主要是aap進行編譯。命令使用:

-J :指定R.java的輸出目錄

-M:指定AndroidManifest.xml的位置

-P:指定public_resources.xml的輸出目錄,這個檔案記述了apk資源中屬性的相關描述

-S:指定res目錄的路徑

-I:指定apk專案可能引用的其他資源,比如framework層下的資源。

比如短彩信中會引用framework下的資源

chips_dir := ../../../frameworks/ex/chips/res
res_dirs := $(chips_dir) res
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
aapt package  -z -m  -J out/target/common/obj/APPS/MiuiNotes_intermediates/src -M packages/apps/Notes/AndroidManifest.xml -P out/target/common/obj/APPS/MiuiNotes_intermediates/public_resources.xml -S packages/apps/Notes/res
我們可以看到 -J指定了R.java的輸出目錄 -M,指定了AndroidManifest.xml檔案的路徑 -P指定了public_resource.xml的位置 -S:指定了res的編譯目錄。

執行完aapt命令,那麼就會在相應的輸出目錄中存在一個R.java檔案了。

2、編譯aidl檔案。

我們在上篇文章中展示瞭如何在Android.mk檔案中新增aidl檔案。要編譯aidl檔案需要aidl命令,aidl 引數 輸入 輸出。

3、包含java靜態庫,也就是jar包。

有的模組需要第三方支援,有時候第三方為了保護程式碼,會提供一個jar,沒有原始檔。編譯系統定義了這部分規則。

for f in  out/target/common/obj/JAVA_LIBRARIES/android-support-v4_intermediates/javalib.jar; do if [ ! -f $f ]; then echo Missing file $f; exit 1; fi; unzip -qo $f -d /out/target/common/obj/APPS/MiuiNotes_intermediates/classes; (cd /out/target/common/obj/APPS/MiuiNotes_intermediates/classes && rm -rf META-INF); done
jar檔案會被解壓縮,然後拷貝解壓縮後的class檔案到out下對應app的src目錄下。

4、編譯java原始檔,生成jar包。

首先將找到所有的*.java檔案,將他們編譯生成class檔案。

-bootclasspath:指定java執行庫core.jar。core.jar中包含著Dalvik虛擬機器執行時所需的java庫。

-classpath:指定靜態庫,例如core.jar、framework.jar、ext.jar等。

-d:指明class的輸出路徑

javac -J-Xmx512M -target 1.5 -Xmaxerrs 9999999 -encoding UTF-8 -g  -bootclasspath out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar <span style="font-family: Arial, Helvetica, sans-serif;">-classpath /out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar:/out/target/common/obj/JAVA_LIBRARIES/core-junit_intermediates/classes.jar:/out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar:/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar:/out/target/common/obj/JAVA_LIBRARIES/framework2_intermediates/classes.jar:/out/target/common/obj/JAVA_LIBRARIES/android-support-v4_intermediates/javalib.jar  -extdirs "" -d /out/target/common/obj/APPS/MiuiNotes_intermediates/classes </span>
然後將這些所有的class檔案打包成class.jar包,這些class檔案應該就包含上一步jar包解壓縮後產生的class檔案。
jar -cf /out/target/common/obj/APPS/MiuiNotes_intermediates/classes-full-debug.jar  -C /out/target/common/obj/APPS/MiuiNotes_intermediates/classes .
-cf:c代表建立一個新的jar包,f:指定jar包的名稱。-C:指定jar包包含的檔案,此處就是剛才生成的所有的class檔案。

生成了class-full-debug.jar。

然後執行

acp -fp /out/target/common/obj/APPS/MiuiNotes_intermediates/classes-full-debug.jar /out/target/common/obj/APPS/MiuiNotes_intermediates/classes-jarjar.jar
acp -fp /out/target/common/obj/APPS/MiuiNotes_intermediates/classes-jarjar.jar /out/target/common/obj/APPS/MiuiNotes_intermediates/emma_out/lib/classes-jarjar.jar
acp -fp /out/target/common/obj/APPS/MiuiNotes_intermediates/emma_out/lib/classes-jarjar.jar /out/target/common/obj/APPS/MiuiNotes_intermediates/classes.jar
acp -fp /out/target/common/obj/APPS/MiuiNotes_intermediates/classes.jar /out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes.jar
複製剛才產生的classes-full-debug.jar ,生成四個檔案,classes-jarjar.jar、classed-jarjar.jar、classes.jar、noproguard.classes.jar

5、將jar包轉換為dex檔案。

在android系統中構建了一個java虛擬機器,這個虛擬機器需要的是dex檔案。在編譯系統中我們可以使用dx工具,將jar檔案轉換為dex檔案。

--dex:產生一個dex格式的檔案

--output:指定輸出路徑

最後指定要轉換為dex的jar檔案。

/out/host/linux-x86/bin/dx -JXms16M -JXmx2048M --dex --output=/out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes-with-local.dex     /out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes.jar
生成了noproguard.classes-with-local.dex檔案,接下來
acp -fp /out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes-with-local.dex /out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes.dex
複製產生一個noproguard.classes.dex檔案。

6、編譯資原始檔生成apk包

apk包,本質上是個zip壓縮檔案包。將它解壓縮我們可以看到這個包中檔案列表如下:

inflating: res/layout/activity_main.xml  
  inflating: res/menu/main.xml       
  inflating: AndroidManifest.xml     
 extracting: resources.arsc          
 extracting: res/drawable-hdpi/ic_launcher.png  
 extracting: res/drawable-mdpi/ic_launcher.png  
 extracting: res/drawable-xhdpi/ic_launcher.png  
 extracting: res/drawable-xxhdpi/ic_launcher.png  
  inflating: classes.dex             
  inflating: META-INF/MANIFEST.MF    
  inflating: META-INF/CERT.SF        
  inflating: META-INF/CERT.RSA

包含resource.arsc:包含了所有資原始檔的id值和路徑的對映關係

res目錄:原封不動的複製了開發時的res目錄

class.dex:java原始檔達成jar包,然後dx工具將jar包轉化為jar

AndroidManifest.xml:原始檔的二進位制檔案。

編譯apk時,aapt首先將資原始檔等除class.dex檔案之外的所有檔案打包成apk檔案,然後再將classes.dex檔案新增到apk檔案中。

aapt工具參與了編譯資原始檔,參與了將原始檔打包成apk。編譯資源時使用命令引數 -m -J,-m的含義是告訴aapt使用-J後面的路徑為輸出路徑。在將資原始檔jar包壓縮成apk時,使用-F引數,後面指定輸出路徑。-u代表如果目標apk存在,更新包中的內容。

aapt package -u  -z -c en_US,en_US,cs_CZ,da_DK,de_AT,de_CH,de_DE,de_LI,el_GR,en_AU,en_CA,en_GB,en_NZ,en_SG,es_ES,fr_CA,fr_CH,fr_BE,fr_FR,it_CH,it_IT,ja_JP,ko_KR,nb_NO,nl_BE,nl_NL,pl_PL,pt_PT,ru_RU,sv_SE,tr_TR,zh_CN,zh_HK,zh_TW,am_ET,hi_IN,ug_CN,en_US,fr_FR,it_IT,es_ES,de_DE,nl_NL,cs_CZ,pl_PL,ja_JP,zh_TW,zh_CN,ru_RU,ko_KR,nb_NO,es_US,da_DK,el_GR,tr_TR,pt_PT,pt_BR,rm_CH,sv_SE,bg_BG,ca_ES,en_GB,fi_FI,hi_IN,hr_HR,hu_HU,in_ID,iw_IL,lt_LT,lv_LV,ro_RO,sk_SK,sl_SI,sr_RS,uk_UA,vi_VN,tl_PH,ar_EG,fa_IR,th_TH,sw_TZ,ms_MY,af_ZA,zu_ZA,am_ET,hi_IN,ug_CN,mdpi,nodpi  -M packages/apps/Notes/AndroidManifest.xml -S packages/apps/Notes/res  -I /out/target/common/obj/APPS/framework-res_intermediates/package-export.apk --min-sdk-version 16 --target-sdk-version 16 --product default --version-code 16 --version-name 4.1.2-eng.hlwang.20130310.122659   -F /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk

7、將dex檔案新增到apk包中。

由於apk本身就是個zip壓縮包,因此將dex檔案新增進去的,很容易。

_adtp_classes_dex=/out/target/common/obj/APPS/MiuiNotes_intermediates/classes.dex; cp /out/target/common/obj/APPS/MiuiNotes_intermediates/noproguard.classes.dex $_adtp_classes_dex && /out/host/linux-x86/bin/aapt add -k /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk $_adtp_classes_dex && rm -f $_adtp_classes_dex

首先定義class.dex檔案,然後執行cp,拷貝剛才生成的noproguard.class.dex檔案到class.dex中,然後呼叫aapt add -k命令,將class.dex新增到package.apk中,最後刪除class.dex檔案。

這樣在out下的相應應用的目錄中就產生了一個package.apk檔案了。並且這個package.apk檔案包含了一個完整apk所應該有的所有內容。

有時候我們的apk中需要JNI的支援,那麼我們就需要將JNI所實現的庫包含到apk中。我們通過在Android.mk檔案中對變數LOCAL_JNI_SHARED_LIBRARIES進行賦值。在編譯apk時,我們呼叫了 include $(BUILD_PACKAGE),這個變數在編譯系統中會載入package.mk,在這個檔案中,規則了載入LOCAL_JNI_SHARED_LIBARIES變數所對應的檔案。

jni_shared_libraries := \
    $(addprefix $($(my_prefix)OUT_INTERMEDIATE_LIBRARIES)/, \
      $(addsuffix $(so_suffix), \
        $(LOCAL_JNI_SHARED_LIBRARIES)))
這段程式碼會給要載入進去的庫寫上字首路徑,以及字尾.so。

然後在package.mk後面會判斷這段程式碼是否為空,如果不為空,則將這個庫檔案拷貝到apk目錄下的lib下。

java靜態庫在編譯時不會包含到apk中,動態共享庫會包含到apk中,詳見:http://blog.csdn.net/hailushijie/article/details/8648665

ifneq ($(jni_shared_libraries),)
        $(add-jni-shared-libs-to-package)
endif
關於add-jni-shared-libs-to-package變數的定義實在編譯系統初始化時在definations.mk中定義的。
define add-jni-shared-libs-to-package
$(hide) rm -rf $(dir [email protected])lib
$(hide) mkdir -p $(dir [email protected])lib/$(PRIVATE_JNI_SHARED_LIBRARIES_ABI)
$(hide) cp $(PRIVATE_JNI_SHARED_LIBRARIES) $(dir [email protected])lib/$(PRIVATE_JNI_SHARED_LIBRARIES_ABI)
$(hide) (cd $(dir [email protected]) && zip -r $(notdir [email protected]) lib)
$(hide) rm -rf $(dir [email protected])lib
endef
以原始碼的方式包含庫檔案,package/inputmethods/PinyinIME
include $(BUILD_PACKAGE)

MY_PATH := $(LOCAL_PATH)

include $(MY_PATH)/jni/Android.mk
include $(MY_PATH)/lib/Android.mk

8、對apk檔案進行簽名

mv /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.unsigned
java -jar /out/host/linux-x86/framework/signapk.jar build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8 /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.unsigned /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.signed
mv /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.signed /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk
首先將上一步中的package.apk更名為package.apk.unsigned,然後呼叫signapk.jar、testkey.x509.pem,testkey.pk8給更名的package.apk.unsigned簽名後生成package.apk.signed。

最後在把package.apk.signed更名為package.apk。

9、使用zipalign優化apk內部儲存。

為了提高apk程式的載入速度,使用zipalign對apk進行邊界對齊。

mv /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.signed /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk
mv /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.unaligned
/out/host/linux-x86/bin/zipalign -f 4 /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.unaligned /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.aligned
mv /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk.aligned /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk

過程和簽名基本相似。

10、dex-preopt優化。

dalvik/tools/dex-preopt --dexopt=host/linux-x86/bin/dexopt --build-dir=/out --product-dir=target/product/generic/dex_bootjars --boot-dir=system/framework --boot-jars=core:core-junit:bouncycastle:ext:framework:framework2:android.policy:services:apache-xml --uniprocessor target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk target/product/generic/obj/APPS/MiuiNotes_intermediates/package.odex

package.apk作為輸入檔案,將其中的dex檔案輸出到package.odex中。

將class.dex檔案從package.apk中移除
/out/host/linux-x86/bin/aapt remove /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk classes.dex
這樣package.apk中就不再含有class.dex檔案了。


怎樣設定才能不進行這一步

在我們執行Android.mk時,最後一步,call $BUILD_PACKAGE時,會檢查WITH_DEXPREOPT的值是否為true,然後對LOCAL_DEX_PREOPT進行賦值。

ifneq (true,$(WITH_DEXPREOPT))
LOCAL_DEX_PREOPT :=
else
ifeq (,$(TARGET_BUILD_APPS))
ifneq (,$(LOCAL_SRC_FILES))
ifndef LOCAL_DEX_PREOPT
LOCAL_DEX_PREOPT := true
然後在base_rules.mk中
ifdef (true,$(LOCAL_DEX_PREOPT))
installed_odex := $(basename $(LOCAL_INSTALLED_MODULE)).odex
built_odex := $(basename $(LOCAL_BUILT_MODULE)).odex
$(installed_odex) : $(built_odex) | $(ACP)
        @echo -e ${CL_CYN}"Install: [email protected]"${CL_RST}
        $(copy-file-to-target)

$(LOCAL_INSTALLED_MODULE) : $(installed_odex)
endif
這樣apk在編譯時就能進行dex-preopt優化了。

所以,我們可以更改WITH_DEXPREOPT的值為false,或者更改LOCAL_DEX_PREOPT的值。都ok。WITH_DEXPREOPT的值在BoardConfig.mk中定義,LOCAL_DEX_PREOPT的值在package.mk中定義。

網上有人說修改system.prop檔案,增加

dalvik.vm.verify-bytecode = false不知道是否ok。
如果不進行這個步驟,那麼我們的apk檔案中將會包含所有的檔案,包括class.dex,如果包括這步則apk內不含有class.dex檔案,class.dex將會以應用名.odex檔案存在。

11、odex檔案

dalvik/tools/dex-preopt --dexopt=host/linux-x86/bin/dexopt --build-dir=/out --product-dir=target/product/generic/dex_bootjars --boot-dir=system/framework --boot-jars=core:core-junit:bouncycastle:ext:framework:framework2:android.policy:services:apache-xml --uniprocessor target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk target/product/generic/obj/APPS/MiuiNotes_intermediates/package.odex
odex可能為了加速apk的解析吧。

最後生成了package.odex。

acp -fp /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.odex /out/target/product/generic/system/app/MiuiNotes.odex
拷貝剛才生成的package.odex,生成MiuiNotes.odex。

12、拷貝package.apk生成目標apk

acp -fp /out/target/product/generic/obj/APPS/MiuiNotes_intermediates/package.apk /out/target/product/generic/system/app/MiuiNotes.apk

這樣我們通過編譯同時生成了MiuiNotes.apk以及MiuiNotes.odex檔案。

我們的原始檔class.dex包含在MiuiNotes.odex中,我們的MiuiNotes.apk中包括資原始檔。


相關推薦

android APK手動編譯流程

apk編譯過程中的流程。 1、首先編譯專案下的資原始檔,生成R.java檔案。因為資原始檔相對獨立,不會跟java檔案存在依賴,相反java檔案要以來資原始檔,因為我們在java檔案中通過R.string.xx來引用具體某個資源。編譯res資原始檔,主要是aap進行編譯

Android APK編譯就這麽簡單 詳解(附圖)

雙擊 整合 cmd 進行 自我 nts clas 以及 思路 在學習Android開發的過程你,你往往會去借鑒別人的應用是怎麽開發的,那些漂亮的動畫和精致的布局可能會讓你愛不釋手,作為一個開發者,你可能會很想知道這些效果界面是怎麽去實現的,這時,你便可以對改應用的APK進行

Android APK編譯 apktool使用教程

文件夾 ossh ng- 右鍵 xmu shape func prev pos 2017年棋牌遊戲突然就火了,正所謂春江水暖鴨先知本猿處在軟件行業中就能清晰的感受到市場的變化,最近老家那邊也是玩的風生水起,於是最近閑暇時光想到反編譯下這些棋牌軟件,看看代碼實現的思路

Android APK編譯

exe 下載 最新 free size 輸出 布局文件 最新版本 style 1.官方最新版本下載地址 http://java.decompiler.free.fr/?q=jdgui 2.反編譯流程: ①dex2jar (將apk反編譯成java源碼(classe

Android apk編譯-----【附:反編譯工具】

        Android應用開發完成之後,我們最終都會將應用打包成一個apk檔案,然後讓使用者通過手機或者平板電腦下載下來進行安裝。正常情況下,Android應用打包成apk之後,就無法再看到開發這個應用時使用的資原始檔以及程式碼了。但是我們通過網上提供

android apk編譯(反編譯—改程式碼—再編譯—簽名)

1.工具(請到網站搜尋並自行下載):     ①apktool(反編譯:能得到圖片資源與佈局檔案等)     ②dex2jar(反編譯:能得到activity等java程式碼)     ③jd-gui(檢視dex2jar得到的java檔案)     ④手機簽名工具

Android Apk編譯 dex2j遇到如下問題 com.googlecode.d2j.DexException: not support version.

控制檯執行 如下命令 d2j-dex2jar.bat classes.dex //報如下錯誤 com.googlecode.d2j.DexException: not support version. at com.googlecode.d2j.read

Android APK編譯詳解(附圖)

這段時間在學Android應用開發,在想既然是用Java開發的應該很好反編譯從而得到原始碼吧,google了一下,確實很簡單,以下是我的實踐過程。 在此鄭重宣告,貼出來的目的不是為了去破解人家的軟體,完全是一種學習的態度,不過好像通過這種方式也可以去漢化一些外國軟體。

Android平臺交叉編譯流程

一: 當我們在Android平臺上開發一些軟體的時候,有時不可避免的要用到一些用c/c++所編寫的庫。有些庫有大神們已經封裝好了在特定平臺上對應的api,我們直接呼叫就可以,但是更多的庫需要我們自己根據自己所需的特定的平臺去進行編譯。 二: 不同的目標平臺都有明確的編譯器

Android 混淆程式碼總結 和 Android APK編譯(最新更新)

http://blog.csdn.net/vipzjyno1/article/details/21039349/ http://blog.csdn.net/vipzjyno1/article/details/21039349/  反編譯 在學習Android開發的過程你

Android APK編譯就這麼簡單 詳解(附圖)

From: http://blog.csdn.net/vipzjyno1/article/details/21039349 在學習Android開發的過程你,你往往會去借鑑別人的應用是怎麼開發的,那些漂亮的動畫和精緻的佈局可能會讓你愛不釋手,作為一個開發者,你可能會很想知

Android apk編譯步驟

一. apktool 下載apktool.bat,開啟wrapper script 然後右鍵儲存連結 下載apktool.jar檔案,重名為apktool.jar 在電腦上建一個資料夾儲存apktool.jar 和 apktool.bat檔案 如:

android apk編譯安全檢查----shared_preferences任意讀寫漏洞

測試某apk時,使用http://appscan.360.cn進行首次分析,報出存在shred_prefs任意讀寫的問題。於是研究一下測試思路。此文純屬個人分析,若有不對指出,還請指出。 一、sha

mac android apk編譯

在mac os系統上反編譯android apk,首先需要準備好以下3個檔案:1、apktool:https://ibotpeaches.github.io/Apktool/install/  2、dex2jar:https://github.com/pxb1988/dex2jar 3、jd-gui:http

Android APK編譯及去廣告漢化,apk優化簽名等

概述 Android APK反編譯是個有趣的事情。我們可以對APK反編譯進行漢化破解工作等。 Android APK反編譯主要涉及三個工具的使用,分別是 apktooldex2jarjd-gui(即jad)最後介紹了一款國人開發的整合反編譯工具AndroidKiller

Android APK編譯、重打包、重簽名

準備工作 Apk反編譯 個人覺得這兩個檔案直接放到 C:\Windows 下比較方便,開啟dos命令可以直接使用 反編譯命令列 apktool d -f 需要反編譯的apk -o 反編譯生成的目錄 例如:apktool d -f

[置頂] Android APK編譯就這麼簡單 詳解(附圖)

在學習Android開發的過程你,你往往會去借鑑別人的應用是怎麼開發的,那些漂亮的動畫和精緻的佈局可能會讓你愛不釋手,作為一個開發者,你可能會很想知道這些效果介面是怎麼去實現的,這時,你便可以對改應用的APK進行反編譯檢視。下面是我參考了一些文章後簡單的教程詳解。 (注

Android APK編譯之工具篇

平時使用問題 以上的工具,不一定說只選擇一種工具。在拿的一個apk的時候,優先可以使用 Jadx 工具,因為它可以直接開啟apk,並且發編譯出來的程式碼可讀性更高。如果這個工具反編譯出來的內容有問題,或者apk本身做了針對它的處理,再選擇ApkTool工具進行解壓縮,然後分析smali程式碼,這個就需要你對

Android APK編譯方法(可以獲取APK xml和android Manifest,java程式碼等內容)

APK反編譯和簽名 apk檔案反編譯以及簽名打包 通過dex2jar和jd我們可以反編譯apk中的dex,可以比較完美的檢視java原始檔;通過apktool可以反編譯apk中的xml等資原始檔,然後通過apk-sign簽名,可以製作成修改版的可釋出apk檔案。 1.dex

Android APK編譯:APKtool使用詳解

bug -s safe 下載 code 要掌握 所有 class deb 導言:在我們安卓開發當中,我們不僅需要掌握基礎的開發技能,也需要掌握軟件的安全技能,這樣才可以讓我們的軟件能夠成為一款能夠真正可以進行發布的軟件,同時也可以讓自己的核心技術不會被別人所盜取。