Android Studio下項目構建的Gradle配置及打包應用變體

Gradle簡介

  Gradle是一個自動化構建工具,採用Groovy的Domain Specific Language(領域特定語言)來描述和控制構建邏輯。具有語法簡潔、可讀性強、配置靈活等特點。基於Intellij IDEA社區版本開發的Android Studio天生支持Gradle構建程序。Groovy是一種基於JVM的敏捷開發語言,結合了Phthon、Ruby和Smalltalk的許多強大特性。同時,Groovy代碼既能夠與java代碼很好地結合,也能夠用於擴展現有的代碼。
Gradle有如下特點:

  • Gradle支持多工程構建和局部構建
  • Gradle支持遠程或本地依賴管理:支持從遠程maven倉庫(項目構建工具、軟件項目管理綜合工具)、nexus私服(局域網內一種特殊的遠程倉庫)、ivy倉庫(管理項目依賴的工具)以及本地倉庫獲取依賴
  • Gradle與Ant、Maven兼容
  • Gradle可輕鬆遷移:Gradle適用於任何結構的工程,可以在同一個開發平臺平行構建原工程和Gradle工程
  • Gradle使用靈活:Gradle的整體設計是以作爲一種語言爲導向的,而非成爲一個嚴格死板的框架
  • Gradle免費開源
  • Gradle很好的與IDE集成
  • Gradle可以更容易地集成到自動化構建系統

Android Studio下項目構建的Gradle配置

  在Android Studio下創建一個Android項目,並切換到Project視圖下,可以看到下圖的項目結構。
這裏寫圖片描述
  紅框標記就是項目中Gradle相關的配置文件,下面我們從app模塊下的build.gradle開始對各個配置文件進行分析。

一、app Module下的build.gradle文件說明

  app這個Module下的gradle配置文件,算是整個項目最主要的gradle配置文件,主要配置應用程序屬性、配置應用程序簽名、配置應用程序特性(渠道)、配置應用程序構建類型和配置應用程序依賴,下圖是默認生成的文件內容:
這裏寫圖片描述

1. 應用插件apply plugin總共有三種類型值,分別如下:

apply plugin: 
‘com.android.application’//這表示此module是一個可運行的應用程序,可以直接run的
apply plugin: ‘com.android.library’//這表示此module是一個安卓依賴庫的工程,不可直接run
apply plugin: ‘java’//這表示此module是一個java項目,在此module中只能使用java的api

2. 關於android閉包,

  其默認有compileSdkVersion、buildToolsVersion、defaultConfig閉包和buildTypes閉包。
  compileSdkVersion和buildToolsVersion是兩個關於版本描述的參數

compileSdkVersion 25//指定編譯版本,開發採用的sdk版本
buildToolsVersion “25.0.2//編譯時採用的構建工具的版本

  defaultConfig閉包參數說明

applicationId “com.jointem.variantpackaging”//應用的id,這裏決定應用的唯一標識
minSdkVersion 17//決定此應用可運行的安卓系統最低版本
targetSdkVersion 25//決定此應用可運行的安卓系統最高版本
versionCode 1//應用版本號,更新需要,新包的值要大於老包的方可更新
versionName ‘1.0’//應用版本名,通常用於顯示
testInstrumentationRunner”andrid.support.test.runner.AndroidJUnitRunner”//Android單元測試test runner

  buildTypes閉包參數說明
  關於構建類型buildType,默認有release和debug兩種,默認只顯示release方式,一般是正式發佈的包。

minifyEnabled false//混淆開關
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’// 指定混淆文件及混淆文件規則配置文件的位置

3.關於模塊依賴dependencies

compile fileTree(include: [‘*.jar’], dir: ‘libs’)//編譯文件樹(編譯依賴libs目錄下所有jar)
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2’, { 
exclude group: ‘com.android.support’, module: ‘support-annotations’ 
})
compile ‘com.android.support:appcompat-v7:24.2.1’//是從repository(默認是jCenter())裏下載一個依賴包進行編譯並打包
compile ‘com.android.support.constraint:constraint-layout:1.0.0-beta5’
testCompile ‘junit:junit:4.12’// 僅僅是針對單元測試代碼的編譯編譯以及最終打包測試apk時有效,而對正常的debug或者release apk包不起作用
compile project(‘:andr-library’)//是將另一個module進行編譯並打包

  其實,app下的腳本對應的是項目的Project Structure對話框中的設置,從左到右依次是屬性、簽名、渠道特性、構建類型和依賴,快捷鍵Ctrl+Shift+Alt+S(Windows/Linux),如下。
