Gradle for Android 問題總結(jié)

Gradle是什么球凰?

Gradle 是以Groovy為基礎(chǔ)狮腿,面向java應(yīng)用,基于DSL語法的自動化構(gòu)建工具呕诉。是google引入缘厢,替換ant和maven的新工具,其依賴兼容maven和ivy甩挫。

使用gradle的目的:
更容易重用資源和代碼;
可以更容易創(chuàng)建不同的版本的程序贴硫,多個類型的apk包;
更容易配置伊者,擴展;
更好的IDE集成英遭;

首先明確gradle跟maven一樣,也有一個配置文件亦渗,maven里面是叫pom.xml挖诸,而在gradle中是叫build.gradle。Android Studio中的android項目通常至少包含兩個build.gradle文件法精,一個是project范圍的多律,另一個是module范圍的,由于一個project可以有多個module搂蜓,所以每個module下都會對應(yīng)一個build.gradle狼荞。這么說有點抽象,看下面這個圖:


1. Project中build.gradle

project下的build.gradle是基于整個project的配置帮碰,主要配置gradle 版本及 全局依賴倉庫相味、庫或者其他全部參數(shù)。
android studio 現(xiàn)在重要倉庫采用jcenter(),之前版本放在mavenCentral收毫。
另外有時還沒有加入jcenter()倉庫的第三方庫攻走,也需要在這里配置他們的庫地址殷勘。
需要在這里配置,才能將第三方庫拉下來

buildscript {
   //構(gòu)建過程依賴的倉庫
  repositories {
      jcenter()
  }
  
  //構(gòu)建過程需要依賴的庫
  dependencies {
      //聲明的是gradle插件的版本
      classpath 'com.android.tools.build:gradle:2.0.0'

      // NOTE: Do not place your application dependencies here; they belong
      // in the individual module build.gradle files
  }
}

allprojects {
  //這里面配置整個項目依賴的倉庫,這樣每個module就不用配置倉庫了
  repositories {
      jcenter()

      maven {
          // LeanCloud 的包倉庫
          url "http://mvn.leancloud.cn/nexus/content/repositories/releases"
      }
  }
}

//配置全局變量
ext {
  // module依賴庫公共版本號
  SupportXVersion = '23.2.0'
  GsonVersion = '2.6.2'
  LeanCloudVersion = 'v3.13.4'
  JunitVersion = '4.12'
  
  compileSdkVersion = 22
  buildToolsVersion = "23.0.1"
  minSdkVersion = 10
  targetSdkVersion = 22
  versionCode = 34
  versionName = "v2.6.1"
}

注:大家可能很奇怪昔搂,為什么倉庫repositories需要聲明兩次玲销,這其實是由于它們作用不同,buildscript中的倉庫是gradle腳本自身需要的資源摘符,而allprojects下的倉庫是項目所有模塊需要的資源

2. module中build.gradle

//申明使用插件贤斜,表明要編譯的內(nèi)容和產(chǎn)物,
//com.android.application 表明該module 為android 應(yīng)用
//com.android.library 表明為library庫
//java 表名是java庫
apply plugin: 'com.android.application'

