Android Gradle使用总结(2)

1,841 阅读5分钟

Android Gradle使用篇:

Android Gradle使用总结(1)

Android Gradle使用总结(2)

一、自定义Android gradle工程

1、defaultConfig默认配置

defaultConfig 是默认的配置,是一个ProductFlavour。对于多渠道打包,等情况,如果不针对自定义的是一个ProductFlavour单独配置的话,则默认使用defaultConfig的配置

(1)applicationId

指定生成的app包名,对应值是 String,如:applicationId "com.android.xx"

(2)minSdkVersion

App最低支持的Android操作系统版本,对应值是 int型(即对于sdk 的ApiLevel)如,minSdkVersion 25

(3)targetSdkVersion

配置当前是基于哪个sdk版本进行开发,可选值与 minSdkVersion一样

(4)versionCode

内部版本号,对应值是int型,用于配置Android App内部版本号,通常用于版本的升级

(5)versionName

用于配置app的版本名称,对应值是String,如"v1.0.0",让用户知道当前app版本。versionCode是内部使用,versionName是外部使用,一起配合完成app的版本升级控制。

(6)testApplicationId

配置测试app的包名,默认是 applicationId + ".test",一般情况下,用默认的即可。

(7)testInstrumentationRunner

用于配置单元测试时使用的Runner,默认使用android.test.InstrumentationTestRunner。

(8)signingConfig

配置默认的签名信息,对生成的app进行签名。对应值是SigningConfig对象。 具体使用,查看配置签名信息部分

(9)proguardFile 和 proguardFiles

两者都是配置混淆规则文件,区别是proguardFile接受一个文件对象,而proguardFiles可以同时接受多个。

(10)multiDexEnabled

是否启动自动拆分多个Dex的功能,用于突破方法超过65535的设置,后面再具体介绍

multiDexEnabled true

2、配置签名信息

Android Gradle 提供了signingConfigs{}配置块,用于生成多个签名配置信息,其类型是NamedDomainObjectContainer,因此,我们在signingConfigs{}中定义的都是一个SigningConfig的对象实例。

一个SigningConfig,即签名配置,可配置的元素有:storeFile: 签名文件位置;storeType:签名证书类型(可不填);storePassword:签名证书密码;keyAlias:签名证书密钥别名;keyPassword:签名证书中的密钥的密码。如:

signingConfigs{
        release{ //生成了release的签名配置
            storeFile file('../John.jks')
            storePassword '12345678'
            keyAlias 'key0'
            keyPassword '12345678'
        }
    }

注:debug签名文件一般位于$HOME/.android/debug.keystore

对于生成的签名配置,可以应用到 defaultConfig中的signingConfig进行默认签名配置或应用到buildTypes中针对构建类型进行签名配置。如:

