Gradle在Android中的自定义用法

参考链接:

使用共享库

在Android中除了标准的SDK还存在两种库:

一种是add-ons库(位于sdk的add-ons目录下,大部分是第三方厂商或者公司开发的) 一种是optional库(位于platforms/android-xx/optional目录下,一般是为了兼容旧版本的API)

第一类库Android Gradle会自动解析,帮我们添加到classpath中。 第二类库需要我们自己手动添加到classpath中。

android {
    useLibrary 'org.apache.http.legacy'
}

最好在AndroidManifest文件里面配置一下uses-library标签,类似于google Maps如下:

<uses-library
    android:name="com.google.android.maps"
    android:required="true"/>

批量生成apk文件名

Android Gradle为我们提供了三个属性:applicationVariants、libraryVariants、testVariants. 这三个属性都返回DomainObjects对象集合,里面的元素分别是ApplicationVariant、LibraryVariants和TestVariants.修改它们会自动触发创建所有任务。


android{
    
    //....

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            if (output.outputFile != null && output.outputFile.name.endsWith('.apk')
                    && 'release'.equals(variant.buildType.name)){
                def flavorName = variant.flavorName.startWith("_") ? variant.flavorName.
                        substring(1) : variant.flavorName
                def apkFile = new File(output.outputFile.getParent(),
                        "Project_${flavorName}_v${variant.versionName}_${buildTime()}.apk")
            }
        }
    }

    def buildTime(){
        def date = new Date()
        def formattedDate = date.format("yyMMdd")
        return formattedDate
    }
}

applicationVariants中的variant都是ApplicationVariant,通过查看源码,可以看到它有一个outputs作为它的输出。

动态生成版本信息

version.gradle

ext{
    appVersionCode=1
    appVersionName="1.0.0"
}

build.gradle

apply from 'version.gradle'

android{

    defaultConfig{
        versionCode appVersionCode
        versionName appVersionName
    }
}

隐藏签名文件信息

对于apk的签名文件以及密码,我们存放到版本库和服务器都不是很好,所以下面将这些信息配置到本地环境变量再获取。

android{
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

        signingConfigs {

            def appStoreFile = System.getenv("STORE_FILE")
            def appStorePassword = System.getenv("STORE_PASSWORD")
            def appKeyAlias = System.getenv("KEY_ALIAS")
            def appKeyPassword = System.getenv("KEY_PASSWORD")

            release {
                storeFile file(appStoreFile)
                storePassword appStorePassword
                keyAlias appKeyAlias
                keyPassword appKeyPassword
            }
        }
    }
}

动态配置AndroidManifest文件

<meta-data android:name="CHANNEL_NAME" android:value="${CHANNEL_VALUE}" />
android{

    productFlavors{

        google{

        }

        baidu{

        }
    }

    productFlavors.all{ flavor ->
        manifestPlaceholders.put("CHANNEL_NAME", name)
    }
}

Android Gradle提供的manifestPlaceholders占位符方式,可以替换Manifest文件中任意${valu}格式的占位符。

自定义BuildConfig

BuildConfig类是Android工程自动生成的,不允许修改。

/**
 * Automatically generated file. DO NOT MODIFY
 */
package com.parkingwang.business;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.parkingwang.business";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "Appium";
  public static final int VERSION_CODE = 54001;
  public static final String VERSION_NAME = "5.4.1";
  // Fields from product flavor: Appium
  public static final boolean DISABLE_KEYBOARD = true;
  public static final boolean USING_TEST_API = true;
  // Fields from default config.
}

可以看到这里面有一些配置信息,是否debug、appid、版本号、版本名称等,如果有所变化这些配置信息都会自动修改的。

Android Gradle提供了buildConfigField(String type, String name, String value)让我们自己添加到BuildConfig中。

    /**
     * Adds a new field to the generated BuildConfig class.
     *
     * <p>The field is generated as: {@code <type> <name> = <value>;}
     *
     * <p>This means each of these must have valid Java content. If the type is a String, then the
     * value should include quotes.
     *
     * @param type the type of the field
     * @param name the name of the field
     * @param value the value of the field
     */
    public void buildConfigField(
            @NonNull String type, @NonNull String name, @NonNull String value){ //... }

这样我们就可以使用这个特点结合productFlavors来配置不同渠道下的信息。

android{

    productFlavors{

        google{
            buildConfigField 'String', 'WEB_URL', 'http://www.google.com'
        }

        baidu{
            buildConfigField 'String', 'WEB_URL', 'http://www.baidu.com'
        }
    }
}

利用这个特点我们就可以不同的渠道做一些特殊的处理。

动态自定义资源文件

res/values类型的资源文件可以在Android Gradle中定义

android{
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

    productFlavors{

        google{
            resValue 'string', 'channel_tips', 'google渠道'
        }
        baidu{
            resValue 'string', 'channel_tips', 'baidu渠道'
        }
    }
}

这样我们在工程中使用channel_tips字符串的时候就会相应的使用对应渠道的字符串内容。

除了string资源之外,还可以使用 id、bool、dimen、integer、color等资源。

Java编译选项

有的时候我们需要配置JDK的版本来使用一些新的特性,Android Gradle给我们提供了一种方便的配置方式。

android{
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

    compileOptions{
        encoding = 'utf-8'
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

adb操作配置

adbOptions有两个属性:installOptions和timeOutInMs

android{
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

    adbOptions{
        timeOutInMs = 5 * 1000 //秒
        installOptions = '-r', '-s'
    }
}

timeOutInMs是设置adb命令的超时时间,单位为毫秒。 installOptions是adb install 的可选参数。

参数含义
-l锁定该应用程序
-r替换已存在的应用程序,强制安装
-t允许测试包
-s把应用程序安装到SD卡
-d允许进行降级安装
-g为该应用程序授予所有运行时权限

DEX选项配置

dx命令是一个脚本,调用的是dx.jar,默认情况下给dx分配1024M内存。Android Gradle提供了dexOptions{ }对dx操作进行一些配置。

android{
    compileSdkVersion 27
    buildToolsVersion '28.0.3'

    dexOptions{
        incremental true
    }
}

incremental 属性是dx的增量模式,速度更快一些,有很多限制可能会不工作,所以慎用。

javaMaxHeapSize 属性解决dx时的内存不足问题,可以配置一个内存大小。

dexOptions{
    javaMaxHeapSize '4g'
}

jumboMode 属性用来配置是否开启jumbo模式,也就是65535问题(Android 5.0及以上可用)。

dexOptions{
    jumboMode true
}

preDexLibraries 属性配置是否开启执行dex Libraries库工程。

threadCount属性配置dx运行时候的线程数量。