第八章 自定义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对自己的项目进行自定义构建,以满足自己的项目需求。


目录
相关文章
|
2月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
2月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
14天前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
38 10
|
19天前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
30 3
|
20天前
|
前端开发 Android开发 开发者
安卓应用开发中的自定义视图基础
【9月更文挑战第13天】在安卓开发的广阔天地中,自定义视图是一块神奇的画布,它允许开发者将想象力转化为用户界面的创新元素。本文将带你一探究竟,了解如何从零开始构建自定义视图,包括绘图基础、触摸事件处理,以及性能优化的实用技巧。无论你是想提升应用的视觉吸引力,还是追求更流畅的交互体验,这里都有你需要的金钥匙。
|
23天前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
2月前
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。
|
2月前
|
Android开发
Android在rootdir根目录创建自定义目录和挂载点的方法
本文介绍了在Android高通平台的根目录下创建自定义目录和挂载点的方法,通过修改Android.mk文件并使用`LOCAL_POST_INSTALL_CMD`变量在编译过程中添加目录,最终在ramdisk.img的系统根路径下成功创建了`/factory/bin`目录。
83 1
|
2月前
|
Android开发
Android Studio: 解决Gradle sync failed 错误
本文介绍了解决Android Studio中出现的Gradle同步失败错误的步骤,包括从`gradle-wrapper.properties`文件中获取Gradle的下载链接,手动下载Gradle压缩包,并替换默认下载路径中的临时文件,然后重新触发Android Studio的"Try Again"来完成同步。
384 0
Android Studio: 解决Gradle sync failed 错误
|
27天前
|
前端开发 搜索推荐 Android开发
探索安卓开发中的自定义视图##
【9月更文挑战第6天】 在安卓应用开发的世界里,自定义视图如同绘画艺术中的色彩,它们为界面设计增添了无限可能。通过掌握自定义视图的绘制技巧,开发者能够创造出既符合品牌形象又提升用户体验的独特界面元素。本文将深入浅出地介绍如何从零开始构建一个自定义视图,包括基础框架搭建、关键绘图方法实现、事件处理机制以及性能优化策略。准备好让你的安卓应用与众不同了吗?让我们开始吧! ##
下一篇
无影云桌面