搞懂 Android Studio 構建那些事

2022-01-30 鴻洋

本來是投稿文章,不會源碼分析類在手機端閱讀體驗實在捉急,感興趣還是建議大家導入源碼後,對著學習下。

Android進階——Small源碼分析之啟動流程詳解

http://blog.csdn.net/qq_30379689/article/details/79208290

Android進階——Small源碼分析之跳轉流程詳解

http://blog.csdn.net/qq_30379689/article/details/79221413

Android進階——Small源碼分析之更新流程詳解

http://blog.csdn.net/qq_30379689/article/details/79242653

作者:shangmingchao

連結:

http://blog.csdn.net/fu908323236/article/details/78356344

本文由作者投稿發布。

構建 APK 的過程是個相當複雜的過程,Android 構建系統需要將應用的資源文件和源文件一同打包到最終的 APK 文件中。應用可能會依賴一些外部庫,構建工具要靈活地管理這些依賴的下載、編譯、打包(包括合併、解決衝突、資源優化)等過程。

應用的源碼可能包括 Java 、RenderScript、AIDL 以及 Native 代碼,構建工具需要分別處理這些語言的編譯打包過程,而有些時候我們需要生成不同配置(如不同 CPU 架構、不同 SDK 版本、不同應用商店配置等)的 APK 文件,構建工具就需要根據不同情況編譯打包不同的 APK。

總之,構建工具需要完成從工程資源管理到最終編譯、測試、打包、發布的幾乎所有工作。而 Android Studio 選擇了使用 Gradle,一個高級、靈活、強大的自動構建工具構建 Android 應用,利用 Gradle 和 Android Gradle 插件可以非常靈活高效地構建和測試 Android 應用了: 

 

Gradle和其Android插件可以幫助你自定義以下幾方面的構建配置:

Build types(構建類型)定義了一些構建、打包應用時 Gradle 要用到的屬性,主要用於不同開發階段的配置,如 debug 構建類型要啟用 debug options 並用 debug key 籤名,release 構建類型要刪除無效資源、混淆源碼以及用 release key 籤名

Product flavors(產品風味)定義了你要發布給用戶的不同版本,比如免費版和付費版。你可以在共享重用通用版本功能的時候自定義 product flavors 使用不同的代碼和資源,Product flavors 是可選的所以你必須手動創建

build variant(構建變體)是 build type 和 product flavor 的交叉輸出(如free-debug、free-release、paid-debug、paid-release),Gradle 構建應用要用到這個配置。也就是說添加 build types 或 product flavors 會相應的添加 build variants

你可以在 build variant 配置中指定 manifest 文件中的某個屬性值(如應用名、最小 SDK 版本、target SDK 版本),這個值會覆蓋 manifest 文件中原來的屬性值

構建系統會管理工程用要用到的本地文件系統和遠程倉庫的依賴。

構建系統會讓你指定籤名設置以便在構建時自動給你的 APK 籤名,構建工具默認會使用自動生成的 debug key 給 debug 版本籤名,你也可以生成自己的 debug key 或 release key 使用。

構建系統讓你可以為每個構建變體指定不同的混淆規則文件

構建系統讓你可以為不同屏幕密度或 Application Binary Interface (ABI)的設備生成包含其所需要的資源的 APK 文件,如為 x86 CPU 架構的設備生成只包含該 x86 架構 so 庫的 APK 文件。

而這些構建配置要體現在不同的構建配置文件中,典型的Android應用結構為: 

位於工程根目錄的 settings.gradle 文件用於告訴Gradle構建應用時需要包含哪些 module,如 :

對於setting.gradle中也可以寫代碼的,可以參考:

https://kymjs.com/code/2018/02/25/01/

1.2 頂層 Build 文件

位於工程根目錄的 build.gradle 文件用於定義工程所有 module 的構建配置,一般頂層 build 文件使用 buildscript 代碼塊定義 Gradle 的 repositories 和 dependencies,如自動生成的頂層 build 文件:


buildscript {
   
   repositories {
       google()
       jcenter()
   }
   
   dependencies {
       classpath 'com.android.tools.build:gradle:3.0.1'
   }
}

allprojects {
  repositories {
      google()
      jcenter()
  }
}

