方法一:使用Android SDK中的簽名工具給apk簽名:
(1)Android源碼的 build/target/product/security/ 目錄下有 media.pk8、media.x509.pem、platform.pk8、platform.x509.pem、shared.pk8、shared.x509.pem、testkey.pk8、testkey.x509.pem等簽名文件,不同的簽名文件對應不同的權限,Android默認的簽名文件為testkey.pk8、testkey.x509.pem。

(2) Android SDK中的簽名工具為 signapk.jar,具體路徑:out/host/linux-x86/framework/signapk.jar,簽名指令如下:
java -jar signapk.jar platform.x509.pem platform.pk8 old.apk new.apk
8.0上驗證需要額外的一些參數: (直接在源碼根目錄執行簽名,但是7.0以上采用 APK Signature Scheme v2,會導致安裝不了,但是增加參數 --disable-v2 無效,知道原因的朋友還請告知一下!)
java -Xmx2048m -Djava.library.path="out/host/linux-x86/lib64" \
-jar out/host/linux-x86/framework/signapk.jar --disable-v2 \
-w build/target/product/security/platform.x509.pem \
build/target/product/security/platform.pk8 \
old.apk new.apk
方法二:通過Android.mk配置編譯成簽名apk:
(1)編寫Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := app //要簽名的apk名稱 LOCAL_SRC_FILES := app.apk //apk文件 LOCAL_MODULE_CLASS := APPS LOCAL_MODULE_SUFFIX := .apk LOCAL_BUILT_MODULE_STEM := package.apk LOCAL_CERTIFICATE := platform //系統簽名 LOCAL_DEX_PREOPT := false LOCAL_PRIVILEGED_MODULE := true include $(BUILD_PREBUILT)
(2) 將apk放入.mk同目錄(命名為app.apk),配置好sdk編譯環境后執行mm指令編譯,簽名apk生成在:out/target/product/xxxx/system/priv-app/app/app.apk 。
注:LOCAL_CERTIFICATE := platform 表示使用系統簽名
LOCAL_DEX_PREOPT := false 不提前優化,無oat文件
方法三:Android studio配置key簽名:
(1)生成key:
------>生成本地key:

----------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------

------>生成系統平台key:
下載 keytool-importkeypair 工具,使用sdk的security文件生成對應平台的key:
./keytool-importkeypair -k [jks文件名] -p [jks的密碼] -pk8 platform.pk8 -cert platform.x509.pem -alias [jks的別名]
如:
./keytool-importkeypair -k ./SignDemo.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias SignDemo
(2)使用key:
通過以上方法生成的SignDemo.jks更新到android studio原來設置的目錄,下一步即可生成簽名APK:

簽名apk生成路徑:\xxxx\app\release
實質是運行 Sdk\build-tools\27.0.3\lib\apksigner.jar 進行簽名:
V1簽名(jarsigner方式):
//jarsigner -verbose -keystore (簽名地址) -signedjar (簽名后的apk地址) (待簽名apk地址) (別名) jarsigner -verbose -keystore D:\itlao5.keystore -signedjar D:\itlao5_signed.apk D:\itlao5.apk itlao5
V2簽名(apksigner方式):
// apksigner sign --ks (簽名地址) --ks-key-alias (別名) --out (簽名后的apk地址) (待簽名apk地址) apksigner sign --ks D:\itlao5.keystore --ks-key-alias itlao5 --out D:\itlao5_signed.apk D:\itlao5.apk
驗證簽名是否成:
apksigner verify -v --print-certs (apk地址)
每次生成簽名apk都要選擇 Build->Generate Signed APK 配置一下key,豈不是很麻煩?當然有簡化方法,生成.jks后可以在項目的app目錄下的build.gradle中進行配置,步驟如下:
① File -> Project structure -> Signing:

② File -> Project structure -> Flavors:

③ File -> Project structure -> Build Types:

通過以上配置步驟后,可在build.gradle中可以看到增加了如下配置信息(粗體),當然也可以手動直接在build.gradle中輸入配置信息:
android { signingConfigs { release { keyAlias 'SignDemo' keyPassword '123456' storeFile file('E:/project/androidStudio/signAPK/SignDemo.jks') storePassword '1234546' } } ...... buildTypes { release { //生成release apk zipAlignEnabled true //4字節對齊,減少運行內存消耗 minifyEnabled true //false = 關閉混淆 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } debug { //生成debug apk zipAlignEnabled true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
然后通過Build Variants選擇對應的項目版本,直接編譯生成簽名apk,省去之前每次選擇key麻煩。

然而對於一些開源項目,直接在build.gradle中顯式配置key,那密碼等信息就泄露了,所以可以把相關信息定義在local.properties中,因為local.properties存儲的是本地環境資源的一些相關信息,默認不加入代碼版本管理,然后build.gradle中引用其變量即可:
①在local.properties中添加信息:
## This file must *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. #Mon Nov 26 16:21:41 CST 2018 ndk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk\\ndk-bundle sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk keystore.path=E\:/project/androidStudio/signAPK/SignDemo.jks keystore.password=123456 keystore.alias=SignDemo keystore.alias_password=123456
②在build.gradle中引用其定義的值:
signingConfigs { release { //加載資源 Properties properties = new Properties() InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream() properties.load(inputStream) //讀取文件 def sdkDir = properties.getProperty('keystore.path') storeFile file(sdkDir) //讀取字段 def key_keyAlias = properties.getProperty('keystore.alias') def key_keyPassword = properties.getProperty('keystore.password') def key_storePassword = properties.getProperty('keystore.alias_password') keyAlias key_keyAlias keyPassword key_keyPassword storePassword key_storePassword } } ...... buildTypes { release { //生成release apk zipAlignEnabled true //4字節對齊,減少運行內存消耗 minifyEnabled true //false = 關閉混淆 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } }
通過以上方法就可以在build.gradle中隱式配置key,而Project Structure中就不用再配置key相關信息了:

關於system app的提示:
平台簽名的apk,如果 AndroidManifest.xml 中指定是 android:sharedUserId="android.uid.system",即為system app:

-end-