//安卓構(gòu)建過程需要配置的參數(shù)
android {
    //編譯SDK的版本
    compileSdkVersion COMPILE_SDK_VERSION as int
    //buildtool 的版本
    buildToolsVersion BUILD_TOOLS_VERSION
    
    /默認配置逛裤,會同時應(yīng)用到debug和release版本上
    defaultConfig {
        //應(yīng)用包名
        applicationId APPLICATION_ID
        //支持最小android sdk 版本
        minSdkVersion MIN_SDK_VERSION as int
        // 目標版本
        targetSdkVersion TARGET_SDK_VERSION as int
        //應(yīng)用版本號
        versionCode VERSION_CODE as int
        //應(yīng)用版本名稱
        versionName VERSION_NAME
        
        /// 配置生成的 BuildConfig 文件中的常量瘩绒,代碼引用直接 
        buildConfigField "String", "LOG_TAG", LOG_TAG // 日志tag
        buildConfigField "String", "LOG_HTTP_TAG", LOG_TAG_HTTP // http日志tag
        buildConfigField "String", "LOG_WEB_TAG", LOG_TAG_WEB // web日志tag

      // 默認是UMENG_CHANNEL_VALUE為umeng
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
        
      // dex突破65535的限制
        multiDexEnabled true
    }
    
    //java版本號
    compileOptions{
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    
    //簽名
    signingConfigs {
        release {
            //簽名文件
            storeFile file(STORE_FILE)
            storePassword STORE_PASSWORD
            keyAlias KEY_ALIAS
            keyPassword KEY_PASSWORD
        }
    }
    // 為了解決部分第三方庫重復(fù)打包了META-INF的問題
    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
    
    //移除lint檢測的error
    lintOptions {
        abortOnError false
    }
    
    //編譯類型
    //其中debug, release是gradle默認自帶的兩個build type, 當(dāng)然你可以定義其他類型带族。
    //可以針對不停編譯的版本中配置不同的參數(shù)锁荔,比如混淆、簽名等蝙砌。preview
    buildTypes {
        debug {
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
        }
        
         preview {
            debuggable false // 是否保留調(diào)試信息
            minifyEnabled true  //是否混淆
            zipAlignEnabled true // 包優(yōu)化
            shrinkResources true // 移除不必要的資源

            // 簽名
            signingConfig signingConfigs.release
            // 代碼混淆規(guī)則文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        
        release {
            //加上后綴
            applicationIdSuffix ".release"
            minifyEnabled true //是否混淆
            zipAlignEnabled true // zip對齊優(yōu)化
            shrinkResources true // 移除不必要的資源
            
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"

            // 簽名
            signingConfig signingConfigs.release
            //混淆文件的位置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    // 多渠道
    productFlavors {
        //可以設(shè)置不同渠道渠道號阳堕,應(yīng)用名稱
        dev { // 開發(fā)
            buildConfigField "String", "CHANNEL_NUMBER", '"11111"'
        }
        '360' {
            buildConfigField "String", "CHANNEL_NUMBER", '"11112"'
        }
        GooglePlay {
            buildConfigField "String", "CHANNEL_NUMBER", "11113"'

    }
    // 多渠道批量替換
    productFlavors.all { flavor ->
         //批量修改Manifest占位符替換
        //在Manifest使用`${UMENG_CHANNEL_VALUE}`,`LEANCLOUD_CHANNEL_VALUE`,打包時將替換成渠道名,例如UMENG_CHANNEL_VALUE="dev";
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name, LEANCLOUD_CHANNEL_VALUE: name]
        // Project Properties->_myAPPBuildVersionName择克,用于程序集成下命令行修改
        if (project.hasProperty('_myAPPBuildVersionName')) {
            defaultConfig.versionName = _myAPPBuildVersionName
        }
    }
     
     //定義變量
     //gradle 可以用def定義一些值例如:def KeyPassword = "123123" 
     def releaseTime() {
         return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
     }

    
    // 批量打包
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName
                if (variant.buildType.name.equals('release')) {
                    // myAPP_v版本號_渠道名.apk
                    fileName = "myAPP_v${variant.versionName}_${variant.productFlavors[0].name}.apk"
                } else {
                    // myAPP_v版本號_渠道名_時間_編譯類型名.apk
                    fileName = "myAPP_v${variant.versionName}_${variant.productFlavors[0].name}_${releaseTime()}_${variant.buildType.name}.apk"
                }
                output.outputFile = new File(outputFile.parent + "/${variant.buildType.name}", fileName)
            }
        }
    }


}

//依賴第三方庫
dependencies {
   //編譯libs目錄下所以jar包
   //compile files('libs/xxx.jar')   導(dǎo)入一個特定jar包
    compile fileTree(dir: 'libs', include: ['*.jar'])//導(dǎo)入所有的jar包
    compile project(':core')
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.android.support:recyclerview-v7:23.1.1'
    compile 'com.android.support:cardview-v7:23.1.1'
}

注意:

  • buildToolsVersion這個需要你本地安裝該版本才行恬总,很多人導(dǎo)入新的第三方庫,失敗的原因之一是build version的版本不對肚邢,這個可以手動更改成你本地已有的版本或者打開 SDK Manager 去下載對應(yīng)版本壹堰。
  • proguardFiles這部分有兩段,前一部分代表系統(tǒng)默認的android程序的混淆文件骡湖,該文件已經(jīng)包含了基本的混淆聲明贱纠,免去了我們很多事,這個文件的目錄在 /tools/proguard/proguard-android.txt , 后一部分是我們項目里的自定義的混淆文件勺鸦,目錄就在 app/proguard-rules.pro ,在這個文件里你可以聲明一些第三方依賴的一些混淆規(guī)則并巍,最終混淆的結(jié)果是這兩部分文件共同作用的。
  • 一般重要的信息,例如簽名信息捉兴,可以直接將信息寫到gradle.properties翩活,然后在然后在build.gradle中引用即可。
  • 多渠道的關(guān)鍵在于定義不同的product flavor蠕趁。
    注意:這里的flavor名如果是數(shù)字開頭,必須用引號引起來。
  • buildTypes是指建構(gòu)的類型懈息,一般只用兩種默認類型 debug 和 release ,顧名思義 debug 用來配置開發(fā)過程中的一些內(nèi)容摹恰;release 用來配置正式發(fā)布版本的內(nèi)容辫继。有時我們需要發(fā)布介于debug與release之間的preview 版本怒见。

3. Project中setting.gradle

這個文件是全局的項目配置文件,里面主要聲明Project中所包括的所有module姑宽,

//一個Project中所包括的所有module
include ':app', ':model',':lib', ':core'

4. Project中g(shù)radle.properties

gradle.properties為gradle的配置文件遣耍,里面可以定義一些常量供build.gradle使用,比如可以配置簽名相關(guān)信息如keystore位置炮车,密碼舵变,keyalias等,build.gradle就可以直接引用
gradle 中的一些配置參數(shù)建議寫到gradle.properties

//編譯版本信息
APPLICATION_ID = com.jin.myAPP
COMPILE_SDK_VERSION = 23
BUILD_TOOLS_VERSION = 23.0.1
MIN_SDK_VERSION = 15
TARGET_SDK_VERSION = 1
VERSION_CODE = 1
VERSION_NAME = 1.0.0.0

//keystore信息
STORE_FILE = ../app/mykey.keystore
STORE_PASSWORD = your password
KEY_ALIAS = your alias
KEY_PASSWORD = your password

5. ext配置全局參數(shù)

project的build.gradle中的ext可以為各位module進行全局配置參數(shù),防止各個module之間的不統(tǒng)一瘦穆,不可控纪隙。而且當(dāng)我們升級sdk、build tool扛或、target sdk等绵咱,幾個module都要更改,非常的麻煩熙兔。

ext {
   compileSdkVersion = 22
   buildToolsVersion = "23.0.1"
   minSdkVersion = 10
   targetSdkVersion = 22
   versionCode = 34
   versionName = "v2.6.1"
}

然后在各自module的build.gradle中引用:

android {

  compileSdkVersion rootProject.ext.compileSdkVersion

  buildToolsVersion rootProject.ext.buildToolsVersion

 defaultConfig {

    applicationId "com.xxx.xxx"

    minSdkVersion rootProject.ext.minSdkVersion

    targetSdkVersion rootProject.ext.targetSdkVersion

    versionCode rootProject.ext.versionCode

    versionName rootProject.ext.versionName
  }
}

6. resValue 定義資源麸拄。

例如resValue "string" 就是字符串資源,可以用R.String 來引用對應(yīng)的字符串資源

android {
   defaultConfig {
       resValue "string", "build_time", buildTime()
       resValue "string", "build_host", hostName()
       resValue "string", "build_revision", revision()
    }
}

def buildTime() {
   return new Date().format("yyyy-MM-dd HH:mm:ss")
}

def hostName() {
   return System.getProperty("user.name") + "@" +InetAddress.localHost.hostName
 }

def revision() {
  def code = new ByteArrayOutputStream()
     exec {
        commandLine 'git', 'rev-parse', '--short', 'HEAD'
        standardOutput = code
      }
  return code.toString()
  }

上述代碼實現(xiàn)了動態(tài)的添加了3個字符串資源: build_time黔姜、build_host拢切、build_revision, 然后在其他地方可像如引用字符串一樣使用如下:

// 在Activity里調(diào)用
getString(R.string.build_time) // 輸出2015-11-07 17:01
getString(R.string.build_host) // 輸出jay@deepin,這是我的電腦的用戶名和PC名
getString(R.string.build_revision) // 輸出3dd5823, 這是最后一次commit的sha值

7. PlaceHolder

manifest的一些值我們可以用PlaceHolder處理秆吵。例如

<meta-data
    android:name="UMENG_CHANNEL"
    android:value="${UMENG_CHANNEL_VALUE}" />

在gradle中改成

 manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360"]

可以放在defaultConfig中設(shè)置默認值淮椰,或者放在productFlavors中根據(jù)不同渠道修改成不同值∧杉牛或者批量修改

  productFlavors.all { 
        flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] 
    }