這裏寫圖片描述

二、library Module下的build.gradle配置

  除了app Module,每一個Module也都有一個gradle配置文件,語法都一樣,區別在於開頭聲明的是apply plugin: ‘com.android.library’,表明該Module是以依賴模塊的形式存在。

三、全局配置文件

  所有的全局配置文件都會放置在項目的根目錄下,包括忽略文件、本地配置文件、gradlew的批處理文件以及項目gradle相關的配置文件。

1.gradle配置文件gradle-wrapper.properties,默認內容如下:

#Thu Mar 09 16:27:37 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

  此配置文件中主要聲明瞭gradle的目錄與下載路徑以及當前項目使用的gradle版本,這些默認的路徑我們一般不會更改的,這個文件裏指明的gradle版本不對也是很多導包不成功的原因之一。

2.關於project下build.gradle配置文件

  整個項目的gradle基礎配置文件,用來配置項目的構建任務,內容如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.// 項目構建文件,可以在各子項目/模塊添加常用的配置選項。
buildscript {
    //Android插件從這個倉庫下載
    repositories {
        jcenter()//依賴倉庫源的名稱,兼容maven的遠程中央倉庫
    }
    //項目依賴
    dependencies {
        //android gradle插件
        classpath 'com.android.tools.build:gradle:2.3.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    //此處配置Project中默認的倉庫源,包括每個module的依賴,無需每個module單獨配置
    repositories {
        jcenter()
    }
}
//打包前執行clean任務
//任務類型是Delete
//clean任務就是刪除項目根目錄下的build目錄中的文件
task clean(type: Delete) {
    delete rootProject.buildDir
}

3.關於Gradle配置文件gradle.properties

  gradle.properties是Gradle的配置文件,build.gradle通過讀取這個文件配置的參數來進行相應構建,可在此配置文件中配置一些全局參數(全局代理)。默認文件內容如下:

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# 配置守護進程的jvm參數
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

#配置完成後,Gradle將在並行模式下運行(並行編譯)
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
#http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

4.關於全局配置文件setting.gradle

  默認文件內容include ‘:app’。是項目的全局配置文件,主要聲明一些需要加入構建的模塊。在Android studio中通常都是默認自動在此文件中添加依賴的module。

Android Studio下的依賴方式

一、Project Structure

  按快捷鍵Ctrl+Shift+Alt+S(Windows/Linux),打開Project Structure彈窗。
這裏寫圖片描述
  在Dependencies下有個scope,這裏可以選擇依賴的方式,可選項有Compile、Provided、APK、Test compile、Debug compile和Release compile,下面分別對這些可選項進行簡單說明。

  • Compile:是對所有的build type以及favlors都會參與編譯並且打包到最終的apk文件中,是從repository(默認是jCenter())裏下載一個依賴包進行編譯並打包。
  • Provided:Provided是對所有的build type以及favlors只在編譯時使用,類似eclipse中的external-libs,只參與編譯,不打包到最終apk,是提供給那些只編譯不打包場景的命令。就是我在編譯的時候對某一個jar文件有依賴,但是最終打包apk文件時,我不想把這個jar文件放進去,可以用這個命令。
  • APK:只會打包到apk文件中,而不參與編譯,所以不能再代碼中直接調用jar中的類或方法,否則在編譯時會報錯。
  • Test compile:僅僅是針對單元測試代碼的編譯編譯以及最終打包測試apk時有效,而對正常的debug或者release apk包不起作用。
  • Debug compile:僅僅針對debug模式的編譯和最終的debug apk打包。
  • Release compile:僅僅針對Release 模式的編譯和最終的Release apk打包。

二、關於Compile的兩個子參數:

  • compile files:是從本地的libs目錄下尋找picasso-2.4.0.jar這個文件進行編譯並打包。類似的命令有compile fileTree(dir: 'libs', include: '*.jar'),即,將libs目錄下所有jar文件進行編譯並打包。
  • compile project:是將另一個module(等同eclipse中的library)進行編譯並打包。

打出多變體包

一、爲什麼要打包變體包?

  在開發過程中經常遇到多個環境切換的問題,比如,正在連接測試環境進行調試,此時又想看生產環境的數據顯示,通常的處理方式是卸掉測試環境的然後運行一個生產環境的包。我們都知道,build一個大項目,直到安裝到手機上,整個過程是很耗時的。如果同一臺手機上可以同時安裝同一個應用的多個不同環境的apk,那麼,當想看其它環境的數據時,就不需要重新卸載再安裝了(同理,同一應用,需要不同版本的安裝包[免費版/收費版]時,也可以這樣處理,而無需爲不同版本創建不同的分支)。

二、打包變體包的條件

  在創建完一個項目後,我們在app這個module下的build.gradle中的android節點下defaultConfig節點中,可以看到一個applicationId屬性,默認的 applicationId 和 AndroidManifest.xml 中的 package 屬性是相同的。applicationId 和 packageName 它們各自代表什麼?爲何會是相同的呢?其實,package 代表了 java 代碼中的包名,在應用中的資源,就是通過package標識的(比如R文件,包名.R);applicationId 則代表了應用中的唯一標識,和應用簽名一起用來區別於其他應用。
  在手機上,系統同樣是通過applicationId和簽名來標識一個app的。所以,我們只要在打包apk時,使得應用之間的applicationId和簽名各不相同,就能夠實現同一個應用的不同變體同時安裝在同一臺手機上了。同時,爲了更好的區分給個變體應用,我們還可以通過對佔位符的使用,使用gradle配置不同的資源文件、不同的應用名稱與圖標、不同的java文件等有區別的屬性,打出不同的變體包。

三、打出變體包的步驟

1.配置簽名、渠道(applicationId)

  選擇app module,選擇Signing選項卡,首先配置好了這兩個變體版本的簽名文件,文件名可任意取(見名知意)。
這裏寫圖片描述
  簽名屬性字段描述:

  • keyAlias//指定簽名文件的別名
  • keyPassword//指定簽名文件的別名配對密碼
  • storeFile//簽名文件路徑
  • storePassword//簽名文件的密碼

  切換到Flavors選項卡,配置變體包的相關屬性,由於下一步創建資源文件夾時,需要與這裏的文件名對應,所以此處的取名儘量簡約。這裏我創建兩個命名dev和rea的Flavor,所有的Flavor都會複寫defaultConfig中的屬性,所以可以看到我並沒有填寫其中的一些屬性。在這裏非常關鍵的一點,是對不同的變體設置不同的applicationId,並選擇對應的Signing Config。
這裏寫圖片描述

2.新建不同變體的sourceSet

  在修改完變體的配置文件後,我們還需要再項目的src文件夾下,新建以我們的Flavor名稱命名的文件夾,並在這些文件夾下新建如main中相同的目錄結構。
這裏寫圖片描述
  我們正常編寫項目都是寫在main這個sourceSet下的,但是如果我們的項目的變體有不同的資源文件、Java文件時,我們就需要使用不同的sourceSet來區別開。
  需要注意的是,Flavor下的資源文件會與main中的合併,如果存在重複,則Flavor中優先級高於main中。我們可以將不同變體中共用的資源存放在main中,只將不同的內容存放在flavor的sourceSet中。
  如果不同變體有內容不同的Java文件則要注意,需要將這個Java文件放置到每個flavor 的sourceSet文件夾下,main中不可以有這個Java文件,如果main中也存在此文件,編譯時會提示文件重複。比如說有兩個變體,有着不同的TargetActivity.java,那麼main中就不能有這個文件了,需要把這個Java文件放到各個flavor的sourceSet下,同時這個Java文件在sourceSet中要按照main中的包結構保存。

3.關於配置不同的launcher圖標和應用名

  通過之前的操作,已經可以有效區分變體包的applicationId、Signing Config和java文件,那麼應用logo和name又該如何處理呢,這裏有兩種方法。

1)配置不同的資源:我們可以使用類似於處理java文件的方法,在不同的sourceSet中配置string.xml中app_name屬性,在mipmap文件夾中放置對應的ic_app.png圖標資源。不過當我們需要更換啓動圖和應用名而變體包又比較多的情況下,這種方法會比較麻煩,因爲我們要到每一個sourceSet資源文件下去對應的修改,如果使用佔位符的方式,那麼會變得簡單一些。
2)使用佔位符的方式:在AndroidManifest文件中使用佔位符然後在flavor中直接配置,在flavor中使用的屬性是manifestPlaceholderss(manifestPlaceholders =[NAME1:VALUE1]),而圖標資源和應用名稱我們都可以直接放置到main中。
結果如下圖:
這裏寫圖片描述

