1. 為什麼要簽名
1) 寄件者的身份認證
由於開發商可能通過使用相同的Package Name來混淆替換已經安裝的程式,以此保證簽名不同的包不被替換
2) 保證資訊傳輸的完整性
簽名對於包中的每個檔案進行處理,以此確保包中內容不被替換
3) 防止交易中的抵賴發生,Market對軟體的要求
2. 簽名的說明
1) 所有的應用程式都必須有數位憑證,Android系統不會安裝一個沒有數位憑證的應用程式
2) Android程式包使用的數位憑證可以是自簽名的,不需要一個權威的數位憑證機構簽名認證
3) 如果要正式發布一個Android應用,必須使用一個合適的私密金鑰產生的數位憑證來給程式簽名,而不能使用adt外掛程式或者ant工具產生的調試認證來發布
4) 數位憑證都是有有效期間的,Android只是在應用程式安裝的時候才會檢查認證的有效期間。如果程式已經安裝在系統中,即使認證到期也不會影響程式的正常功能
5) 簽名後需使用zipalign最佳化程式
6) Android將數位憑證用來標識應用程式的作者和在應用程式之間建立信任關係,而不是用來決定終端使用者可以安裝哪些應用程式
3. 簽名的方法
有三種打包方式:命令列手動打包、ant自動編譯打包、eclipse+ADT編譯打包,打包步驟如下:
第一步 產生R.java類檔案:
Eclipse中會自動產生R.java,ant和命令列使用android SDK提供的aapt.ext程式產生R.java。
第二步 將.aidl檔案產生.java類檔案:
Eclipse中自動產生,ant和命令列使用android SDK提供的aidl.exe產生.java檔案。
第三步 編譯.java類檔案產生class檔案:
Eclipse中自動產生,ant和命令列使用jdk的javac編譯java類檔案產生class檔案。
第四步 將class檔案打包產生classes.dex檔案:
Eclipse中自動產生,ant和命令列使用android SDK提供的dx.bat命令列指令碼產生classes.dex檔案。
第五步 打包資源檔(包括res、assets、androidmanifest.xml等):
Eclipse中自動產生,ant和命令列使用Android SDK提供的aapt.exe產生資源套件檔案。
第六步 產生未簽名的apk安裝檔案:
Eclipse中自動產生debug簽名檔案存放在bin目錄中,ant和命令列使用android SDK提供的apkbuilder.bat命令指令碼產生未簽名的apk安裝檔案。
第七步 對未簽名的apk進行簽名產生簽名後的android檔案:
Eclipse中使用Android Tools進行簽名,ant和命令列使用jdk的jarsigner對未簽名的包進行apk簽名。
3.1 用eclipse+ADT方式簽名
詳見:http://jojol-zhou.iteye.com/blog/719428
a) 調試簽名
eclipse外掛程式預設賦予程式一個DEBUG許可權的簽名,此簽名的程式不能發布到market上,此簽名有效期間為一年,如果到期則導致你無法產生apk檔案,此時你只要刪除debug keystore即可,系統又會為你產生有效期間為一年的新簽名
b) 開發人員產生密鑰並簽名
右鍵點擊項目名,在菜單中選擇Android Tools,然後選擇Export Signed Application Package,即可通過eclipse自訂認證並簽名
c) 開發人員匯出未簽名的包
右鍵點擊項目名,在菜單中選擇Android Tools,然後選擇Export Signed Application Package…,即可匯出未簽名的包,之後可通過命令列方式簽名
3.2 用命令列方式簽名
使用標準的java工具keytool和jarsigner來產生認證和給程式簽名。
詳見:http://jojol-zhou.iteye.com/blog/729254
a) 產生簽名
$ keytool -genkey -keystore keyfile -keyalg RSA -validity 10000 -alias yan
註:validity為天數,keyfile為產生key存放的檔案,yan為私密金鑰,RSA為指定的密碼編譯演算法(可用RSA或DSA)
b) 為apk檔案簽名
$ jarsigner -verbose -keystore keyfile -signedjar signed.apk base.apk yan
註:keyfile為產生key存放的檔案,signed.apk為簽名後的apk,base.apk 為未簽名的apk,yan為私密金鑰
c) 看某個apk是否經過了簽名
$ jarsigner -verify my_application.apk
d) 最佳化(簽名後需要做對齊最佳化處理)
$ zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk
3.3 在源碼中編譯的簽名
a) 使用源碼中的預設簽名
在源碼中編譯一般都使用預設簽名的,在某源碼目錄中用運行
$ mm showcommands能看到簽名命令
Android提供了簽名的程式signapk.jar,用法如下:
$ signapk publickey.x509[.pem] privatekey.pk8 input.jar output.jar
*.x509.pem為x509格式公開金鑰,pk8為私密金鑰
build/target/product/security目錄中有四組預設簽名可選:testkey platform shared media(具體見README.txt),應用程式中Android.mk中有一個LOCAL_CERTIFICATE欄位,由它指定用哪個key簽名,未指定的預設用testkey.
b) 在源碼中自簽名
Android提供了一個指令碼mkkey.sh(build/target/product/security/mkkey.sh),用於產生密鑰,產生後在應用程式中通過Android.mk中的LOCAL_CERTIFICATE欄位指名用哪個簽名
c) mkkey.sh介紹
i. 產生公開金鑰
openssl genrsa -3 -out testkey.pem 2048
其中-3是演算法的參數,2048是密鑰長度,testkey.pem是輸出的檔案
ii. 轉成x509格式(含作者有效期間等)
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj ‘/C=US/ST=California/L=MountainView/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’
iii. 產生私密金鑰
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt
把的格式轉換成PKCS #8,這裡指定了-nocryp,表示不加密,所以簽名時不用輸入密碼
4. 簽名的相關檔案
1) apk包中籤名相關的檔案在meta_INF目錄下
CERT.SF:產生每個檔案相對的密鑰
MANIFEST.MF:數位簽章資訊
xxx.SF:這是JAR檔案的簽名檔案,預留位置xxx標識了簽名者
xxx.DSA:對輸出檔案的簽名和公開金鑰
2) 相關源碼
development/tools/jarutils/src/com.anroid.jarutils/SignedJarBuilder.java
frameworks/base/services/java/com/android/server/PackageManagerService.java
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
dalvik/libcore/security/src/main/java/java/security/Sign*
build/target/product/security/platform.*
build/tools/signapk/*
5. 簽名的相關問題
一般在安裝時提示出錯:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
1) 兩個應用,名字相同,簽名不同
2) 升級時前一版本簽名,後一版本沒簽名
3) 升級時前一版本為DEBUG簽名,後一個為自訂簽名
4) 升級時前一版本為Android源碼中的簽
5.1 查看預設簽名
不同的機子上或不同的裝置上,利用eclipse編譯出的apk簽名是不一樣的。eclipse都有一個預設的簽名。查看簽名路徑:
1)開啟EclipseàWindowàAndoridàBuild,在這個Build介面,找到Default debug keysore這個編輯框,裡面的值則為本台裝置中Eclipse的keystore的預設路徑。
2)如果出現因簽名不同而導致應用程式未安裝,可以將原先的keystore替換掉當前裝置上的keystore。並重新啟動Eclipse。否則只能完全卸載掉行動裝置上的apk,重新安裝了。
5.2 無法覆蓋安裝
1、通過簽名的方式產生你的APK,而不是直接從Bin目錄底下去拷貝,每個Android可執行程式的APK都有自己的簽名,只要簽名一致,就可以覆蓋安裝,而不需要卸載;
2、資料庫表結構的變化(增加一個欄位,減少一個欄位,新表的建立)。正常升級資料庫的方法 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
3、sharepreferences的資料有改變,這個跟資料庫差不多,比如原來的sharepreferences儲存的一資料是boolean,在後一版本把儲存的資料改為string,問題就出現了。
5.3 匯出簽名
1)開啟cmd控制台,輸入命令:keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore,按照提示依次填寫內容,並記住密碼,後面會用到;
2)產生好keystore後,就可以匯出簽名apk了。Eclipse中,右擊需要簽名的工程àandroid toolsàexport signed application package,location為產生的keystore所在的位置,密碼為建立keystore時設定的密碼,然後按照提示,next,最後finish,成功匯出簽名apk。
詳見:http://blog.csdn.net/yiwanxinyuefml/article/details/6765129
5.4 debug簽名和release簽名的區別
1)debug簽名的應用程式不能在Android Market上架銷售,它會強制你使用自己的簽名;Debug模式下籤名用的認證(預設是Eclipse/ADT和Ant編譯)自從它建立之日起,1年後就會失效。
2)debug.keystore在不同的機器上所產生的可能都不一樣,就意味著如果你換了機器進行apk版本升級,那麼將會出現上面那種程式不能覆蓋安裝的問題,相當於軟體不具備升級功能!
6. Zipalign簡單最佳化6.1 為什麼要最佳化
Android SDK中包含一個“zipalign”的工具,它能夠對打包的應用程式進行最佳化。在你的應用程式上運行zipalign,使得在運行時Android與應用程式間的互動更加有效率。因此,這種方式能夠讓應用程式和整個系統運行得更快。我們強烈推薦在新的和已經發布的程式上使用zipalign工具來得到最佳化後的版本——即使你的程式是在老版本的Android平台下開發的。
6.2 如何有助於效能改善
在Android中,每個應用程式中儲存的資料檔案都會被多個進程訪問;安裝程式會讀取應用程式的manifest檔案來處理與之相關的許可權問題;Home應用程式會讀取資源檔來擷取應用程式的名和表徵圖;系統服務會因為很多種原因讀取資源(例如,顯示應用程式的Notification);此外,就是應用程式自身用到資源檔。
在Android中,當資源檔通過記憶體映射對齊到4位元組邊界時,訪問資源檔的代碼才是有效率的。但是,如果資源本身沒有進行對齊處理(未使用zipalign工具),它就必須回到老路上,顯式地讀取它們——這個過程將會比較緩慢且會花費額外的記憶體。
對於應用程式開發人員來說,這種顯式讀取方式是相當便利的。它允許使用一些不同的開發方法,包括正常流程中不包含對齊的資源,因此,這種讀取方式具有很大的便利性(本段的原始意思請參考原文)。
遺憾的是,對於使用者來說,這個情況恰恰是相反的——從未對齊的apk中讀取資源比較慢且花費較多記憶體。最好的情況是,Home程式和未對齊的程式啟動得比對齊後的慢(這也是唯一可見的效果)。最壞的情況是,安裝一些未對齊資源的應用程式會增加記憶體壓力,並因此造成系統反覆地啟動和殺死進程。最終,使用者放棄使用如此慢又耗電的裝置。
6.3 如何最佳化
1)使用ADT:
如果你使用匯出嚮導的話,Eclipse中的ADT外掛程式(從Ver.0.9.3開始)就能自動對齊Release程式包。
使用嚮導,右擊工程屬性,選擇Android ToolsàExport Signed Application Package。當然,你還可以通過AndroidManifest.xml編輯器的第一頁做到。
2)使用Ant:
Ant編譯指令碼(從Android 1.6開始)可以對齊程式包。老平台的版本不能通過Ant編譯指令碼進行對齊,必須手動對齊。
從Android 1.6開始,Debug模式下編譯時間,Ant自動對齊和簽名程式包。
Release模式下,如果有足夠的資訊簽名程式包的話,Ant才會執行對齊操作,因為對齊處理髮生在簽名之後。為了能夠簽名程式包,進而執行對齊操作,Ant必須知道keystore的位置以及build.properties中key的名字。相應的屬性名稱為key.store和key.alias。如果這些屬性為空白,簽名工具會在編譯過程中提示輸入store/key的密碼,然後指令碼會執行簽名及apk檔案的對齊。如果這些屬性都沒有,Release程式包不會進行簽名,自然也就不會進行對齊了。
3)手動:
為了能夠手動對齊程式包,Android 1.6及以後的SDK的tools/檔案夾下都有zipalign工具。你可以使用它來對齊任何版本下的程式包。你必須在簽名apk檔案後進行,使用以下命令:zipalign -v 4 source.apk destination.apk
4)驗證對齊:
zipalign -c -v 4 application.apk