除了這些,你還可以使用 ext 代碼塊在這個頂層 build 文件中定義工程級(工程中所有 modules 共享)的屬性:

buildscript {...}
allprojects {...}
ext {
   
   compileSdkVersion = 26
   supportLibVersion = "27.0.2"
   ...
}
...

每個 module 的 build 文件使用 rootProject.ext.property_name 語法使用這些屬性即可:

android {
 compileSdkVersion rootProject.ext.compileSdkVersion
 ...
}
...
dependencies {
   compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
   ...
}

位於每個 project/module/ 目錄的 build.gradle 文件用於定義該 module 自己的構建配置,同時你也可以重寫頂層 build 文件或 main app manifest 的配置:


apply plugin: 'com.android.application'

android {
 
 compileSdkVersion 26
 
 buildToolsVersion "27.0.3"
 
 defaultConfig {
   
   applicationId 'com.example.myapp'
   
   minSdkVersion 15
   
   targetSdkVersion 26
   
   versionCode 1
   
   versionName "1.0"
 }
 
 buildTypes {
   release {
       minifyEnabled true
       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
   }
 }
 
 flavorDimensions "tier", "minApi"
 productFlavors {
      free {
       
       
       dimension "tier"
       ...
     }
     paid {
       dimension "tier"
       ...
     }
     minApi23 {
         dimension "minApi"
         ...
     }
     minApi18 {
         dimension "minApi"
         ...
     }
 }
 
 splits {
   density {
     
     enable false
     
     exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
   }
 }
}

dependencies {
   implementation project(":lib")
   implementation fileTree(dir: 'libs', include: ['*.jar'])
   implementation 'com.android.support:appcompat-v7:27.0.2'
}


1.4 Gradle 屬性文件

位於工程根目錄的 gradle.properties 文件和 local.properties 用來指定 Gradle 構建工具自己的設置。 


gradle.properties 文件可以用來配置工程的 Gradle 設置,如 Gradle 守護進程的最大堆棧大小 


local.properties 文件用來配置構建系統的本地環境屬性,如 SDK 安裝路徑,由於該文件內容是 Android Studio 自動生成的且與本地開發環境有關,所以你不要更改更不要上傳到版本控制系統中。

Gradle 是專注於靈活性和性能的開源自動構建工具。Gradle 的構建腳本使用 Groovy 或 Kotlin 語言。Gradle 構建工具的優勢在於:

高度可定製 - Gradle 是以最基本的可定製和可擴展的方式模塊化的

更快 - Gradle 通過重用之前執行的輸出、只處理更改的輸入以及並行執行 task 的方式加快構建速度

更強大 - Gradle 支持跨多語言和平臺,是 Android 官方構建工具,支持很多主流 IDE,包括 Android Studio、Eclipse、IntelliJ IDEA、Visual Studio 2017 以及 XCode,將來會支持更多語言和平臺

學習 Gradle 的途徑有很多:

每個月都有由 Gradle 核心工程師主持的 免費在線培訓,你需要提前註冊預約

https://gradle.org/training

Gradle 的 guides 和 reference documentation 也是很好的閱讀材料

https://gradle.org/guides 

https://docs.gradle.org/current/userguide/userguide.html

通過 Gradle Newsletter 閱讀Gradle最新期刊

https://newsletter.gradle.com/

通過 Gradle Forum 論壇獲取幫助,其他成員或核心開發者會回答你的問題

https://discuss.gradle.org/

還可以通過 Command-line completion 學習 bash 和 zsh 命令行

https://git.io/gradle-completion


2.1 Gradle 的依賴管理

依賴管理(Dependency management)是每個構建系統的關鍵特徵,Gradle 提供了一個既容易理解又其他依賴方法兼容的一流依賴管理系統,如果你熟悉 Maven 或 Ivy 用法,那麼你肯定樂於學習 Gradle,因為 Gradle 的依賴管理和兩者差不多但比兩者更加靈活。

Gradle 依賴管理的優勢包括:

傳遞依賴管理 - Gradle 讓你可以完全控制工程的依賴樹

支持非託管依賴 - 如果你只依賴版本控制系統或共享磁碟中的單個文件,Gradle 提供了強大的功能支持這種依賴

支持個性化依賴定義 - Gradle 的 Module Dependencies 讓你可以在構建腳本中描述依賴層級

