1.背景
接手的項目近期需要上線,于是復(fù)習(xí)了一下項目簽名文件配置流程,這里做個系統(tǒng)性總結(jié)。
2.最終目標(biāo)
編譯時動態(tài)獲取本地簽名文件,根據(jù)需求來配置自己的debug包與release包的簽名。
3.創(chuàng)建簽名文件
要將簽名文件配置到項目中,首先需要創(chuàng)建一個簽名文件。android studio為我們提供了圖形化創(chuàng)建方式,這里簡單贅述一下:
導(dǎo)航欄build下選擇 generate signed bundle/apk,如下圖:

國內(nèi)的就選擇apk,點擊next:

點擊 create new,創(chuàng)建一個新的簽名文件:

接下來需要填入一些信息,下面的截圖簡單解釋了一下。其中,certificate下的六個填空題,做一個就可以了,這里建議應(yīng)填盡填:

填完之后,點擊OK,進行創(chuàng)建,完事兒~
等等?咋還報錯了嘞?瞅瞅說的啥。。。

哦~ 他讓咱們用命令行遷移到行業(yè)標(biāo)準(zhǔn)格式,那來吧:復(fù)制一下警告彈窗里的那條命令(keytool -importkeystore......pkcs12),打開terminal終端,粘貼進去,點回車,走你~
按照提示,輸入源秘鑰庫口令,就是剛剛設(shè)置的密碼,再回車,走你~
OK,到這里,簽名文件就創(chuàng)建完成了。

4.生成release與debug簽名文件的配置信息
我們需要在app的build.gradle下生成測試包與正式包的配置腳本,來分別配置debug包與release包的不同屬性,比如測試包與正式包都使用自己的簽名文件、正式包開混淆但測試包不開等等,方便我們進行開發(fā)與上線。
android studio也為我們提供了圖形化操作界面,下面一起來走一遍:
導(dǎo)航欄 file -> project structure,進到項目結(jié)構(gòu)界面

項目結(jié)構(gòu)界面依次選擇: modules -> app -> signing configs,如下圖:

點擊“+”新增一個配置信息,輸入release,代表這是用于正式包的簽名文件信息,點擊OK:


輸入相關(guān)信息后,點擊 apply,release包的簽名文件就生成完畢了,同理,生成debug包的簽名文件配置信息,用于日常開發(fā)與調(diào)試,這里建議與release包使用相同的簽名文件,避免相同包名的debug版本與release版本,由于簽名不同而重復(fù)卸載與安裝(插個題外話:必須要讓debug包與release包使用不同簽名文件的小伙伴,可以采用給測試包追加包名的方式,避免正式包與測試包的包名沖突,這里先挖個坑【坑1】,下文來填上)。
release簽名文件配置如圖:

debug簽名文件配置如圖:

點擊OK之后,等待項目配置完成,然后打開項目app目錄下的build.gradle文件,我們可以看到,release包的簽名信息與debug包的簽名信息都已經(jīng)生成,如圖:

但是目前為止,我們僅僅是生成了自己的兩種簽名文件信息,卻還沒配置到測試包與正式包里。那么怎么在編譯測試包或者正式包的時候,讓他們各自使用自己的簽名文件信息呢?先別捉急,咱喝口茶緩一緩先。
5.將簽名文件信息配置給對應(yīng)的包
喝著茶咱也別閑著,來看一看app目錄下build.gradle里面的buildType的信息:

這個bulidType里,記錄著項目的release包、debug包等各種包的配置。咱們可以看到,創(chuàng)建項目的時候,系統(tǒng)為咱們顯式自動生成了release包的配置,但是只配置了兩個值,這里簡單解釋一下:
- minifyEnabled:是否開啟混淆(debug模式默認(rèn)為true,release模式默認(rèn)false)
- proguardFiles:混淆文件(僅在minifyEnabled為true時生效)
OK,接下來咱們先配置release包的簽名文件,依舊是打開項目結(jié)構(gòu)界面,但是選擇 build variants,如圖:

咱們看到,系統(tǒng)已經(jīng)生成了一個release,這個就是正式包的配置文件,咱們這次只需要設(shè)置一下簽名文件就OK了,別的設(shè)置可以自行了解。在signing config下選擇設(shè)置的signingConfigs.release選項,點擊apply來應(yīng)用設(shè)置。
編譯完成后,回到app目錄下的build.gradle,查看buildTypes,如圖:

到這里,release包的簽名文件便配置完成了。
接下來配置debug包的簽名文件,依舊是打開項目結(jié)構(gòu)界面創(chuàng)建變量界面(file-> project structure -> build variants ),選擇app包:

點擊“+”號,輸入debug,點擊OK后,debug包的各項默認(rèn)配置便顯示出來了。

咱們可以根據(jù)需要來更改這些配置,比如,Debuggable(應(yīng)用是否可調(diào)試,底下解釋【埋坑2】)默認(rèn)值是true,這時候咱們可以顯式的指定出來,就給它默認(rèn)值改為手動設(shè)置的true,當(dāng)然,這里不改也是沒問題的Debuggable如下圖:

【坑2】解釋:debuggable,顧名思義,就是是否可調(diào)式,指的是應(yīng)用在運行過程中,能否通過編譯器進行調(diào)試,最直接的表現(xiàn)就是系統(tǒng)日志輸出。默認(rèn)情況下,release包下處于關(guān)閉模式,debug包處于開啟模式,開發(fā)過程中,必要情況下可以更改該值來調(diào)試debug包或者release包。
配置debug包簽名文件操作與配置release包的簽名文件基本一樣,找到 signing config,選擇簽名文件,然后點擊apply來應(yīng)用配置,最后OK,如下圖:

