释果存 發表於 2023-4-26 15:11:00

Android开发之深入理解Android Studio构建文件build.gradle配置

<blockquote>
<p>原文地址 www.cnblogs.com</p>
</blockquote>
<h2 id="摘要">摘要:</h2>
<p>每周一次,深入学习Android教程,TeachCourse今天带来的一篇关于Android Studio构建文件<code>build.gradle</code>的相关配置,重点学习几个方面的内容:1、<code>applicationId</code>和<code>package</code>属性值的关系,2、怎么配置安全的自定义签名,3、两种构建类型的区别,4、为什么要定制产品的偏好配置?,5、怎么才能加快_DEX文件_的生成速度,6、为什么要将一个apk拆分成多个?,7、关于引入依赖包你不知道的秘密。通过这篇文章的学习,你会对<code>build.gradle</code>文件有一个全新的认识,可以将TeachCourse文章提到的相关说明作为文档参考,方便在另一个module中引入,代码如下:</p>
<pre><code>apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "25.0.2"
    /**
   * 一、默认产品偏好配置
   */
    defaultConfig {
      ...
    }
    /**
   * 二、自定义签名配置
   */
    signingConfigs {
      config {
          ...
      }
    }
    /**
   * 三、构建类型,分为release和debug两种
   */
    buildTypes {
      release {
          ...
      }
      debug {
          ...
      }
    }
    /**
   * 四、自定义产品偏好配置,可以定义多个偏好产品
   */
    productFlavors {
      demo {
            applicationId "cn.teahcourse.demo"
            versionName "1.0-demo"
            signingConfig signingConfigs.config
      }
      personal{
          ...
      }
      enterprise{
          ...
      }
    }
    /**
   *五、DEX文件构建属性配置(加快构建速度)
   */
    dexOptions {
      ...
    }
    /**
   * 六、将一个apk拆分成多个相关配置(拆分依据:屏幕密度、系统架构)
   */
    splits {
      density {
         ...
      }
      abi {
         ...
      }
    }
}
/**
* 七、引入依赖包的秘密
*/
dependencies {
   ...
}
</code></pre>
<h2 id="一applicationid和package属性值的关系">一、<code>applicationId</code>和<code>package</code>属性值的关系</h2>
<p>Android Studio开发工具创建module的时候,默认在<code>build.gradle</code>文件生成一个<code>applicationId</code>,对应的属性值是填写的_package name_,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-ac398368aad2a3dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="applicationId属性值" loading="lazy"></p>
<p>这时候的<code>applicationId</code>和<code>package</code>属性值一样,刚开始接触Android Studio的时候,TeachCourse就听说<code>applicationId</code>表示真正的包名,而<code>package</code>不再被认为是包名,因为应用程序被打包成apk文件的时候,原先在_manifest_声明的<code>package</code>被<code>applicationId</code>代替,也就是说如果你的<code>build.gradle</code>文件添加了<code>applicationId</code>属性值,无论两者是否一样,打包的apk文件的<code>package</code>属性值等于<code>applicationId</code>,如果不信,TeachCourse先来做过实验,将<code>applicationId</code>改为<code>cn.teachcourse.demo</code>,将<code>package</code>改为<code>cn.teachcourse</code>,然后将module打包成apk文件,使用反编译工具_apktool.exe_,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-9559ad631f09cf62.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="apktool反编译工具" loading="lazy"></p>
<p>最后,打开<code>AndroidManifest.xml</code>文件,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-7e68d5d403540984.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="package被applicationId代替" loading="lazy"></p>
<p><strong>结果证明:</strong><code>cn.teachcourse</code>被<code>cn.teachcourse.demo</code>代替</p>
<p>正是因为打包的apk文件的<code>package</code>的属性值被<code>applicationId</code>代替,也刚好说明为什么应用程序安装到手机后,手机上显示的是<code>applicationId</code>,而不是显示<code>package</code>,同时如果想在应用程序中接入第三方的API,填写的包名也必须是<code>applicationId</code>,常见的例子有:1.接入微信的支付功能,2.接入微信的分享功能,3.集成百度地图的定位功能</p>
<p>那么,_AndroidManifest.xml_的<code>package</code>到底有什么用呢?尽管,<code>package</code>在打包成apk的时候被<code>applicationId</code>代替,但是在构建的时候<code>package</code>有两方面的作用:</p>
<p><strong>第一个作用:</strong>在<code>package</code>指定的目录下,生成对应的<code>R.java</code>文件,上面的例子,构建的时候,生成<strong>R</strong>文件的目录,如下图:</p>
<pre><code>app\build\generated\source\r\demo\debug\cn\teachcourse\R.java
</code></pre>
<p><strong>第二个作用:</strong>在<code>package</code>指定的目录下,引用对应的<code>activity</code>、<code>server</code>组件,如下图:</p>
<pre><code>&lt;!-- 定义Activity --&gt;
&lt;activity android:/&gt;

