第八章 自定义Android Gradle工程

简介: Android Gradle为我们提供了大量的DSL,我们使用这些DSL定义配置我们的工程以满足我们项目中不同的需求。这些DSL有很多,在上一章演示Android Gradle工程示例的时候,我们已经大概介绍了compileSdkVersion、buildToolsVersion以及defaultConfig等,这一章我们再详细介绍一些常用的DSL配置,这些配有有签名信息、构建类型、代码混淆、zipAlign对齐压缩等。

Android Gradle为我们提供了大量的DSL,我们使用这些DSL定义配置我们的工程以满足我们项目中不同的需求。这些DSL有很多,在上一章演示Android Gradle工程示例的时候,我们已经大概介绍了compileSdkVersion、buildToolsVersion以及defaultConfig等,这一章我们再详细介绍一些常用的DSL配置,这些配有有签名信息、构建类型、代码混淆、zipAlign对齐压缩等。


8.1 defaultConfig默认配置


defaultConfig是android对象中的一个配置块,负责定义所有的默认配置,它是一个ProductFlavor,如果一个ProductFlavor没有被特殊定义配置的话,默认就会使用defaultConfig{}块指定的配置,比如包名、版本号、版本名称等。


一个基本上的defaultConfig配置如下:


image.png

以上示例配置了Android 开发的基本信息,可以满足一个基本的Android App开发,下面我们对它的一些配置进行一个详细的说明。


8.1.1 applicationId


applicationId是ProductFlavor的一个属性,用于指定生成的App的包名,默认情况下是null,这时候在构建的时候,会从我们的AndroidManifest.xml文件中读取,也就是我们在AndroidManifest.xml文件中配置的manifest标签的package属性值。


8.1.2 minSdkVersion


minSdkVersion是ProductFlavor的一个方法,对应的方法原型是

public void minSdkVersion(int minSdkVersion) {
        this.setMinSdkVersion(minSdkVersion);
    }


它可以指定我们的App最低支持的Android 操作系统版本,其对应的值是Android SDK的API LEVEL,根据这里的方法原型,它接受的值是一个整数,除此之外,它还有以下两种方法原型定义:


image.png


根据我们前面讲的Gradle知识,发现minSdkVersion也是一个属性,它也可以接受一个字符串作为它的值,在这里明确一下,这个字符串不是我们SDK API LEVEL的字符串形式,而是Code Name,也就是我们的每个Android SDK或者说是Android OS的代号。就是我们新闻上经常见到的什么‘冰激凌三明治’什么的。这里给出一个列表,让大家一目了然。


image.png


8.1.3 targetSdkVersion


这个用于配置我们基于哪个Android SDK开发,它的可选值和minSdkVersion一样,没有配置的时候也会从AndroidManifest.xml文件中读取,参考minSdkVersion的介绍,这里就不多做介绍了。


8.1.4 versionCode


它也是ProductFlavor的一个属性,用于配置Android App的内部版本号,是一个整数值,通常用于版本的升级。没有配置的时候从AndroidManifest.xml文件中读取,建议配置。其方法原型是

public class DefaultProductFlavor extends BaseConfigImpl implements ProductFlavor {
    ...
    public ProductFlavor setVersionCode(Integer versionCode) {
        this.mVersionCode = versionCode;
        return this;
    }
    public Integer getVersionCode() {
        return this.mVersionCode;
    }
    ...
}


8.1.5 versionName


versionName和versionCode类似,也是ProductFlavor一个属性,用于配置Android App的版本名称,比如V1.0.0等等,主要显示用,让用户或者市场知道我们的Android App版本,它和versionCode一个是外部用,一个是内部使用,一起配合完成Android App的版本控制,其方法原型是


public ProductFlavor setVersionName(String versionName) {
        this.mVersionName = versionName;
        return this;
    }
    public String getVersionName() {
        return this.mVersionName;
    }


8.1.6 testApplicationId


用于配置测试App的包名,默认情况下是applicationId + “.test”,一般情况下默认即可,它也是ProductFlavor的一个属性,方法原型是