為依賴解析提供完全可定製的方法 - Gradle 讓你可以自定義依賴解析規則以便讓依賴可以方便地替換

完全兼容Maven和Ivy - 如果你已經定義了 Maven POM 或 Ivy 文件,Gradle 可以通過相應的構建工具無縫集成

可以與已存在的依賴管理系統集成 - Gradle 完全兼容 Maven 和 Ivy 倉庫,所以如果你使用 Archiva、Nexus 或 Artifactory,Gradle 可以100%兼容所有的倉庫格式


2.2 常用的依賴配置

Java Library插件 繼承自 Java插件,但 Java Library 插件與 Java 插件最主要的不同是 Java Library 插件引入了將 API 暴露給消費者(使用者)的概念,一個 library 就是一個用來供其他組件(component)消費的 Java 組件。 


Java Library 插件暴露了兩個用於聲明依賴的 Configuration(依賴配置): api 和 implementation。出現在 api 依賴配置中的依賴將會傳遞性地暴露給該 library 的消費者,並會出現在其消費者的編譯 classpath 中。而出現在 implementation 依賴配置中的依賴將不會暴露給消費者,也就不會洩漏到消費者的編譯 classpath 中。因此,api 依賴配置應該用來聲明library API 使用的依賴,而 implementation 依賴配置應該用來聲明組件內部的依賴。implementation 依賴配置有幾個明顯的優勢:

依賴不會洩漏到消費者的編譯 classpath 中,所以你也就不會無意中依賴一個傳遞依賴了

由於 classpath 大小的減少編譯也會更快

當 implementation 的依賴改變時,消費者不需要重新編譯,要重新編譯的很少

更清潔地發布,當結合新的 maven-publish 插件使用時,Java librariy 會生成一個 POM 文件來精確地區分編譯這個 librariy 需要的東西和運行這個 librariy 需要的東西

那到底什麼時候使用 API 依賴什麼時候使用 Implementation 依賴呢?

這裡有幾個簡單的規則: 


一個 API 是 library binary 接口暴露的類型,通常被稱為 ABI (Application Binary Interface),這包括但不限於:

相反,下面列表重要到的所有類型都與 ABI 無關,因此應該使用 implementation 依賴:

只用在方法體內的類型

只出現在 private 成員的類型

只出現在內部類中的類型

例如



import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class HttpClientWrapper {
   private final HttpClient client;
   
   
   public HttpClientWrapper(HttpClient client) {
       this.client = client;
   }
   
   public byte[] doRawGet(String url) {
       GetMethod method = new GetMethod(url);
       try {
           int statusCode = doGet(method);
           return method.getResponseBody();
       } catch (Exception e) {
           ExceptionUtils.rethrow(e);
       } finally {
           method.releaseConnection();
       }
       return null;
   }
   
   private int doGet(GetMethod method) throws Exception {
       int statusCode = client.executeMethod(method);
       if (statusCode != HttpStatus.SC_OK) {
           System.err.println("Method failed: " + method.getStatusLine());
       }
       return statusCode;
   }
}

其中,public 構造器 HttpClientWrapper 使用了 HttpClient 參數暴露給了使用者,所以屬於 API 依賴。而 ExceptionUtils 只在方法體中出現了,所以屬於 implementation 依賴。

所以 build 文件這樣寫:

dependencies {
   api 'commons-httpclient:commons-httpclient:3.1'
   implementation 'org.apache.commons:commons-lang3:3.5'
}

因此,應該優先選擇使用 implementation 依賴:缺少一些類型將會直接導致消費者的編譯錯誤,可以通過移除這些類型或改成 API 依賴解決。 

compileOnly 依賴配置會告訴 Gradle 將依賴只添加到編譯 classpath 中(不會添加到構建輸出中),在你創建一個 Android library module 且在編譯時需要這個依賴時使用 compileOnly 是個很好的選擇。但這並不能保證運行時良好,也就是說,如果你使用這個配置,那麼你的 library module 必須包含一個運行時條件去檢查依賴是否可用,在不可用的時候仍然可以優雅地改變他的行為來正常工作,這有助於減少最終 APK 的大小(通過不添加不重要的transient依賴)。 

