說明:由于翻譯水平有限,可能會(huì)存在一些不恰當(dāng)?shù)牡胤剑瑲g迎指出,我會(huì)馬上改正。系列的剩余部分會(huì)陸續(xù)翻譯完晚凿。
- 原文地址:Little Things That Matter
- 原文作者:Dmytro Danylyk
- 譯者 / 校對(duì)者:bincn
本文是配置 Android 項(xiàng)目系列的一部分:
我們?cè)谶@篇文章中討論的一切都可以在 template 項(xiàng)目中找到
gitignore
當(dāng)你在 Android Studio 中創(chuàng)建一個(gè)新的 Android 項(xiàng)目時(shí),它就已經(jīng)生成了 gitignore 文件塘辅,但是通常并不包含所有必要的規(guī)則晃虫。
為了快速生成和下載 gitignore 文件,我推薦你使用 gitignore.io 網(wǎng)站扣墩。只要輸入必要的關(guān)鍵詞哲银,例如 Android扛吞,Intellij,然后點(diǎn)擊生成按鈕荆责。
查看 template 項(xiàng)目的 gitignore 文件滥比。
tools folder
如果你有一些第三方腳本、規(guī)則集或者其他和你項(xiàng)目相關(guān)的文件做院,不要放在根目錄下盲泛,會(huì)造成混亂。(特別是哪些使用項(xiàng)目視圖键耕,而不是 Android 視圖)
嘗試創(chuàng)建一個(gè)文件夾(例如:tools)寺滚,并把這些文件放入這個(gè)文件夾。
通常我會(huì)放入自定義的 gradle 腳本文件屈雄、混淆 (proguard) 規(guī)則和靜態(tài)代碼分析工具村视,例如:pmd、findbugs酒奶、lint蚁孔。
查看 template 項(xiàng)目的 tools 文件夾
flavors
Flavors 用于創(chuàng)建不同設(shè)置的構(gòu)建。在大多數(shù)情況下惋嚎,我會(huì)設(shè)置兩種風(fēng)格杠氢,它們的不同在于:
- applicationId
- versionCode / versionName
- server endpoints
- google services keys
- ...
productFlavors {
dev {
signingConfig signingConfigs.debug
versionCode gitVersionCodeTime
versionName gitVersionName
}
prod {
signingConfig signingConfigs.release
versionCode gitVersionCode
versionName gitVersionName
}
}
查看 template 項(xiàng)目的 productFlavors
keystore
密鑰庫是一個(gè)二進(jìn)制文件,包含一個(gè)或多個(gè)私鑰用于簽名你的應(yīng)用程序另伍。
當(dāng)你在 IDE 中運(yùn)行或者調(diào)試項(xiàng)目鼻百,Android Studio 會(huì)通過 Android SDK 工具生成一個(gè)調(diào)試證書自動(dòng)的簽名你的 APK。
使用本地調(diào)試密鑰庫時(shí)有幾個(gè)問題:
- 365天期滿
- 通過多臺(tái)電腦安裝應(yīng)用需要先卸載
- 谷歌的服務(wù)需要密鑰庫 SHA-1 指紋
這就是為什么我通常生成調(diào)試密鑰庫提交到版本控制系統(tǒng)质况。
signingConfigs {
debug {
keyAlias 'androiddebugkey'
keyPassword 'android'
storePassword 'android'
storeFile file('../keystore/debug.keystore')
}
release {
...
}
}
查看 template 項(xiàng)目的 signingConfigs
proguard
Android 上的混淆器用于三件事:
- 縮小未使用的代碼愕宋,幫助你免于64K限制 (64k limit)
- 優(yōu)化代碼和 APK
- 混淆代碼,使你的 APK 難逆向工程
問題是结榄,混淆和代碼優(yōu)化顯著增加編譯時(shí)間,使調(diào)試更難囤捻。
這就是為什么最好是針對(duì)發(fā)布和調(diào)試構(gòu)建使用不同的混淆器規(guī)則:
- rules-proguard.pro
- rules-proguard-debug.pro
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
"$project.rootDir/tools/rules-proguard.pro"
signingConfig signingConfigs.release
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
"$project.rootDir/tools/rules-proguard-debug.pro"
signingConfig signingConfigs.debug
}
}
對(duì)于調(diào)試構(gòu)建臼朗,混淆器規(guī)則必須具備以下內(nèi)容,強(qiáng)制忽略警告蝎土,跳過代碼混淆與優(yōu)化:
# Add project specific ProGuard rules here.
-dontobfuscate
-dontoptimize
-ignorewarnings
對(duì)于發(fā)布版本設(shè)置混淆器規(guī)則是很難的视哑,因?yàn)閹缀趺恳粋€(gè)庫都會(huì)有它自己特定的規(guī)則。幸好有開源庫 android-proguard-snippets誊涯,包含所有主要庫的混淆規(guī)則挡毅。
# Add project specific ProGuard rules here.
# Remove logs
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
# Proguard configurations for common Android libraries:
# https://github.com/krschultz/android-proguard-snippets
查看 template 項(xiàng)目的 rules-proguard.pro 和 rules-proguard-debug.pro
strict mode
Android 的嚴(yán)格模式 (StrictMode) 幫助你檢測(cè)不同種類的問題:
- 可以關(guān)閉的對(duì)象沒有關(guān)閉
- 在主線程執(zhí)行文件讀取和網(wǎng)絡(luò)請(qǐng)求
- 暴露 uri
- ...
每當(dāng)檢測(cè)到這樣的問題,它可以顯示適當(dāng)?shù)娜罩净蜃寫?yīng)用程序崩潰暴构,這取決于你的配置跪呈。
我建議你在調(diào)試版本中打開它段磨,并且使用 detectAll 方法檢測(cè)各種問題。
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
}
以下是示例 log苹支,當(dāng)你忘記關(guān)閉 SQLiteCursor :
StrictMode:
A resource was acquired at attached stack trace but never released.
See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.open(CloseGuard.java:184)
at android.database.CursorWindow.<init>(CursorWindow.java:111)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:139)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
at com.dd.template.MainActivity.onCreate(MainActivity.java:124)
查看 template 項(xiàng)目的 StrictMode
譯文