8. 導(dǎo)入某個project

如果你的app是多模塊的主穗,假設(shè)有兩個模塊app和lib,并且app模塊是依賴lib的,這時候我們就需要在app模塊的build.gradle中的dependencies結(jié)點下配置依賴:

compile project(':lib')

并且你需要在settings.gradle中把lib模塊包含進來:

include ':lib',':app'

此外毙芜,這種情況下lib模塊是作為庫存在的忽媒,因而它的build.gradle中的插件聲明通常應(yīng)該是這樣的:

apply plugin: 'com.android.library'

而且,作為library的模塊lib的build.gradle文件的defaultConfig中是不允許聲明applicationId的腋粥,這點需要注意晦雨。

9. 引用本地aar:

  • 首先將你的庫通過android studio 運行打包成aar文件。運行后在/build/output/aar文件夾中隘冲。
  • 首先將aar文件放到模塊的libs目錄下闹瞧,然后在該模塊的build.gradle中聲明flat倉庫:
repositories{
     flatDir {
        dirs 'libs'
    }
}
  • 最后在dependencies結(jié)點下依賴該aar模塊:
dependencies{
    compile (name:'xxx',ext:'aar')
}

10. BuildConfig

在build.gradle中配置buildConfigField參數(shù),編譯后會在..\app\build\generated\source\buildConfig文件夾下會自動生成對應(yīng)版本對應(yīng)module的BuildConfig.java展辞。BuildConfig就會包含對應(yīng)版本的配置信息奥邮。程序中可以直接引用這些數(shù)據(jù)。例如BuildConfig.DEBUG。