public ProductFlavor setTestApplicationId(String applicationId) {
        this.mTestApplicationId = applicationId;
        return this;
    }
    public String getTestApplicationId() {
        return this.mTestApplicationId;
    }


8.1.7 testInstrumentationRunner


用于配置单元测试时使用的Runner,默认使用的是android.test.InstrumentationTestRunner,如果你想使用自己自定义的Runner,修改这个值即可,它也是一个属性,其方法原型是

public ProductFlavor setTestInstrumentationRunner(String testInstrumentationRunner) {
        this.mTestInstrumentationRunner = testInstrumentationRunner;
        return this;
    }
    public String getTestInstrumentationRunner() {
        return this.mTestInstrumentationRunner;
    }


8.1.8 signingConfig


配置默认的签名信息,用对生成的App签名,它是一个SigningConfig,也是ProductFlavor的一个属性,可以直接对其进行配置,其方法原型是

public SigningConfig getSigningConfig() {
        return this.mSigningConfig;
    }
    public ProductFlavor setSigningConfig(SigningConfig signingConfig) {
        this.mSigningConfig = signingConfig;
        return this;
    }


8.1.9 proguardFile


用于配置App ProGuard混淆所使用的ProGuard配置文件,它是ProductFlavor的一个方法,接受一个文件作为参数。其方法原型为

public void proguardFile(Object proguardFile) {
        this.getProguardFiles().add(this.project.file(proguardFile));
    }


可以看到它可以被调用多次,调用一次添加一个,其参数被project.file方法转换为一个文件对象。其具体使用我们在稍后进行介绍。


8.1.10 proguardFiles


这个也是配置ProGuard配置文件,只不过它可以同时接受多个配置文件,因为它的参数是一个可变类型的参数。

public void proguardFiles(Object... files) {
        Object[] var2 = files;
        int var3 = files.length;
        for(int var4 = 0; var4 < var3; ++var4) {
            Object file = var2[var4];
            this.proguardFile(file);
        }
    }


从方法实现我们可以看到,同时可以添加多个ProGuard配置,在实际情况下中可以选择不同的配置方式。


8.2 配置签名信息


一个App只有被签名之后才能被发布、安装、使用,签名是保护App的方式,标记该App的唯一性,如果App被恶意篡改,签名就不一样了,就无法升级安装,一定程度上也保护了我们的App。


要对App进行签名,你先得有一个签名证书文件,这个文件被开发者持有,我们这里假设你已经有生成的证书,不对证书的生成进行介绍了。


一般我们的App有debug和release两种模式(下面会将构建类型),在我们开发调试的时候使用的是debug模式,发布的时候使用release模式;我们可以针对这两种模式采用不同的签名方式,一般debug模式的时候,Android SDK已经为我们提供了一个默认的debug签名证书,我们可以直接使用,但是发布的时候,release模式构建时,我们要配置使用自己生成的签名证书。


对于签名信息的配置,Android Gradle为我们提供了非常简便的方式,让我们可以非常容易的配置一个签名信息以供调用。


image.png


Android Gradle为我们提供了signingConfigs{}配置块便于我们生成多个签名配置信息。signingConfigs是android的一个方法,它接受一个域对象作为其参数,前面我们讲过的,其类型是NamedDomainObjectContainer<SigningConfig>,这样我们在signingConfigs{}块中定义的都是一个SigningConfig。一个SigningConfig就是一个签名配置,其可配置的元素如下:


  • storeFile 签名证书文件


  • storePassword 签名证书文件的密码


  • storeType 签名证书的类型


  • keyAlias 签名证书中密钥别名


  • keyPassword 签名证书中该密钥的密码


例子中我们定义配置了一个名为release的签名配置,除此之外,我们还可以配置多个不同的签名前置,比如我们添加一个debug的配置。


image.png


默认情况下,debug模式的签名已经被配置好了,使用的就是Android SDK自动生成的debug证书,它一般位于$HOME/.android/debug.keystore,其Key和密码都是已知的,一般情况下我们不需要单独配置debug模式的签名信息。