同步完成后,可以看到編譯器已經(jīng)為我們自動產(chǎn)生了debug包的配置信息,并應(yīng)用了咱們自定義的簽名文件:

到這里,簽名文件的基本配置流程已經(jīng)講完了,但是這樣的配置是會產(chǎn)生簽名文件信息的安全問題的。
在談安全問題之前,咱們先填一填前面埋的【坑1】:關(guān)于在debug包追加包名的事兒。有興趣的小伙伴來了解一下,沒興趣的可以跳下一小節(jié)了。
前面提到,為了避免測試包與正式包安裝沖突,咱們可以使用兩種方式,一種是上面的使用同一個簽名文件,另一種是給測試包追加包名,讓他們包名不同,從而避免包名沖突。android studio同樣為我們提供了圖形化追加包名的方式,甚至剛剛我們還見到過。
[ 黑人問號臉.jpg ]
不信你看截圖:

沒錯,就是在這里追加包名,比如我的demo的默認(rèn)包名是com.dylan.signaturetest,我想讓測試包的包名是com.dylan.signaturetest.debug,那么我只需要在這個application id suffix里添加“.debug”即可,如圖:

依次點擊apply與OK后,等待同步完成,查看build.gradle的配置如下:

可以看到,applicationIdSuffix屬性已經(jīng)被添加成功,這時候我們分別運行正式包與測試包,運行方式如圖:


運行結(jié)果如圖:

可以看到,兩個包可以同時存在,查看包名,如圖:


正如我們期望的那樣,正式包與測試包同時存在了。
OK,上面埋的坑填完了,底下講一講上文提到的,簽名文件信息安全問題。
6.將簽名文件信息移動到項目本地配置文件
前面我們發(fā)現(xiàn),簽名文件的文件名、密碼等極其敏感的信息,都是放在項目app包下的build.gradle里的,會隨著項目的發(fā)包,一起發(fā)到各大應(yīng)用市場,這樣安裝包被不懷好意的玩家們進行反編譯后,輕而易舉的就可以獲取到我們的簽名文件信息。除此之外,文件路徑寫在gradle里,在多端協(xié)作開發(fā)同一個項目的時候,大家的簽名文件放置的位置五花八門,也會引起這里gradle文件的簽名文件路徑被多人頻繁修改的問題。
為了避免這種情況,往往我們會將簽名文件的配置信息單獨在本地配置文件local.properties里,該文件在新建項目的時候,android studio會幫我們創(chuàng)建好,位于項目根目錄下,在進行Git版本控制時,默認(rèn)不會被添加到Git提交到遠程倉庫,在別人第一次拉取遠程倉庫代碼時,只需要創(chuàng)建自己的local.properties文件即可。文件截圖如下:

可以看到,我們的android SDK路徑就是在這里配置的,底下我們來編寫代碼,來實現(xiàn)從local.properties文件里讀取簽名文件信息。
首先,local.properties文件內(nèi)指定簽名文件路徑、密碼、別名、別名密碼等信息,如圖:

接著在app目錄下的build.gradle文件的android下編寫代碼,讀取local.properties文件,并讀取指定的信息,如圖:

最后,將讀取到的簽名文件信息配置給signingConfigs內(nèi)debug與release,如圖:

至此,簽名文件從產(chǎn)生到配置的完整流程,算是已經(jīng)講完了。
7.總結(jié)
本文講解了從零開始配置一個android項目簽名文件的完整流程,通過閱讀本文,我們可以對簽名文件配置有一個整體的把握,后續(xù)配置簽名文件也可以一文搞定。
由于筆者能力有限,文章難免出現(xiàn)錯誤,歡迎指正!
附錄:相關(guān)源碼
核心配置文件一共兩點,即項目根目錄下的local.properties與app目錄下的build.gradle文件的android屬性,分別如下:
local.properties
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *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.
sdk.dir=C\:\\Users\\Dylan\\AppData\\Local\\Android\\Sdk
#
#簽名文件配置信息
keyStoreFile=C\:\\Users\\Dylan\\Desktop\\signatureTest.jks
keyStorePassword=123456
keyAlias=key0
keyAliasPassword=123456
使用的時候更換為自己的簽名文件相關(guān)信息。
app//build.gradle
android {
// 讀取local.properties文件
Properties properties = new Properties()
InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream()
properties.load(inputStream)
// 讀取簽名文件
def keyKeyStoreFile = file(properties.getProperty('keyStoreFile'))
// 讀取簽名文件別名、密碼等信息
def keyKeyStorePassword = properties.getProperty('keyStorePassword')
def keyKeyAlias = properties.getProperty('keyAlias')
def keyKeyAliasPassword = properties.getProperty('keyAliasPassword')
signingConfigs {
release {
storeFile keyKeyStoreFile
storePassword keyKeyStorePassword
keyAlias keyKeyAlias
keyPassword keyKeyAliasPassword
}
debug {
storeFile keyKeyStoreFile
storePassword keyKeyStorePassword
keyAlias keyKeyAlias
keyPassword keyKeyAliasPassword
}
}
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.dylan.signaturetest"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.debug
debuggable true
applicationIdSuffix '.debug'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
參考文獻: