通過命令列實現Android工程資原始檔到apk的流程
前言
我們在開發Android應用的時候,可能很少研究整個Apk生成的過程,一般如AS或者Eclipse的開發工具,在執行的時候會自動幫我們將程式碼與資原始檔打包並簽名,生成相應的apk檔案,不知道大家有沒有好奇整個apk的編譯、打包過程呢,下面通過這篇文章,一塊來了解一下一個Android的工程檔案是怎麼從程式碼、資原始檔變成最終的apk檔案的。
命令列演示Android工程專案資源的編譯打包流程
參考官方文件的流程圖,下面我們通過命令列手動的模擬一下整個流程:
本篇文章的環境
首先我的作業系統是基於Windows系統,JDK版本最終使用的是1.6(以上會出現異常),sdk-tools版本是21。
相關工具地址
建立Android工程檔案
進入tools資料夾:
cd D:\eclipse\sdk\tools
命令列:
[android.bat] --target [target_id] --name [project_name] --path [project_path] --package [package_name] --activity[activity_name]
這些引數代表的意思:
佔位符 | 描述 | 本文示例 |
---|---|---|
target_id | sdk版本 | 每個人電腦上面根據安裝的版本不同,id對應的版本也不同,我電腦上的的8,即API21 |
project_name | 工程名稱 | resource2apk |
project_path | 工程路徑 | D:\CSDN\ |
package_name | 包名 | com.csdn.lhy |
activity_name | 建立Activity的名稱 | MainActivity |
D:\eclipse\sdk\tools\android.bat create project --target 8 --name source2apk --path D:\CSDN\ --package com.csdn.lhy --activity MainActivity
執行結果如下,可以看到在相應的目錄下,已經建立了該工程,注意此時是沒有gen目錄的,也就是說此時還沒有生成R檔案。
生成R.java
接下來,我們通過命令列處理相應的資原始檔,來生成R檔案。
命令列:
[aapt.exe] -f -m -J [gen_folder_path] -S [res_path] -I [android.jar_path] -M [manifest_path]
佔位符 | 描述 | 本文示例 |
---|---|---|
aapt.exe | aapt工具路徑 | D:\eclipse\sdk\build-tools\build-tools-21.1.1\aapt.exe |
gen_folder_path | gen目錄路徑 | D:\CSDN\gen |
res_path | res資原始檔路徑 | D:\CSDN\res |
android.jar_path | 覆蓋引導類檔案的位置 | D:\eclipse\sdk\platforms\android-21\android.jar |
manifest_path | AndroidManifest.xml檔案位置 | D:\CSDN\AndroidManifest.xml |
D:\eclipse\sdk\build-tools\build-tools-21.1.1\aapt.exe
D:\eclipse\sdk\build-tools\build-tools-21.1.1\aapt.exe package -f -m -J D:\CSDN\gen -S D:\CSDN\res -I D:\eclipse\sdk\platforms\android-21\android.jar -M D:\CSDN\AndroidManifest.xml
執行之後看到如下,在相應的gen目錄下面,生成了R.java檔案,注意到第一次這個命令列執行失敗,需要人工建立一下gen目錄,第二次執行成功,開啟R檔案,看到裡面已經生成了相應的程式碼。
編譯.java2.class
編譯java檔案生成class ,不要忘記R.java檔案
注意:-bootclasspath
是必須要設定的, 它表示覆蓋引導類檔案的位置,如果不設定會報錯,命令列如下:
javac -target [jdk_version] -bootclasspath [android.jar_path] -d [.java_path]
佔位符 | 描述 | 本文示例 |
---|---|---|
jdk_version | jdk的版本 | 1.6 |
android.jar_path | 覆蓋引導類檔案的位置 | D:\eclipse\sdk\platforms\android-21\android.jar |
.java_path | .java檔案的位置 | 即src檔案下的.java以及gen目錄下的R.java |
javac -target 1.6 -bootclasspath D:\eclipse\sdk\platforms\android-21\android.jar -d D:\CSDN\bin D:\CSDN\src\com\csdn\lhy\*.java D:\CSDN\gen\com\csdn\lhy\R.java
執行成功的話,如下圖所示,在bin目錄下生成了相應的.class檔案,注意不要忽略了R.java。
我們通過JD-GUI開啟看一下,發現可以正常的反編譯回來。
.class2.dex
class打包成dex,需要注意的是,dx工具最好使用建立專案中的sdk版本中的,與bootclasspath所用版本一致,命令列如下:
[dx.bat] --dex --output=[dex_path] [classes_path]
佔位符 | 描述 | 本文示例 |
---|---|---|
dx.bat | dx工具的位置 | D:\eclipse\sdk\build-tools\build-tools-21.1.1\dx.bat |
dex_path | 打包後dex檔案的生成路徑 | D:\CSDN\bin\classes.dex |
classes_path | 當前的.class位元組碼檔案路徑 | D:\CSDN\bin\ |
D:\eclipse\sdk\build-tools\build-tools-21.1.1\dx.bat
D:\eclipse\sdk\build-tools\build-tools-21.1.1\dx.bat --dex --output= D:\CSDN\bin\classes.dex D:\CSDN\bin\
執行成功之後,結果如下圖,我們發現在bin目錄下已經生成了相應的dex檔案:
打包資原始檔
打包資原始檔,將資原始檔打包成resources.ap_檔案,命令列如下:
[aapt.exe] package -f -m -S [res_path] -I [android.jar_path] -M[manifest_path] -F[resources.ap_]
佔位符 | 描述 | 本文示例 |
---|---|---|
aapt.exe | aapt.exe路徑 | D:\eclipse\sdk\build-tools\build-tools-21.1.1\aapt.exe |
res_path | 專案中res資原始檔位置 | D:\eclipse\sdk\platforms\android-21\android.jar |
android.jar_path | 覆蓋引導類檔案的位置 | D:\CSDN\bin\ |
manifest_path | AndroidManifest.xml檔案路徑 | D:\CSDN\AndroidManifest.xml |
resources.ap_ | 打包資原始檔生成的resources.ap_檔案路徑 | D:\CSDN\bin\resources.ap_ |
D:\eclipse\sdk\build-tools\build-tools-21.1.1\aapt.exe package -f -m -S D:\CSDN\res -I D:\eclipse\sdk\platforms\android-21\android.jar -M D:\CSDN\AndroidManifest.xml -F D:\CSDN\bin\resources.ap_
執行結果如下:
生成未簽名的apk
最終打包apk,需要使用apkbuilder.bat 必須放到tools資料夾下面:
[apkbuilder.bat] [unsigned_apk_path] -v -u -z [resources.ap_] -f [classes.dex] -rf [src_path]
佔位符 | 描述 | 本文示例 |
---|---|---|
apkbuilder.bat | apkbuilder.bat路徑 | D:\eclipse\sdk\tools\apkbuilder.bat |
unsigned_apk_path | 生成的未簽名apk檔案路徑 | D:\CSDN\bin\final.apk |
resources.ap_ | 打包資原始檔生成的resources.ap_檔案路徑 | D:\CSDN\bin\resources.ap_ |
classes.dex | classes.dex檔案路徑 | D:\CSDN\bin\classes.dex |
src_path | src資料夾路徑 | D:\CSDN\src |
D:\eclipse\apkbuilder.bat
D:\eclipse\sdk\tools\apkbuilder.bat D:\CSDN\bin\final.apk -v -u -z D:\CSDN\bin\resources.ap_ -f D:\CSDN\bin\classes.dex -rf D:\CSDN\src
我們可以看到執行成功後,在相應的檔案下生成了未簽名的apk檔案。
生成簽名祕鑰
建立密匙,會在當前C:\Users\使用者名稱\
檔案下下生成相應的簽名證書檔案:
keytool -genkey -alias release -keyalg RSA -validity 20000 -keystore release.keystore
apk簽名
jarsigner -verbose -keystore [keystore_path] -storepass [password] -keypass [password] android -signedjar [signed_apk] [unsigned_apk] release
佔位符 | 描述 | 本文示例 |
---|---|---|
keystore_path | 簽名證書路徑 | C:\Users\memphise\release.keystore |
password | 簽名中自己設定的密碼 | 我設定的是android |
signed_apk | 最終生成的簽名之後的apk檔案路徑 | D:\CSDN\bin\resource2jar-signed.apk |
unsigned_apk | 需要簽名的apk檔案路徑 | D:\CSDN\bin\final.apk |
jarsigner -verbose -keystore C:\Users\memphise\release.keystore -storepass android -keypass android -signedjar D:\CSDN\bin\resource2jar-signed.apk D:\CSDN\bin\final.apk release
執行結果如圖,在bin目錄下,生成了剛才簽名的apk檔案。
我們在模擬器上安裝一下,可以看到執行成功,Hello World
異常總結
在將class檔案打包成dex檔案時候遇到:
com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
這是由於jdk版本與dx工具版本不一致的問題,解決方案參考了stackoverflow ,原本我的JDK版本是1.8,這裡打包的時候就遇到了這個問題,最終降級到1.6之後解決了這個問題。
至於Eclipse,AS等工具,使用1.6版本以上的JDK仍然可以打包成功,有哪位大神可以告知一下麼?