四、Debug時選擇變體

1.選擇要調試的應用

  通過之前的操作,已經成功配置了多個變體,那麼問題來了,這麼多個變體,我們在debug的時候,我們怎麼選擇要debug的變體呢?這裏有兩種方式進行切換。

  • 選擇Build->Select Build Variant,在左下角會顯示出Build Variant視圖,點擊選擇要編譯的變體。
    這裏寫圖片描述
  • 另一種方式則是直接點擊左下角Build Variant選下卡,之後的操作同上。

2.需要注意的的地方

  • 在這裏可以看到有4個變體,這是爲什麼呢?我們明明只配置了兩個變體呀?在這需要提到Build Type配置,這個選項卡下默認有兩個類型,分別是debug和release,變體包的數量正是(build type數量)*(flavor數量)。
    這裏寫圖片描述
  • 當你選擇完要編譯的變體後,會發現未被選中的變體下會報找不到資源的錯誤,這是很正常的,當被選中之後就會變成正常的工程文件夾樣式了,其這種報錯也並不會影響我們進行批量打包。

五、常用gradlew命令

  首次運行命令行,沒有gradle的要下載的哦,下載需要的時間根據網絡狀況而定。

1.八個常用命令:

  • ./gradlew -v //查看gradle版本
  • ./gradlew assembleDebug //編譯並打出Debug版本的包
  • ./gradlew assembleRelease //編譯並打出Release版本的包
  • ./gradlew build //執行檢查並編譯打包,打出所有Release和Debug的包
  • ./gradlew clean //刪除build目錄,會把app下面的build目錄刪掉
  • ./gradlew installDebug //編譯打包並安裝Debug版本的包
  • ./gradlew uninstallDebug //卸載Debug版本的包
  • ./gradlew -info //使用-info查看任務詳情