buildTypes {
        release {
            signingConfig signingConfigs.release //配置release类型签名
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    
    defaultConfig {
        applicationId "com.example.john.tapeview"
        minSdkVersion 24
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        signingConfig signingConfigs.release  //配置默认签名
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

3、构建类型(buildTypes)

buildTypes{}signingConfigs{}一样,都是Android 的一个方法,接收到也是域对象 NamedDomainObjectContainer,添加的每一个都是BuildType类型。

每一个BuildType都会生成一个SourceSet,默认位置是src//,因此,可以单独为其指定Java源代码和res资源等。且,新增的BuildType不能命名为 main 或 androidTest(因android默认已经生成),且相互之间不能同名。

(1)applicationIdSuffix

用于配置基于applicationId的后缀,如applicationId为 com.John.gradle.sample , 在debug的buildType中指定 applicationIdSuffix ".debug",则生成的debug的包名为com.John.gradle.sample.debug。

注:library 工程不支持

(2)signingConfig

配置签名信息,使用同前面提到的 defaultConfig一样。

(3)启动zipAlign优化

zipalign是android提供的整理优化apk的工具,能提高系统和应用的运行效率,更快读写apk资源,降低内存,所以,对于发布的apk,一般开启 zipAlignEnabled true //true为开启

(4)资源清理shrinkResources

用于配置是否自动清理未使用的资源,true为开启,false为关闭。需结合混淆使用。

(5)使用混淆 minifyEnabled

启用混淆可以优化代码,同时结合shrinkResources清理资源,可以缩小apk包,还可以混淆代码。一般发布的都是要混淆的。

开启混淆:minifyEnabled true //true为开启;使用proguardFileproguardFiles设置混淆规则文件,两者区别如前面defaultConfig中说明。

**注:**对于多渠道打包,每个productFlavor都可以单独配置混淆规则文件(通过各自的proguardFileproguardFiles)。

(6)multiDexEnabled

是否启动自动拆分多个Dex的功能,用于突破方法超过65535的设置,后面再具体介绍

multiDexEnabled true

(7)debuggable 和 jniDebuggable

debuggable:是否生成一个可供调试的apk,对应值为boolean类型;

jniDebuggable:是否生成一个可供调试Jni(C/C++)代码的apk,对应值为boolean类型;

二、Android gradle高级自定义

1、批量修改生成的apk文件名

Android Gradle提供了3个属性,applicationVariants(仅仅适用于Android 应用Gradle插件),和libraryVariants(仅仅适用于Android库gradle插件),testVariants(以上两种都适用)

applicationVariants是一个集合,每一个元素都是一个生成的产物,即 xxxRelease 和 xxxDebug 等(即生成apk) ,它有一个outputs作为输出集合。遍历,若名字以.apk结尾,那么就是要修改的apk输出。

//动态改变生成的apk的名字:  项目名_渠道名_v版本名_构建日期.apk
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            if (output.outputFile != null && output.outputFile.name.endsWith('.apk')
                    &&'release'==(variant.buildType.name)) {
                def flavorName = variant.flavorName.startsWith("_") ? variant.flavorName.substring(1) : variant.flavorName
                def apkFileName = "Example92_${flavorName}_v${variant.versionName}_${buildTime()}.apk"
                outputFileName = apkFileName
            }
        }
    }
    
    ...
    def static buildTime() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMdd')
    return formattedDate
}

2、多方式配置 VersionCode 和 VersionName

(1)通过应用脚本插件(apply from)

  1. 新建一个version.gradle(当前存放在项目路径下的gradle文件夹中),并设置自定义属性

ext{
    appVersionCode = 1
    appVersionName = '1.0.2'
}
  1. 在rootProject中应用该脚本文件
apply from : 'gradle/version.gradle'
  1. 可在任意子工程中引用该设置:

(2)直接在属性文件(xxx.properties)中定义使用

  1. 在工程目录下的gradle.properties中定义
    3.可在任意子工程中引用该设置:

(3)从 git 的 tag 上获取 VersionName 和 versionCode

/**
 * 以git tag的数量作为其版本号
 * @return tag的数量
 */
def static getAppVersionCode(){
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git','tag','--list'
        standardOutput = stdout
    }
    return stdout.toString().split("\n").size()
}

/**
 * 从git tag中获取应用的版本名称
 * @return git tag的名称
 */
def static getAppVersionName(){
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git','describe','--abbrev=0','--tags'
        standardOutput = stdout
    }
    return stdout.toString().replaceAll("\n","")
}

3、动态配置AndroidManifest文件

在构建过程,动态修改AndroidManifest文件中的内容

android gradle 提供了非常便捷的方法替换AndroidManifest文件中的内容,即manifestPlaceholder、Manifest占位符。

manifestPlaceholdersProductFlavor的一个属性,Map类型,所以可以同时配置多个占位符。

  1. 定义占位符:
...

productFlavors{
    google{
        manifestPlaceholders.put("UMENG_CHANNEL","google")
    }
    baidu{
        manifestPlaceholders.put("UMENG_CHANNEL","baidu")
    }
}