public final class BuildConfig {
 public static final boolean DEBUG = Boolean.parseBoolean("true");
 public static final String BUILD_TYPE = "debug";
 public static final String FLAVOR = "360";
 public static final int VERSION_CODE = 45;
 public static final String VERSION_NAME = "3.2.0.0";
 // Fields from build type: debug
 public static final String HOST_IMG_SERVER = "img";
 public static final String HOST_SERVER = "test";
 // Fields from product flavor: 360
 public static final String CHANNEL_NUMBER = "232100";
}

11. module 調(diào)整目錄結(jié)構(gòu)sourceSets

默認情況下洽腺,java文件和resource文件分別在src/main/java和src/main/res目錄下脚粟,在build.gradle文件,andorid{}里面添加下面的代碼蘸朋,便可以將java文件和resource文件放到src/java和src/resources目錄下珊楼。

sourceSets {
   main {
      java {
          srcDir 'src/java'
      }
      resources {
        srcDir 'src/resources'
     }
   }
}

更簡便的寫法是:

sourceSets {
   min.java.srcDirs = ['src/java']
   min.resources.srcDirs = ['src/resources']
}

12. Gradle常用命令

上面大家接觸了一些命令如 ./gradlew -v ./gradlew clean ./gradlew build, 這里注意是./gradlew, ./代表當(dāng)前目錄,gradlew代表 gradle wrapper度液,意思是gradle的一層包裝厕宗,大家可以理解為在這個項目本地就封裝了gradle,即gradle wrapper堕担, myAPP/gradle/wrapper/gralde-wrapper.properties**文件中聲明了它指向的目錄和版本已慢。只要下載成功即可用grdlew wrapper的命令代替全局的gradle命令。