2.命令行終端Terminal下執行打包命令

  我們直接利用./gradlew build打出所有的變體包,在Terminal終端下鍵入./gradlew build命令,需要等待大概20秒鐘左右,當看到終端打印出BUILD SUCCESSFUL,說明打包任務執行完成,打開指定的apk生成目錄(默認app/build/outputs/apk),就可以看到已經打出的apk。
這裏寫圖片描述
  將兩個release包都安裝到同一臺手機,可以發現能同時存在,並且都能正常打開運行。
這裏寫圖片描述

3.關於打包需要注意的坑

  如果項目中存在使用Library Module,並且Library Module中manifest下的application也存在與app Module下的application相同的屬性標籤,那麼會報manifest.xml合併錯誤的提示,如下。
這裏寫圖片描述

  • 原因:這是因爲AS的Gradle插件默認會啓用Manifest Merger Tool,若Library項目中也定義了與主項目相同的屬性(例如默認生成的android:icon和android:theme),則此時會合並失敗,並報上面的錯誤。
  • 處理辦法:在Manifest.xml的application標籤下添加tools:replace=”android:icon, android:theme”(多個屬性用,隔開,並且記住在manifest根標籤上加入xmlns:tools=”http://schemas.android.com/tools”,否則會找不到namespace哦)。

注:本篇博客純屬個人筆記,如果錯誤之處,還望幫忙指正,謝謝!

發佈了53 篇原創文章 · 獲贊 18 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章