&lt;!-- 添加service组件 --&gt;
&lt;service android: /&gt;
</code></pre>
<p>在上面反编译的_AndroidManifest.xml_文件中,查看对应的组件目录,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-715de4f0d9bbda0d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="package属性值作用" loading="lazy"></p>
<p>也就是说,_manifest_指定的组件不管使用相对路径还是绝对路径,打包成apk文件后,都变成绝对路径,结构是:<em>package.组件</em></p>
<p>需要特别注意的问题有:<br>
<strong>第一个问题:</strong>代码中使用<code>getPackageName()</code>或<code>getPackageManager()</code>对应的方法,返回的是<code>applicationId</code>属性值</p>
<p><strong>第二问题:</strong>使用<code>WebView</code>基本存放于<code>res/raw</code>内的文件时,如果<code>applicationId</code>不等于<code>package</code>,提示<code>ClassNotFoundException</code>异常(可能是官方的bug),TeachCourse测试后找到两个解决的办法</p>
<ol>
<li>尝试将<code>res/raw/note.html</code>文件移动到<code>assets</code>文件夹下,更换资源文件加载路径</li>
</ol>
<pre><code>mWebView.loadUrl("file:///android_asset/note.html");
</code></pre>
<ol start="2">
<li>保持<code>applicationId</code>属性值和<code>package</code>属性值一致</li>
</ol>
<pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.teahcourse.demo"&gt;
    ...
