gradle概覽
Project build.gradle
//配置構建過程
buildscript {
//配置依賴倉庫 maven
repositories {
mavenCentral()
}
//配置依賴插件 gradle
dependencies {
classpath 'com.android.tools.build:gradle:0.11.1'
}
}
//應用android插件
apply plugin: 'android'
//配置android構建所需所有參數
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
}
Module build.gradle
下面是實際項目的一個截圖,我們常用的幾個頂層配置都在這了,我們重點關注android這個配置項,其他幾項不太需要修改
接下來看下android配置項下面的子集
defaultConfig{} 默認配置,是ProductFlavor類型。它共享給其他ProductFlavor使用
sourceSets{ } 源文件目錄設置,是AndroidSourceSet類型。
buildTypes{ } BuildType類型
signingConfigs{ } 簽名配置,SigningConfig類型
productFlavors{ } 產品風格配置,ProductFlavor類型
testOptions{ } 測試配置,TestOptions類型
aaptOptions{ } aapt配置,AaptOptions類型
lintOptions{ } lint配置,LintOptions類型
dexOptions{ } dex配置,DexOptions類型
compileOptions{ } 編譯配置,CompileOptions類型
packagingOptions{ } PackagingOptions類型
jacoco{ } JacocoExtension類型。 用於設定 jacoco版本
splits{ } Splits類型
下面列幾個常用的配置項,
lintOptions {
lintConfig file("lint.xml")
abortOnError false
}
sourceSets { //目錄指向配置
main {
manifest.srcFile 'AndroidManifest.xml' //指定 AndroidManifest 文件
java.srcDirs = ['src'] //指定 source 目錄
resources.srcDirs = ['src'] //指定 source 目錄
aidl.srcDirs = ['src'] //指定 source 目錄
renderscript.srcDirs = ['src'] //指定 source 目錄
res.srcDirs = ['res'] //指定資源目錄
assets.srcDirs = ['assets'] //指定 assets 目錄
jniLibs.srcDirs = ['libs'] //指定 lib 庫目錄
}
debug.setRoot('build-types/debug') //指定 debug 模式的路徑
release.setRoot('build-types/release') //指定 release 模式的路徑
}
signingConfigs { //簽名配置
release { //發佈版本簽名配置
storeFile file("fk.keystore") //密鑰文件路徑
storePassword "123" //密鑰文件密碼
keyAlias "fk" //key 別名
keyPassword "123" //key 密碼
}
debug { //debug版本簽名配置
storeFile file("fk.keystore")
storePassword "123"
keyAlias "fk"
keyPassword "123"
}
}
buildType { // build 類型
release { //發佈
minifyEnabled true //混淆開啓
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-android.txt' //指定混淆規則文件
signingConfig signingConfigs.release //設置簽名信息
}
debug { //調試
signingConfig signingConfigs.release
}
custom {//自定義類型
minifyEnabled false
renderscriptDebuggable true
}
}
local.properties
配置sdk.dir屬性,配置這個跟配置ANDROID_HOME環境變量差不多
任務
● assemble 這個任務會彙集工程的所有輸出。
● check 這個任務會執行所有校驗檢查
● connectedCheck 運行checks需要一個連接的設備或者模擬器,這些checks將會同時運行在所有連接的設備上。
● deviceCheck 通過API連接遠程設備運行checks。它被用於CI(譯者注:持續集成)服務器上。
● build 這個任務會同時執行 assemble 和 check 任務
● clean 這個任務會清理工程的所有輸出
共享變量
定義整個項目的公共變量,如sdk版本等,讓所有子module都使用同樣的配置
新建common_config.gradle文件
project.ext{
//java語言相關
javaVersion = 8
javaMaxHeapSize = '4G'
//Android編譯相關
compileSdkVersion = 23
buildToolsVersion = '23.1.1'
minSdkVersion = 16
targetSdkVersion = 23
//混淆相關
minifyEnbale = true
shrinkResEnable = minifyEnable
//JDK版本兼容
sourceCompatibility = this.&getJavaVersion()
targetCompatibility = this.&getJavaVersion()
}
def getJavaVersion(){
switch(project.ext.javaVersion){
case "6":
return JavaVersion.VERSION_1_6
case "7":
return JavaVersion.VERSION_1_7
case "8":
return JavaVersion.VERSION_1_8
default:
return JavaVersion.VERSION_1_6
}
}
module中使用
apply from: "${project.rootDir}/common_config.gradle"
minSDKVersion project.ext.minSdkVersion
除了在每個module中進行如上配置導入common_config.gradle之外還可以使用下面方式
只需在Project的build.gradle做如下一次性配置
subprojects{
apply from: "${project.rootDir}/common_config.gradle"
dependencies{
testCompile 'junit:junit:4.12'
}
}
多渠道打包
上面的常用內容配置一個apk的打包足夠了,但很多時候我們應用上架需要配置多個應用商店每個apk包都有一些不同的信息,下面看看這種情況如何處理。
多渠道需要處理的主要就是每個渠道都有一些各自的參數,下面看看這方面怎麼處理。這裏假設每個渠道的application label都不一樣。
這裏引用一個變量${APP_NAME},我們需要在build.gradle中根據不同的渠道進行配置
這裏主要是兩個配置項,都在android配置項裏
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
上面配置了release和debug兩個版本
productFlavors{
//百度推廣渠道
baidu {
applicationId "com.android.baidu"
versionCode 1
versionName "1.0"
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
manifestPlaceholders = [ APP_NAME : "app-百度"]
}
//360推廣渠道
qh360 {
applicationId "ccom.android.three"
versionCode 1
versionName "1.0"
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"]
manifestPlaceholders = [ APP_NAME : "app-360"]
}
//豌豆莢推廣渠道
wandoujia {
applicationId "com.android.douban"
versionCode 1
versionName "1.0"
manifestPlaceholders = [ APP_NAME : "app-豌豆莢"]
}
}
上面配置了三個渠道,三個渠道主要修改了包名跟配置了APP_NAME.這樣配置渠道包的工作就差不多好了,這裏會生成(release+debug) * (baidu + 360 + wandoujia) = 6個Apk包。
此外還要做一個額外的工作,就是輸出的時候 修改apk文件名,否則你只能看到一個Apk包了
這個工作只需要配置andorid下的一個配置項即可
applicationVariants.all{variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def buildType = variant.buildType.name
//這裏修改apk文件名,格式爲 app_渠道名-版本名-當前時間-編譯版本.apk
def fileName = "app_${variant.productFlavors[0].name}-V${defaultConfig.versionName}-${getCurrentTime()}-${buildType}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
我們注意到這邊還需要一個getCurrentTime()的函數,在與android同級的目錄下定義一個好了
//獲取當前時間
def getCurrentTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
最後在項目的根目錄下運行gradle build,注意輸出目錄
簽名
簽名這塊也很簡單,Build -> Generate Signed APK 裏可以創建一個key
創建後,我們在build.gradle的android配置項裏做如下配置
signingConfigs{
myconfig {
keyAlias 'huang'
keyPassword '123456'
storeFile file('/home/huangshunbo/demo.jks')
storePassword 'huangshunbo'
}
}
最後在想要使用該簽名的buildTypes裏做下引用即可
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.myconfig
}
}
就這樣,簽名搞定。下面備註點小知識
查看三方應用或是系統應用簽名:解壓apk -> 進入META-INF得到CERT.RSA文件,通過
keytool -printcert -file META-INF/CERT.RSA
查看簽名信息
查看簽名文件demo.jks信息
keytool -v -list -keystore demo.jks
混淆
首先在buildTypes配置需要混淆並指定混淆規則文件
buildTypes {
debug {
minifyEnabled true //是否要混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//混淆的規則
}
}
Proguard的4個特性:壓縮、優化、混淆、預檢測
proguard-android.txt是Proguard默認的混淆配置文件
proguard-rules.pro在module根目錄下,可替代proguard-android.txt作爲補充。
一般的,我們在proguard-rules.pro文件裏做相關的混淆配置
常用的一些配置:
-keep開頭的表示保持不變,不去混淆
-keep {Modifier} {class_specification} #保護指定的類文件和類的成員
-keepclassmembers {modifier} {class_specification} #保護指定類的成員,如果此類受到保護他們會保護的更好
-keepclasseswithmembers {class_specification} #保護指定的類和類的成員,但條件是所有指定的類和類成員是要存在。
-keepnames {class_specification} #保護指定的類和類的成員的名稱(如果他們不會壓縮步驟中刪除)
-keepclassmembernames {class_specification} #保護指定的類的成員的名稱(如果他們不會壓縮步驟中刪除)
-keepclasseswithmembernames {class_specification} #保護指定的類和類的成員的名稱,如果所有指定的類成員出席(在壓縮步驟之後)
eg:
-keep public class * extends android.app.Activity #保持Activity的子類不被混淆
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
-keep class **.R$* {*;} # 保留R下面的資源
# 代碼混淆壓縮比,在0~7之間,默認爲5,一般不做修改
-optimizationpasses 5
# 混合時不使用大小寫混合,混合後的類名爲小寫
-dontusemixedcaseclassnames
# 指定不去忽略非公共庫的類
-dontskipnonpubliclibraryclasses
#不做預校驗
-dontpreverify
# 混淆時所採用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#忽略警告
-ignorewarning
#混淆過程打印日誌的級別
-verbose
#不使用優化方案
-dontoptimize
#混淆時不做預校驗
-dontpreverify
#如果項目中使用到註解,需要保留註解屬性
-keepattributes *Annotation*
#保持native方法不作混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持Views中的setter和getter方法不混淆,保證屬性動畫能夠正常執行
-keepclassmembers public class * extends android.view.View{
void set*(***);
*** get*();
}
#保持Activity中參數是View類型的函數,保證在XML文件中配置的onClick屬性的值能夠正常調用到
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}
#保持枚舉類型中的函數
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#不混淆泛型
-keepattributs Signature
#保留代碼行號,這在混淆後代碼運行中拋出異常信息時,有利於定位出問題的代碼
-keepattributes SourceFile,LineNumberTable
#保留R類
-keep class **.R$*{
*;
}
Proguard運行後生成的四個文件(build/outputs/mapping/release目錄下)
- dump.txt:列出生成的APK文件中所有class文件的內部結構
- mapping.txt:列出混淆錢的Java源碼和混淆後的類、方法、屬性名之間的映射關係
- seeds.txt:列出未混淆的類和成員
- usage.txt:列出從APK文件中剝離的代碼
Maven Central 和 JCenter
目前存在兩個標準的Java & Android Maven倉庫:Maven Central 和 JCenter。目前JCenter相對有優勢而且Maven Central可以說是JCenter的一個子集。上傳函數庫到JCenter只需要到Bintray網站上進行操作即可
倉庫的匹配模式
compile 'de.greenrobot:eventbus:2.4.0'
GROUP_ID組織/公司/個人名:ARTIFACT_ID函數庫名:VERSION版本號
雜
.arr 的導入
# 生成arr
android{
repositories {
flatDir {
dirs 'aars'
}
}
}
# 使用aar
dependencies {
compile(name:'libraryname', ext:'aar')
}
dependencies
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') //編譯lib 目錄下的 jar 文件
compile project(':Easylink') //編譯附加的項目
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.jakewharton:butterknife:8.4.0' //編譯第三方開源庫
}