理解了gradle wrapper的概念霹购,下面一些常用命令也就容易理解了佑惠。

  • ./gradlew 下載更新gradle
  • ./gradlew -v 版本號
  • ./gradlew assemble 構(gòu)建項目輸出
  • ./gradlew check 運行檢測和測試任務(wù)
  • ./gradlew clean 清除9GAG/app目錄下的build文件夾
  • ./gradlew build 運行check和assemble,檢查依賴并編譯打包
    這里注意的是 ./gradlew build 命令把debug、release環(huán)境的包都打出來齐疙,如果正式發(fā)布只需要打Release的包膜楷,該怎么辦呢,下面介紹一個很有用的命令 assemble<build type="" name="">, 如</build>
  • ./gradlew assembleDebug 編譯并打Debug包
  • ./gradlew assembleRelease 編譯并打Release的包所有渠道的
  • ./gradlew assembleWandoujiaRelease 編譯并打包豌豆莢的Release版本
  • ./gradlew assembleWandoujia 編譯并打包豌豆莢的所有版本
  • ./gradlew installRelease Release模式打包并安裝
  • ./gradlew uninstallRelease 卸載Release模式包
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贞奋,一起剝皮案震驚了整個濱河市赌厅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轿塔,老刑警劉巖特愿,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勾缭,居然都是意外死亡揍障,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門俩由,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毒嫡,“玉大人,你說我怎么就攤上這事幻梯《祷” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵礼旅,是天一觀的道長膳叨。 經(jīng)常有香客問我洽洁,道長痘系,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任饿自,我火速辦了婚禮汰翠,結(jié)果婚禮上龄坪,老公的妹妹穿的比我還像新娘。我一直安慰自己复唤,他們只是感情好健田,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佛纫,像睡著了一般妓局。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呈宇,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天好爬,我揣著相機與錄音,去河邊找鬼甥啄。 笑死存炮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜈漓。 我是一名探鬼主播穆桂,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼融虽!你這毒婦竟也來了享完?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤有额,失蹤者是張志新(化名)和其女友劉穎驼侠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谆吴,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡倒源,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了句狼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笋熬。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖腻菇,靈堂內(nèi)的尸體忽然破棺而出胳螟,到底是詐尸還是另有隱情,我是刑警寧澤筹吐,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布糖耸,位于F島的核電站,受9級特大地震影響丘薛,放射性物質(zhì)發(fā)生泄漏嘉竟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舍扰。 院中可真熱鬧倦蚪,春花似錦、人聲如沸边苹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽个束。三九已至慕购,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茬底,已是汗流浹背脓钾。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留桩警,地道東北人可训。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像捶枢,于是被迫代替她去往敵國和親握截。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理烂叔,服務(wù)發(fā)現(xiàn)谨胞,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 轉(zhuǎn)至:http://blog.csdn.net/heqiangflytosky/article/details/5...
    kkgo閱讀 2,880評論 0 1
  • 本文原作者為:kale2010 .blog地址:http://www.cnblogs.com/tianzhijie...
    NoValue閱讀 3,556評論 0 11
  • 轉(zhuǎn)載注明出處:http://www.reibang.com/p/5255b100930e 0. 前言 完全由個人翻...
    王三的貓阿德閱讀 2,520評論 0 4
  • 上周末看了電視節(jié)目[歡樂喜劇人] 蒜鸡。賈玲演了個節(jié)目:先是老板把她炒了胯努,接著回家尋求老公安慰,發(fā)現(xiàn)老公有外遇;傷心欲...
    stillwalking閱讀 323評論 1 1