runtimeOnly 依賴配置告訴 Gradle 將依賴只添加到構建輸出中,只在運行時使用,也就是說這個依賴不添加到編譯 classpath 中。 


此外,debugImplementation 會使依賴僅在 module 的 debug 變體中可用,而如 testImplementation、androidTestImplementation 等依賴配置可以更好地處理測試相關依賴。

2.3 聲明依賴


2.3.1 聲明 binary 依賴

現在的軟體工程很少單獨地構建代碼,因為現在的工程通常為了重用已存在且久經考驗的功能而引入外部庫,因此被稱為 binary dependencies。Gradle 會解析 binary 依賴然後從專門的遠程倉庫中下載並存到 cache 中以避免不必要的網絡請求: 

每個 artifact 在倉庫中的 coordinate 都會包含 groupId 、 artifactId 和 version 三個元素,如在一個使用 Spring 框架的 Java 工程中添加一個編譯時依賴:

apply plugin: 'java-library'
repositories {
   mavenCentral()
}
dependencies {
   implementation 'org.springframework:spring-web:5.0.2.RELEASE'
}

Gradle 會從 Maven中央倉庫 https://search.maven.org/ 解析並下載這個依賴(包括它的傳遞依賴),然後使用它去編譯 Java 源碼,其中的 version 屬性是指定了具體版本,表明總是使用這個具體的依賴不再更改。 

當然,如果你總是想使用最新版本的 binary 依賴,你可以使用動態的 version,Gradle 默認會緩存 24 小時:

implementation 'org.springframework:spring-web:5.+'

有些情況開發團隊在完全完成新版本的開發之前為了讓使用者能體驗最新的功能特色,會提供一個 changing version,在 Maven 倉庫中 changing version 通常被稱作 snapshot version,而 snapshot version會包含-SNAPSHOT後綴,如:

implementation 'org.springframework:spring-web:5.0.3.BUILD-SNAPSHOT'

2.3.2 聲明文件依賴

工程有時候不會依賴 binary 倉庫中的庫,而是把依賴放在共享磁碟或者版本控制系統的工程源碼中(JFrog Artifactory 或 Sonatype Nexus 可以存儲解析這種外部依賴),這種依賴被稱為 file dependencies ,因為它們是以不涉及任何 metadata(如傳遞依賴、作者)的文件形式存在的。如我們添加來自 ant、libs 和 tools 目錄的文件依賴:

configurations {
   antContrib
   externalLibs
   deploymentTools
}
dependencies {
   antContrib files('ant/antcontrib.jar')
   externalLibs files('libs/commons-lang.jar', 'libs/log4j.jar')
   deploymentTools fileTree(dir: 'tools', include: '*.exe')
}

2.3.3 聲明工程依賴

現在的工程通常把組件獨立成 module 以提高可維護性及防止強耦合,這些 module 可以定義相互依賴以重用代碼,而 Gradle 可以管理這些 module 間的依賴。由於每個 module 都表現成一個 Gradle project,這種依賴被稱為 project dependencies 。在運行時,Gradle 構建會自動確保工程的依賴以正確的順序構建並添加到 classpath 中編譯。

project(':web-service') {
   dependencies {
       implementation project(':utils')
       implementation project(':api')
   }
}

強制所有的 android support libraries 使用相同的版本:

configurations.all {
   resolutionStrategy {
       eachDependency { details ->
           
           if (details.requested.group == 'com.android.support' &&
                   details.requested.name != 'multidex' &&
                   details.requested.name != 'multidex-instrumentation') {
               details.useVersion supportLibVersion
           }
       }
   }
}

更改生成的 APK 文件名:

android.applicationVariants.all { variant ->
   variant.outputs.all {
       outputFileName = "${variant.name}-${variant.versionName}.apk"
   }
}

如果開啟了 Multidex 後在 Android 5.0 以下設備上出現了 java.lang.NoClassDefFoundError 異常,可能是由於構建工具沒能把某些依賴庫代碼放進主 dex 文件中,這時就需要手動指定還有哪些要放入主 dex 文件中的類。在構建類型中指定 multiDexKeepFile 或 multiDexKeepProguard 屬性即可: 

在 build 文件同級目錄新建 multidex-config.txt 文件,文件的每一行為類的全限定名,如:

com/example/MyClass.class
com/example/MyOtherClass.class