现在我们配置好了两个签名信息,但是他们还没有被使用,现在只是生成了两个SigningConfig的实例,一个变量名为release,一个为debug,如果要使用他们我们只需引用他们即可,比如在8.1.8节中我们讲配置默认的签名信息,现在我们就可以引用debug的配置信息使用。


image.png


可以看到我们在defaultConfig中对签名配置的应用这里的signingConfigs是android对象实例的一个属性,对应是getSigningConfigs(),debug就是我们上面创建的签名配置名称。


除了上面的默认签名配置之外,我们也可以对构建的类型分别配置签名信息,比如我上面说的debug模式配置debug的签名信息,release默认配置release的签名信息。


image.png


如果你还有其他类型,想为其配置单独的签名,也可以这么做,比如付费版的VIP,单独进行签名配置、特别的渠道包单独配置等等。


8.3 构建的应用类型


关于构建类型,前面的章节我们已经用到了一些,在Android Gradle工程中,Android Gradle已经帮我们内置了debug和release两个构建类型,他们两种模式的只要差别在于能否在设备上调试以及签名不一样,其他代码和文件资源都是一样的,一般情况下也够用了。


如果想增加新的构建类型,在buildTypes{}代码块中继续添加元素就好了。buildTypes和signingConfigs一样,也是android的一个方法,接受的参数也是一个域对象NamedDomainObjectContainer<BuildType>,添加的每一个都是BuildType类型,所以你可以使用BuildType提供的方法和属性对现有的BuildType配置,这里列举一些常用的配置。


8.3.1 applicationIdSuffix


applicationIdSuffix是BuildType的一个属性,用于配置基于默认applicationId的后缀,比如默认defaultConfig中配置的applicationId为org.flysnow.app.example82,我们在debug的BuildType中指定applicationIdSuffix为.debug,那么构建生成的debug apk的包名就是org.flysnow.app.example82.debug。其方法原型为

public BaseConfigImpl setApplicationIdSuffix(String applicationIdSuffix) {
        this.mApplicationIdSuffix = applicationIdSuffix;
        return this;
    }


8.3.2 debuggable


debuggable也是BuildType的一个属性,用于配置是否生成一个可供调试的Apk。其值可以为true或者false。其方法原型为

public BuildType setDebuggable(boolean debuggable) {
        this.mDebuggable = debuggable;
        return this;
    }


8.3.3 jniDebuggable


jniDebuggable和debuggable类似,也是BuildType的一个属性,用于配置是否生成一个可供调试Jni(C/C++)代码的Apk。接受boolean类型的值


8.3.4 minifyEnabled


也是BuildType的一个属性,用于配置该BuildType是否启用Proguard混淆,接受一个boolean类型的值

8.3.5 multiDexEnabled


也是BuildType的一个属性,用于配置该BuildType是否启用自动拆分多个Dex的功能,一般用于代码太多,超过了65535个方法的时候,进行的拆分为多个Dex的处理,后面会详细讲使用。接受一个boolean类型的值

8.3.6 proguardFile


是BuildType的一个方法,用于配置Proguard混淆使用的配置文件,和前面讲的defaultConfig中的proguardFile一样


8.3.7 proguardFiles


是BuildType的一个方法,用于配置Proguard混淆使用的配置文件,该方法可以同时配置多个Proguard配置文件

8.3.8 shrinkResources


是BuildType的一个属性,用于配置是否自动清理未使用的资源,默认为false.

这是一个非常有用的功能,我们在后面的章节会详细介绍。


8.3.9 signingConfig


配置该BuildType使用的签名配置,前面已经讲过,可以参考8.2章节温习一遍。


每一个BuildType都会生成一个SourceSet,默认位置为src/<buildtypename>/,根据我们以前讲的知识,一个SourceSet包含源代码、资源文件等信息,在Android中就包含了我们的java源代码,res资源文件以及AndroidManiftest文件等,所以针对不同的BuildType,我们可以单独的为其指定Java源代码,res资源等,只要把他们放到src/<buildtypename>/下相应的位置即可,在构建的时候,Android Gradle会优先使用他们代替我们main下的相关文件。