...
  1. 在AndroidManifes中使用这个占位符 "UMENG_CHANNEL"
...
<application>
    ...
    <meta-data android:value="${UMENG_CHANNEL}" android:name = "UMENG_CHANNEL"/>
    ...
</application>
...
  1. 亦可以迭代修改占位符
...
productFlavors{
        google{
        }
        baidu{
        }
    }
productFlavors.all{flavor->
    manifestPlaceholders.put("UMENG_CHANNEL",flavor.name)
}
...

4、自定义BuildConfig

Android gradle提供了buildConfigField(Srting type,String name ,String value) 来实现添加常量到BuildConfig中。一般在productFlavorsbuildTypes中使用:

注:对于value是String类型的,双引号一定得加上,这里写了什么,buildConfig会原封不动放上去

...
productFlavors{
        google{
            //对于value是String类型的,双引号一定得加上,这里写了什么,buildConfig会原封不动放上去
            buildConfigField 'String','name','"google"'
        }
        baidu{
            buildConfigField 'String','name','"baidu"'
        }
}
...

5、动态添加自定义的资源

Android gradle提供了resValue(String type,String name,String value)来 添加资源。只能在productFlavorsbuildTypes中使用

注:这里写了什么,编译出来后也会原封不动放上去

6、Dex选项配置


android {
    ...
    
    dexOptions {
        incremental true //android studio3.x以上已废弃,是否开启dx增量模式
        javaMaxHeapSize '4g' //提高java执行dx命令时的最大分配内存
        jumboMode true //强制开启jumboMode模式,让方法超过65535也构建成功
        pre
    }
    
    ...
}

7、编译选项和adb操作选项

android {
    ...
    
    compileOptions {
        encoding = 'utf-8'
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    adbOptions{
      timeOutInMs = 5000 //设置超时时间,单位 ms
      installOptions '-r','-s'//安装选项,一般不使用
    }
    
    ...
}

8、突破方法超过65535的限制

  1. defaultConfigbuildTypesproductFlavors中,开启multiDexEnabledmultiDexEnabled true

  2. 增加依赖:implementation 'com.android.support:multidex:1.0.3'

  3. 在自定义的 Application 中设置(5.0以上天然支持):

使自定义的Application继承MultiDexApplication

或直接在java代码中修改:

...
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}
...

多渠道构建

一个构建产物(apk),即Build Variant = BuildType + ProductFlavor,其中ProductFlavor又进一步划分dimensions,即Build Variant = BuildType + ProductFlavor's dimensions

1、多渠道构建ProductFlavor属性

...
productFlavors{
        google{
            applicationId "com.john.xxx"
        }
}
...

(1)applicationId,跟前面所述一样。

(2)manifestPlaceholders,跟前面所述一样。

(3)multiDexEnabled,跟前面所述一样。

(4)proguardFiles,跟前面所述一样。

(5)signingConfig,跟前面所述一样。

(6)testApplicationId,跟前面所述一样。

(7)versionCode 和 versionName,跟前面所述一样。

(8)dimension

作为ProductFlavor的维度,可理解为ProductFlavor的分组

如,free 和 paid 属于version分组,而x86 和 arm属于架构分组:

android{
    ...
    
    flavorDimensions "version","abi" //定义分组
    productFlavors{
        free{
            dimension 'version'
        }
        paid{
            dimension 'version'
        }
        x86{
            dimension 'abi'
        }
        arm{
            dimension 'abi'
        }
    }
    ...
}

对于以上的设置,Build Variant = BuildType + ProductFlavor's dimensions,则生成的assemble任务, 即variant:

  • ArmFreeDebug
  • ArmFreeRelaese
  • ArmPaidDebug
  • ArmPaidRelease
  • X86FreeDebug
  • X86FreeRelaese
  • X86PaidDebug
  • X86PaidRelease

参考链接

Android Developer官网