android {
   buildTypes {
       release {
           multiDexKeepFile file('multidex-config.txt')
           ...
       }
   }
}

或者新建 multidex-config.pro 文件,使用 Proguard 語法指定放入主 dex 文件中的類,如:

-keep class com.example.** { *; }

android {
   buildTypes {
       release {
           multiDexKeepProguard file('multidex-config.pro')
           ...
       }
   }
}

參考

Configure Your Build

https://developer.android.com/studio/build/index.html#build-process

Gradle User guides

https://gradle.org/guides

Gradle reference documentation

https://docs.gradle.org/current/userguide/userguide.html

最後推薦一下我做的網站,玩Android: wanandroid.com ,包含詳盡的知識體系、好用的工具,還有本公眾號文章合集,歡迎體驗和收藏!

推薦閱讀:

堅持寫技術博客

使用RxJava的最佳開發場景

如果你想要跟大家分享你的文章,歡迎投稿~

相關焦點

  • 在Ubuntu18.04中Android Studio開發環境搭建
    作為移動端的作業系統Android佔據了半壁以上的江山,那麼今天就談談在Ubuntu18.04中,Android App應用的開發環境構建。第一步,從Android Studio官網,下載應用包。官網: http://www.android-studio.org下載目錄: /home/username/Downloads/android-studio-ide-173.4720617-linux.zip解壓文件: 右鍵解壓zip文件,然後拷貝android-studio
  • 提高工作效率的Android Studio奇技
    http://www.developerphil.com/android-studio-tips-of-the-day-roundup-1/http://www.developerphil.com/android-studio-tips-of-the-day-roundup-2/http://www.developerphil.com/android-studio-tips-of-the-day-roundup-3/http://www.developerphil.com/android-studio-tips-of-the-day-roundup-4/
  • Android Studio 4.1 發布,全方位提升開發體驗
    https://developer.android.google.cn/studiohttps://developer.android.google.cn/jetpackAndroid Studio 4.1 的一些亮點如下: 引入全新的 Database Inspector,用於查詢應用的資料庫;支持瀏覽使用 Dagger 或 Hilt 進行依賴項注入的項目;支持在 Android 項目中使用
  • Android Studio打包apk,aar,jar包
    一片楓葉_劉超的博客地址:http://blog.csdn.net/qq_23547831作者編寫了github項目解析、android源碼分析以及產品研發多個專題,有興趣的可以關注下學習學習~文本我們將講解android studio打包apk,aar,jar包的相關知識。
  • Android studio導入第三方類庫的方法
    2、然後我們重啟我們的android studio就會發現我們的項目下面有了我們的類庫4.還要在項目SlidingMenu-master目錄下添加一個build.gradle的這個文件,內容如下buildscript {repositories {mavenCentral()}dependencies {classpath 』com.android.tools.build:gradle:0.6.+』}}apply plugin: 』android-library
  • Android Studio漢化教程筆記
    收錄於話題 #androidstudio 1個
  • Android Studio 3.0 Android 分析器 | 中文教學視頻
    https://developer.android.google.cn/studio/preview/features/android-profiler.htmlhttps://developer.android.google.cn/guide/topics/te
  • 擁抱Android Studio(二):Android Studio與Gradle深入
    Android Studio 相關功能介紹文件夾組織視圖最常用的有 Project 和 Android 視圖,前者按照項目文件樹進行組織,後者是以 Gradle 構建文件作為核心進行組織:/gradlew -p app buildSync正常情況下,修改了 build.gradle 文件,文件上方就會有一個 sync 的按鈕,點擊之後會重新構建整個 build.gradle。但是某些特殊情況,這個同步可能會失敗。那就需要一個額外的觸發。
  • 谷歌Android Studio 和 Gradle 插件使用全新版本編號
    Android Studio 的新版本編號方案IT之家獲悉,從 Arctic Fox (2020.3.1) 開始,Android Studio 的版本號系統將以年份為基礎,從而更加符合 IntelliJ IDEA 的版本模式——Android Studio 正是基於這個 IDE 構建的。
  • 谷歌:Android Studio 和 Gradle 插件使用全新版本編號
    Android Studio 的新版本編號方案IT之家獲悉,從 Arctic Fox (2020.3.1) 開始,Android Studio 的版本號系統將以年份為基礎,從而更加符合 IntelliJ IDEA 的版本模式——Android Studio 正是基於這個 IDE 構建的。
  • 谷歌Android Studio Arctic Fox (2020.3.1) 預覽版發布,附更新內容
    版本說明 https://developer.android.google.cn/studio/releases對於那些嘗試使用 Jetpack Compose 的用戶,我們提供了大量更新內容,例如將 @Preview Composable 部署到設備 / 模擬器 :Jetpack Composehttps:/
  • Android Studio 3.6 穩定版發布 - OSCHINA - 中文開源技術交流社區
    該計劃著力改進 Android Studio 的三個主要方面:系統運行狀況、功能完善以及錯誤修復,力圖在 Android Studio 與 Android 模擬器中構建功能強大且穩定的基礎特性與工作流。因此在 Android Studio 3.6 中,除了引入一小部分功能和完善現有功能,開發團隊還花費了很大的精力來解決錯誤並改善基礎性能,以確保達到去年設定的高質量標準。
  • 實用教程|Android Studio安裝和設置
    下載地址·  Cocos2d-x  v3.15 (4.14論壇發布社區版本,4.21官網發布正式版本)http://www.cocos.com/download·  Android Studio 2.3 https://developer.android.com
  • Gradle for Android入門
    今天主要介紹Android studio工具的使用,以及cradle基礎入門,使用cradle wrapper和如何從eclipse遷移到Android studio。這篇文章記於2015.12.30,Android studio正式版本已經開發到1.5,而預覽版已經到了2.0,所以轉到Android studio吧。
  • 小技巧 | 在 Android Studio 調試應用 (上)
    接下來,我們會為您一一呈現那些我們認為最好的、節省您時間的、且方便與您的調試流程整合的小技巧。雖然您的應用可能與本文假想中的示例應用大相逕庭,但是本文所介紹的小竅門可以用在任何應用的開發上。本文分為上下兩篇,本篇為上篇。我們從經典調試法 —— printf 語句的一個小竅門說起。
  • 跟隨IntelliJ IDEA,谷歌 Android Studio 和 Gradle 插件使用全新...
    Android Studio 的新版本編號方案  從 Arctic Fox (2020.3.1) 開始,Android Studio 的版本號系統將以年份為基礎,從而更加符合 IntelliJ IDEA 的版本模式——Android Studio 正是基於這個 IDE 構建的
  • Android Studio中使用apt
    別急,我們先搭建環境(基於gradle插件2.2.0以上版本)1.在android studio中新建一個Java module,用於存裝註解處理邏輯,名字隨便啦,反正我一般都取名:apt。很重要的事:在app module中添加註解處理依賴:annotationProcessor project(『:apt』)(解釋原因:由於android的module中不包含有apt相關類,因此需要新建一個java module來編寫apt邏輯。什麼?你不信?
  • 開源之系統:非終端命令,Ubuntu中去官網下載安裝Android Studio
    而這次我們開始安裝Android studio用以開發Android應用APP。我們打開官網,找到下載的頁面。就能找到down Android Studio的綠色按鈕,下面是版本的字樣,機智客這裡下載的是4.1.1 for Linux 64-bit (883 MB)。然後點擊下載,彈窗一個頁面,需要閱讀並同意相關協議。同樣有一個下載按鈕,上面有:適用平臺:Linux 的字樣。
  • 一份官方的 Android Studio 調試應用 技巧!
    接下來,我們會為您一一呈現那些我們認為最好的、節省您時間的、且方便與您的調試流程整合的小技巧。雖然您的應用可能與本文假想中的示例應用大相逕庭,但是本文所介紹的小竅門可以用在任何應用的開發上。本文分為上下兩篇,本篇為上篇。我們從經典調試法 —— printf 語句的一個小竅門說起。
  • Gradle 與 Android 構建入門
    大家也許有偶爾會想,為什麼需要 Gradle 這個自動化構建工具?默認創建的 Android 工程裡的文件都有什麼含義?什麼是依賴管理?Android 的打包流程是什麼?通過閱讀本文,可以大致了解 Gradle 是如何工作,可以有針對性搜索相關內容,更加快速的解決常見編譯錯誤。一 為什麼需要自動化構建工具?