另外需要注意,因为我们的每个BuildType都会生成一个SourceSet,所以新增的BuildType名字一个要注意,不能是main和androidTest,因为他们两个已经被系统占用,同事每个BuildType之间名称不能相同。


除了会生成对应的SourceSet外,每一个BuildType还会生成相应的assemble<BuildTypeName>任务,比如我们常用的assembleRelease和assembleDebug就是Android Gradle自动生成的两个Task任务,他们是release和debug这两个BuildType自动创建生成的。执行相应的assemble<BuildTypeName>任务,就能生成对应BuildType的所有Apk。


8.4 使用混淆


代码混淆是一个非常有用的功能,它不仅可能优化我们的代码,让我们的Apk包变得更小,还可以混淆我们原来的代码,让反编译的人不容易看明白我们业务逻辑,很难分析。一般情况下我们发布到市场的版本一定是要混淆的,也就是我们的release模式编译的版本,但是我们自己调试的版本不用混淆,因为混淆后就无法断点跟踪调试了,也就是我们的debug模式。


要启用混淆,我们把BuildType的属性minifyEnabled的值设置为true即可。


现在我们启用了混淆,但是Android Gradle还不知道按何种规则进行混淆,不知道要保留哪些类不混淆,要做到这些就需要我们的Proguard配置文件了,现在我们为我们的混淆指定配置文件。


根据我们8.3小结讲的知识,指定Proguard配置文件我们可以使用proguardFile方法,也可以使用proguardFiles方法,这个根据情况而定,看你是想指定一个还是想同时指定多个。


这里我们注意到,使用了一个getDefaultProguardFile方法,该方法是android实例的一个方法,全限定写法可以这样android.getDefaultProguardFile,它的作用是获取我们Android SDK安装目录中,Android为我们提供的默认Proguard混淆配置文件,路径是Android SDK安装目录下的tools/proguard文件夹中,我们看下该方法的原型


image.png


从实现中看,我们只需传递一个文件名给这个方法,他就会返回tools/proguard目录下的该文件的绝对路径。


Android SDK默认为我们提供了两个Proguard配置文件,他们分别是proguard-android.txt和proguard-android-optimize.txt,一个是没有优化的,一个是优化的,你可以根据情况自己选择,当然你也可以都不用,全部自己定义,自己定义的时候可以参考Proguard官方网站文档,查看相关配置说明,网址为 http://proguard.sourceforge.net/


除了在BuildType中启用混淆和配置混淆外,我们也可以在defaultConfig中启用和配置,还记得我们前面在8.1章节讲的吧,因为这个是默认配置,一般用的比较少


我们还可以针对个别渠道,启用和配置Proguard混淆,多渠道包是通过productFlavors配置的,productFlavors是一个NamedDomainObjectContainer<ProductFlavor>域对象,其配置的渠道本质上就是一个ProductFlavor,和defaultConfig是一样的,所以每个渠道也可以单独的启用和配置Proguard混淆。


8.5 启用zipalign优化


zipalign是Android为我们提供的一个整理优化Apk文件的工具,它能提供系统和应用的运行效率,更快的读写Apk中的资源,降低内存的使用,所以对于我们要发布的App,在发布之前一定要使用zipalign进行优化


Android Gradle为我们提供了开启zipalign优化更简便的方式,我们只需要配置开启即可,剩下的操作,比如调用SDK目录下的zipalign工具进行处理等,Android Gradle会帮我们搞定。要为我们的release模式开启zipalign优化的话,只需进行如下配置即可。

zipAlignEnabled是BuildType的一个属性,接受一个boolean类型的值.


8.6 小结


这一章对我们Android Gradle常用的DSL做了详细的讲解说明,并且尽可能对常用的属性方法配置也进行了详细的说明,同时配有每个属性和方法的源代码实现,让大家对这些配置有个更深的认识。大家可以灵活的使用这些DSL对自己的项目进行自定义构建,以满足自己的项目需求。


目录
相关文章
|
1月前
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
1月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
41 3
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
86 0
|
18天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
20天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
30 5
|
1月前
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
1月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
1月前
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
81 0
玩转安卓之配置gradle-8.2.1
|
2月前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
62 10
|
2月前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
46 3