&lt;/manifest&gt;
</code></pre>
<h2 id="二怎么配置安全的自定义签名">二、怎么配置安全的自定义签名</h2>
<p>自定义签名指的是使用开发者导出的密钥库对apk文件进行签名,关于怎么生成自己的密钥库,不懂的同学,可以后面看一下TeachCourse另一篇文章《Android Studio运行时自带签名配置过程详解》,文章介绍了怎么配置Android Studio的运行时签名,这样做的目的:在接入一些需要自定义签名的API时,方便直接调试。</p>
<p>这里,介绍的是安全的自定义签名,即怎么才让别人看不到我们在<code>build.gradle</code>写入的密码(包括别名密码、密钥库密码),关于签名文件的重要性,TeachCourse在这里就不说了。</p>
<p>** 2.1 配置安全的自定义签名(1),步骤:**</p>
<ol>
<li>在项目的根目录下创建一个名称为 keystore.properties 的文件。此文件应当包含您的签署信息,如下所示:</li>
</ol>
<pre><code>storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
</code></pre>
<p><strong>这里需要注意:</strong>_keystore.properties_中<code>storeFile</code>签名文件是相对module目录的路径,即将密钥库文件保存在module根目录下<br>
<img src="//upload-images.jianshu.io/upload_images/4692468-c75b002636689fb7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="密钥库配置" loading="lazy"></p>
<ol start="2">
<li>在模块的 <code>build.gradle</code> 文件中,于 <code>android {}</code> 块的前面添加用于加载 <em>keystore.properties</em> 文件的代码。</li>
</ol>
<pre><code>...
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
    ...
}
</code></pre>
<blockquote>
<p>注:您可以选择将 <em>keystore.properties</em> 文件存储在其他位置(例如,存储在模块文件夹中而不是项目的根文件夹中,或者如果您使用连续集成工具,也可以存储在构建服务器上)。在这种情况下,您应当修改上面的代码,以便使用实际 <em>keystore.properties</em> 文件的位置正确初始化 keystorePropertiesFile。</p>
</blockquote>
<ol start="3">
<li>您可以使用语法 <code>keystoreProperties['属性名称']</code> 引用存储在 <em>keystoreProperties</em> 中的属性。修改模块 <code>build.gradle</code> 文件的 <code>signingConfigs</code> 块,以便使用此语法引用存储在 <em>keystoreProperties</em> 中的签署信息。</li>
</ol>
<pre><code>android {
    signingConfigs {
      config {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
      }
    }
    ...
}
</code></pre>
<ol start="4">
<li>最后,我们就可以按照《<em>Android Studio运行时自带签名配置过程详解</em>》介绍的方式,将<code>signingConfigs</code> 块作用于release版本或debug版本</li>
</ol>
<p>** 2.2 配置安全的自定义签名(2),步骤:**</p>
<ol>
<li>第二种安全的自定义签名的方式是:将别名、别名密码、密钥密码以键值对的形式保存到当前电脑的环境变量中,然后通过变量名读取变量值,如下图:</li>
</ol>
<pre><code>android {
    signingConfigs {
      config {
            keyAlias System.getenv("KEYALIAS")
            keyPassword System.getenv("KEYPWD")
            storeFile file('release.jks')
            storePassword System.getenv("KSTOREPWD")
      }
    }
    ...
}
</code></pre>
<ol start="2">
<li>
<p>_KEYALIAS_指的是环境变量的变量名,<code>System.getenv("KEYALIAS")</code>的读取变量名对应的变量值,如图:<br>
<img src="//upload-images.jianshu.io/upload_images/4692468-45ab259b729114dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="读取环境变量值" loading="lazy"></p>
</li>
<li>
<p><em>KEYPWD</em>,按照上图的方式添加,如下图:<br>
<img src="//upload-images.jianshu.io/upload_images/4692468-a57cbd3b9b9659ff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="添加KEYPWD环境变量" loading="lazy"></p>
</li>
<li>
<p>_KSTOREPWD_以同样的方式,如下图:<br>
<img src="http://teachcourse.cn/wp-content/uploads/2017/03/20170317173515.png" alt="添加KSTOREPWD环境变量" loading="lazy"></p>
</li>
</ol>
<p><strong>需要特别注意的是:</strong>第二种自定义签名的方式,需要先检查Android Studio是否已配置了<code>gradle</code>工具的环境变量,打开Android Studio的_terminal_窗口,输入:<code>gradle build</code>,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-c82b7defc50244e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="检查gradle环境变量" loading="lazy"></p>
<p>如果,你的_terminal_窗口提示_gradle不是内部命令_,操作上述步骤之前,你得添加<code>gradle</code>工具的环境变量,Android Studio的<code>gradle</code>工具默认存放路径:</p>
<pre><code>C:\Program Files\Android\Android Studio\gradle\gradle-3.2
</code></pre>
<p>配置<code>gradle</code>的环境变量,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-6c6cbf3c55d7cedc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="添加gradle根目录" loading="lazy"></p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-b3531a7153d4e884.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="添加gradle到path变量中" loading="lazy"></p>
<h2 id="三两种构建类型的区别">三、两种构建类型的区别</h2>
<p>每一个APP至少包含<code>debug</code>和<code>release</code>两种构建类型,<code>debug</code>定义APP的调试版本,<code>debug</code>模式的几个特点:</p>
<ol>
<li>支持断点调试和log信息打印,<code>debuggable</code>属性值为<code>true</code></li>
<li>使用系统默认的密钥库签署apk文件</li>
<li>没有对apk文件进行代码和资源文件的优化(包括文件压缩、冗余文件删除)</li>
<li>没有对代码进行混淆</li>
</ol>
<p><code>release</code>定义APP的发布版本,创建项目module中的<code>build.gradle</code>文件,代码如下:</p>
<pre><code>buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
</code></pre>
<p><code>minifyEnable</code>定义是否压缩代码,<code>false</code>表示不压缩;<code>proguardFiles</code>定义混淆代码的默认混淆规则,<code>proguard-android.txt</code>表示系统自带的混淆规则,<code>proguard-rules.pro</code>位于当前module根目录下,用于定义开发者自己的混淆规则。</p>
<p><code>release</code>模式需要注意的几个特点:</p>
<ol>
<li>不支持断点调试,<code>debuggable</code>默认为false</li>
<li>没有压缩类文件代码,<code>minifyEnabled</code>,默认为false</li>
<li>没有压缩资源文件,<code>shrinkResources</code>,默认为false</li>
<li>没有指定自定义签名文件,默认使用系统的密钥库签署apk</li>
</ol>
<p>开发者在发布应用程序时,需要对<code>release</code>模式下的属性配置进行修改,优化apk文件,删除无用的代码和资源文件,混淆类文件和资源名称,自定义签名密钥库,代码如下:</p>
<pre><code>release {
    shrinkResources true
    minifyEnabled true
    useProguard true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    signingConfig signingConfigs.config
}
</code></pre>
<p><strong>总结:</strong><code>debug</code>和<code>release</code>模式,最大的区别默认属性配置不一样,两种模式支持的属性配置还包括,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-d80aa2499bc1fa72.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="debug和release相关配置" loading="lazy"></p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-7fc57922766be184.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="debug和release相关配置" loading="lazy"></p>
<p>记不住代码的同学,可以选中_Build Types_定义的模式,在可选项中改变对应属性配置,Android Studio运行时签名的实质将<code>debug</code>模式下的<code>Signing Config</code>设置为自定义密钥库文件,但是TeachCourse随着不断深入学习后发现,其实<code>debug</code>模式下配置<code>Signing Config</code>是<strong>多此一举</strong>,而只要在<code>release</code>模式下配置<code>Signing Config</code>就够了,Android Studio的可以方便为我们生成两种模式下对应的apk文件,在Android Studio的左下角_Build Variant_中切换,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-9b6d855d4467229c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="切换debug或release构建类型" loading="lazy"></p>
<p>下面介绍了<strong>产品偏好配置</strong>后,回头再看看它们两者之间的关系。</p>
<h2 id="四为什么要定制产品的偏好配置">四、为什么要定制产品的偏好配置?</h2>
<p>什么是产品的偏好配置呢?比如说,TeachCourse想要开发一个应用程序,包含个人版本<strong>personal</strong>和企业版本<strong>enterprise</strong>,这两个版本之间在功能上有所区别,企业版自然比个人版功能要多一些,很明显就是要就一个Android项目打包成两个产品发布,它们之间的要求如下所示:</p>
<p><strong>personal:</strong>版本号为1,最低SDK版本定义为_11_,最高SDK定义为_24_,版本名称后缀定义为_-personal_,applicationId后缀定义为_-per_,签名文件为自定义密钥库,代码如下:</p>
<pre><code>personal {
    versionCode 1
    minSdkVersion 11
    targetSdkVersion 24
    versionNameSuffix '-personal'
    applicationIdSuffix '-per'
    signingConfig signingConfigs.config
}
</code></pre>
<p><strong>enterprise:</strong>版本号为1000,最低SDK版本定义为_11_,最高SDK定义为_24_,版本名称后缀定义为_-profession_,applicationId后缀定义为_-pro_,签名文件为自定义密钥库代码如下:</p>
<pre><code>enterprise {
    versionCode 1000
    minSdkVersion 11
    targetSdkVersion 24
    versionNameSuffix '-profession'
    applicationIdSuffix 'full'
    signingConfig signingConfigs.config
}
</code></pre>
<p>同时,TeachCourse定义第三个产品偏好配置为demo,用于上传GitHub,提供下载,代码如下:</p>
<pre><code>demo {
    applicationId "cn.teahcourse.demo"
    versionName "1.0-demo"
    signingConfig signingConfigs.config
}
</code></pre>
<p>一个Android项目,配置三个偏好的产品,即使修改了项目代码,也可以快速编译并打包三个apk文件,在Android Studio的左下角Build Variant中切换,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-28cd04a4085941a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="产品偏好配置" loading="lazy"></p>
<p>看上面的图片,你是不是发现了什么,突然间,三个偏好配置的产品,出现了<strong>6</strong>个变体,一个产品包含<code>debug</code>和<code>release</code>两个版本,构建类型和偏好产品之间的关系是:<em>一个偏好产品,肯定包含一个debug版本和一个release版本,可以生成变体的总数为<code>flavors*2</code></em>,选中需要调试的版本或选中需要发布的版本,Android Studio自动重新构建Android项目,就可以针对指定的产品进行调试或打包,非常的方便吧!</p>
<p>偏好产品相关配置,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-c9ba66a25c9f103a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="产品偏好配置" loading="lazy"></p>
<p><code>defaultConfig</code>也属于其中一种偏好产品,在我们没有定义自己的偏好产品时,我们构建和编译的就是默认的<code>defaultConfig</code>这个产品,也就只包含<code>debug</code>和<code>release</code>两个变体。</p>
<h2 id="五怎么才能加快_dex_文件的生成速度">五、怎么才能加快_DEX_文件的生成速度?</h2>
<p>你有没有遇到Android Studio在每次构建的时候,都感觉花好长时间,TeachCourse就不止一次和同事抱怨说,Android Studio的编译速度还不如Eclipse快,蜗牛的速度真受不了呀?那该怎么办呢?</p>
<p>Android Studio提供<code>dexOption</code>区块以便于我们配置<strong>DEX</strong>构建属性,加快DEX文件的生成速度,代码如下:</p>
<pre><code> dexOptions {
    preDexLibraries true
    maxProcessCount 8
    javaMaxHeapSize "2048m"
}
</code></pre>
<ul>
<li><code>preDexLibraries</code>声明是否预先编译依赖库,从而加快构建速度,实质是通过延时清除已生成的依赖库的构建文件,从而提高构建速度,根据使用情况合理配置。</li>
<li><code>maxProcessCount</code>设置进程运行过程中可以使用的最大线程数。默认值为4。</li>
<li><code>javaMaxHeapSize</code>设置DEX编译器的最大堆大小,堆或者栈都是用于存放暂时不用的垃圾,当内存不足时,垃圾回收机制会清除过时的缓存,堆大小决定垃圾清除的频率,影响着构建的速度</li>
</ul>
<h2 id="六为什么要将一个apk拆分成多个">六、为什么要将一个apk拆分成多个?</h2>
<p>根据TeachCourse以往的经验,一个apk文件可以支持不同屏幕密度和不同ABIs的手机设备,是因为我们进行了屏幕适配,做法:<em>将市场主流的屏幕密度和ABIs集成到一个apk</em>,造成的影响,如果你的应用程序本身就比较大,集成了不同屏幕密度和支持不同ABIs的代码,打包出来的apk文件变得更大,考虑到流量成本和用户体验,减少apk文件的大小其中一种方式将一个apk文件拆分成多个。</p>
<p>_Gradle_能够单独指定只包含一种屏幕密度或一种ABI代码和资源文件的apk,在<code>build.gradle</code>文件中使用到<code>splits</code>区块,<code>splits</code>区块内同时提供了_按屏幕密度拆分_的<code>density</code>区块和_按abi拆分_的<code>abi</code>区块,在一个<code>build.gradle</code>文件中可以同时指定两者或两者中的其中一者,下面分别介绍:</p>
<p>** 6.1 按屏幕密度拆分**</p>
<pre><code>android {
...
splits {

    density {
      enable true
      exclude "xxxhdpi"
      reset()
      include "ldpi", "xxhdpi"
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
}
}
</code></pre>
<p>上面是一个按屏幕密度拆分的一个例子,各个标签的含义是:</p>
<ul>
<li><code>enable</code>,是否基于定义的屏幕密度拆分成多个apk文件,默认为false</li>
<li><code>exclude</code>,指定忽略拆分的屏幕密度列表,想要拆分成更多类型的apk文件,该关键字包含的屏幕密度列表应就可能少</li>
<li><code>reset()</code>,重置默认拆分的屏幕密度依据,然后使用<code>include</code>标签定义拆分的屏幕密度依据</li>
<li><code>include</code>,结合<code>reset</code>一起使用,定义拆分的屏幕密度依据</li>
<li><code>compatibleScreens</code>,指定兼容的屏幕尺寸列表,区别于屏幕密度,该标签将会在清单文件<code>manifest</code>中通过<code>&lt;compatible-screens&gt;</code>注入到每一个apk文件中,即apk文件只能安装到<code>&lt;compatible-screens&gt;</code>指定尺寸的手机上</li>
</ul>
<p>按照上面在<code>build.gradle</code>配置完成后,点击<code>Build APK</code>后,将在_apk_文件夹内生成多个apk文件,如下图:</p>
<p><img src="http://teachcourse.cn/wp-content/uploads/2017/03/20170319144209.png" alt="按屏幕密度拆分apk" loading="lazy"></p>
<p>为了验证是否在清单文件中注入指定屏幕尺寸,反编译其中一个apk文件,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-c6a373d076b40c57.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="反编译apk文件" loading="lazy"></p>
<p>** 6.2 按abi拆分**</p>
<pre><code>android {
...
splits {

    abi {

      enable true
      reset()
      include "x86", "armeabi-v7a", "mips"
      universalApk false
    }
}
}
</code></pre>
<p>上面是一个按abi拆分的一个例子,除了<code>universal</code>标签不一样外,其他标签是一样的,使用方法一样,<code>include</code>标签定义拆分的abi依据,关于_abi_介绍,参考下面连接:</p>
<blockquote>
<p>https://developer.android.google.cn/ndk/guides/abis.html</p>
</blockquote>
<p>同样,点击<code>Build APK</code>后,将在_apk_文件夹内生成多个apk文件,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-16c64d9e181289ea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="按abi拆分apk" loading="lazy"></p>
<p>仔细观察生成的apk文件,会发现下面两个规律:</p>
<ul>
<li>第一个规律:<em>apk总数=abi数量+density数量xabi数量</em></li>
<li>第二个规律:<em>apk filename=modulename-screendensityABI-buildvariant.apk</em></li>
</ul>
<h2 id="关于引入依赖包你不知道的秘密">关于引入依赖包你不知道的秘密</h2>
<p>不知道你会不会有和TeachCourse一样的想法,<code>dependencies</code>区块引入的jar包的名称长,基本无法记住,每一节又表示什么含义?Android Studio引入依赖项有几种方式?让我先看下面的这个例子:</p>
<pre><code>dependencies {
    compile project(":mylibrary")
    compile files('libs/zxing.jar')
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:25.1.0'
    compile group: 'com.android.support', name: 'appcompat-v7', version: '25.1.0'
}
</code></pre>
<p>可以看到Android Studio引入依赖项的方式分为上述四种,按顺序依次称为:1、<strong>模块依赖项</strong>,2、<strong>本地二进制依赖项</strong>,3、<strong>本地二进制依赖项</strong>,4、<strong>远程二进制依赖项</strong>,5、<strong>远程二进制依赖项</strong></p>
<ul>
<li><code>compile project(':mylibrary')</code> 行声明了一个名为<code>mylibrary</code>的本地 Android 库模块作为依赖项,并要求构建系统在构建应用时编译并包含该本地模块。</li>
<li><code>compile files('libs/zxing.jar')</code>和<code>compile fileTree(dir: 'libs', include: ['*.jar'])</code>都称为本地依赖项,告诉构建系统在编译类路径和最终的应用软件包中包含 <em>app/libs/</em> 目录内的指定或全部 JAR 文件。如果您有模块需要本地二进制依赖项,请将这些依赖项的 JAR 文件复制到项目内部的 <em>/libs</em> 中。</li>
<li><code>compile 'com.android.support:appcompat-v7:25.1.0'</code>和<code>compile group: 'com.android.support', name: 'appcompat-v7', version: '25.1.0'</code>都称为远程二进制依赖项,通过指定其 <em>JCenter</em> 坐标,针对 Android 支持库的 <em>25.1.0</em> 版本声明了一个依赖项。默认情况下,Android Studio 会将项目配置为使用顶级构建文件中的 JCenter 存储区。当您将项目与构建配置文件同步时,Gradle 会自动从 <em>JCenter</em> 中抽取依赖项。或者,您也可以通过使用 SDK 管理器下载和安装特定的依赖项。</li>
</ul>
<p><strong>第五种</strong>可以清楚看出每一节表示的含义,在Android Studio引入远程二进制依赖项,通常的做法是在_Library Dependency_窗口中搜索,搜索到最新版本的依赖项,如下图:</p>
<p><img src="//upload-images.jianshu.io/upload_images/4692468-650e6c7cf2d722a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="添加远程依赖项" loading="lazy"></p>
<p>似乎无法搜索到低版本的依赖项,如果想要引入低版本的,那该怎么办呢?如果先前不了解_远程二进制依赖项_的含义,可能想不到修改<code>version</code>的办法,现在就变得很简单了。</p>
<h3 id="总结">总结:</h3>
<p>本篇文章在阅读Android Studio用户指南多篇相关文档后完成的,想要更详细深入学习<code>gradle</code>指令的同学,可以继续研读Gradle官网文档,部分内容在TeachCourse开发的项目没有对应的需求,暂时也没有用到,是否使用更多应该根据项目实际情况而定,但可以作为用户开发的例子,先分享和收藏,以备不时之需。</p>
<blockquote>
<p>参考资料:<br>
https://developer.android.google.cn/studio/build/application-id.html<br>
https://developer.android.google.cn/studio/build/optimize-your-build.html<br>
https://developer.android.google.cn/studio/build/dependencies.html<br>
https://developer.android.google.cn/studio/build/build-variants.html</p>
</blockquote>
<p><strong>版权声明:</strong>本文著作权归TeachCourse所有,未经许可禁止转载,谢谢支持!<br>
<strong>转载请注明出处:</strong>http://teachcourse.cn/2385.html</p><br><br>
来源:https://www.cnblogs.com/cps666/p/17356165.html
頁: [1]
查看完整版本: Android开发之深入理解Android Studio构建文件build.gradle配置