Android Gradle 高级自定义

使用共享库

Android 的包有本身就包含在Android SDK中的,系统会自动帮我们链接它们,不会出现找不到相关类的情况。此外,还有一些库,比如 com.google.andorid.maps,android.test.tunner 等独立的库,它们并不会被系统自动链接,所以我们如果要使用它们的话,就需要单独进行生成使用,这些库被称为共享库
我们可以在AndroidManifest 文件中,指定要使用的库。如,我们要声明需要使用 maps 这个共享库:

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

声明之后,在安装生成的APK包的时候,系统就会根据我们的定义,帮助检测手机系统是否有我们需要的共享库,如果系统不满足,将不能安装该应用。

在Android中,除了标准的SDK,还存在两种库。:一种是add-ons库,位于add-ons 目录下,大都为第三方厂商开发;一种是optional可选库,它们位于 platforms/android-xx/optional 目录下,一般是为了兼容旧版本的 API ,比如 org.apache.http.legacy ,这是一个 HttpCilent 库,从API 23开始,标准SDK中就不再包含 HttpClient 库,如果还想使用该库,就必须使用这个可选库。

对于第一种库来说,Android Gradle 会帮我们自动解析,帮我们添加到 classpath 里,但第二种库就不会了,我们需要使用useLibrary方法手动添加。

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

动态配置 AndroidManifest 文件

动态配置 AndroidManifest 文件,顾名思义,就是在构建过程中修改 AndroidManifest 文件中的一些内容。如:在生成不同渠道包的时候为其指定不同的渠道名。对于这种情况,Android Gradle 提供了非常便携的方法让我们来替换 AndroidManifest 文件中的内容,即manifestPlaceholder,Manifest 占位符。
manifestPlaceholderProductFlavors的一个属性,是一个map类型,因此我们可以同时配置多个占位符。
下面我们以定义 Google 和 Baidu 两个渠道举例:

android{
	complieSdkVersion 23
	buldToolsVersion "23.0.1"

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

我们使用的key是一样的,它就是在 AndroidManifest 文件中的占位符变量。在构建的时候,它会把 AndroidManifest 文件中所有占位符变量为 UMNENG_CHANNEL 的内容替换为 manifestPlaceholders 中对应的 value值,我们只需直接引用对应key即可。

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

如果渠道过多,我们可以通过迭代productFlavors批量的方式进行修改:

android{
	complieSdkVersion 23
	buildToolsVersion "23.0.1"

	productFlavors{
		google{}
		baidu{}
	}

	productFlavors.all { flavors ->
		manifestPlaceholders.put("UMENG_CHANNEL", name)
	}
}

我们通过all 函数遍历每一个 productFlavor ,然后把它们的name作为渠道名。当然,manifestPlaceholders的使用场景绝不限于渠道名这一个,比如还有ContentProvider 的 auth 的授权,或者其他动态配置meta信息等,灵活运用它能帮助我们做很多事情。

自定义 BuildConfig

BuildConfig 这个类是由 Android Gradle 构建脚本在编译后自动生成的,默认情况下一般是这样的:

pubilc final class BuildConfig {
	//打包模式
	pubilc static final boolean DEBUG = Boolean.parseBoolean("true");
	//包名
	pubilc static final Sting APPLICATION_ID = "..."
	//构建类型
	pubilc static final Sting BUILD_TYPE = "debug"
	//构建的渠道
	pubilc static final Sting FLAVOR = "baidu"
	//版本号
	pubilc static final int VERSION_CODE = 1;
	//版本名称
	pubilc static final Sting VERSION_NAME = "1.0.0"
}

DEBUG 这个常量需要介绍一下,一般在开发过程中都会输出日志进行调试,一般只有在我们自己开发中才会打印出日志,当我们发布后就不能打印日志了,我们就需要一个标记是debug模式还是release模式的开关,这就是 BuildConfig.DEBUG。在debug模式下它的值为true,而在release模式下会变为false,Gradle 会自动生成、修改。

既然这个BuildConfig这么好用,我们可不可以自己定义、新增些常量呢?答案当然是可以的。对此, Android Gradle 提供了 buildConfigField(String type, String name, String value),让我们可以添加自己的常量到 BuildConfig 中。

最终生成的字段格式如下:

<type> <name> = <value>;

举个例子:

android {
	buildTypes {
		debug {
			buildConfigField 'String','NAME','"value"'
		}
	}
}

自定义BuildConfig非常灵活,可以根据不同的渠道,不同的构建类型来灵活配置APP。

动态添加自定义的资源

Android 开发会用到在res文件夹定义的资源,在工程里引用即可使用。本节我们讲的自定义资源,是专门针对 res/values 类型资源的,它们不止能在 res/values 文件夹里使用 xml 的方式定义,还可以在 Android Gradle 中定义。

实现此功能的是 resValue 方法,它在 BuildType 和 ProdctFlavor 这两个对象中都存在,也就是说我们可以分别针对不同的渠道,或者不同的构建类型来自定义其特有的资源。以 resValue 方法为例。

resValue 方法会添加生成一个资源,效果与在 res/values 文件中定义一个资源是等价的。

该方法有 3 个参数,第一个是 type ,即定义的资源类型,如:string , id , bool 等;第二个是 name,也就是你要定义资源的名称,以便我们在工程中引用它;第三个是 value ,即定义资源的值。

android {
	...
	//该方法当然也可以在 buildType 中使用
	productFlavors {
		google {
			 resValue 'string','channel_tips','google 渠道欢迎你'
		}
		baidu {
			 resValue 'string','channel_tips','baidu渠道欢迎你'
		}
	}
}

当使用该方法时, Android Gradle 帮我们生成的资源在 build/gengerated/res/resValues/baidu/debug/values/generated.xml中。

DEX 选项配置

Android 中的Java源代码被编译成 class 字节码后,在打包成 apk 的时候又被 dx 命令优化成 Android 虚拟机可执行的 dex 文件。dx 命令的处理,Android Gradle 已经帮我们处理好了,但有时可能会遇到 OOM 错误。为什么会提示内存不足呢?因为 dx 命令只是一个脚本,它调用的还是 Java 编写的 dx.jar 库,是Java 程序处理的。dx 的默认内存是1Gb,即1024Mb。

android {
	...
	dexOptions{
		//增量模式
		incremental true
		// 最大内存
		javaMaxHeapSize = '4g'
		// jumbo 模式
		jumboMode true
		// 是否预执行dex Libraries 库工具
		preDexLibrary true
		// 运行 dx 命令的线程数
		threadCount 2
	}
}

突破 65535 方法限制

由于Dalvik虚拟机在执行DEX文件的时候,使用了short这个类型来索引DEX文件中的方法,导致单个DEX文件可以被定义的方法最多只能是65535个,当我们定义的方法超过这个数量时,就会出现错误提示信息。

Android 5.0给出了解决方案,即 MultidexART 虚拟机可以支持多个DEX文件在安装APP的时候执行预编译,将多个DEX文件合并成一个oat文件执行。

android {
	...
	defaultConfig{
		//启用multidex
		multiDexEnabled true
	}
}
dependencies {
	compile fileTree(dir:'libs, include:['*.jar'])
	compile 'com.android.support:multidex:1.0.1'
}

其他方法:插件化

自动清理未使用的资源

方法一:自行寻找,手动删除
方法二:使用Android Lint 检测,手动删除
方法三:Resource Shrinking(打包成APK前,检测所有资源是否被引用,如果没有将不打进APK包中) + Code Shrinking(清理无用代码)

keep 方法配置XX资源不被清理
resConfig 只要需要的资源

其他

批量修改生成的 APK 文件名

如要修改生成的 APK 文件名,就要了解这几个属性:
applicationVariants , libraryVariants , testVariants

动态生成版本信息

四种方法:配置在build中,分模块配置,从git tag中获取,从属性文件(version.gradle)中动态获取和递增

隐藏签名信息

将签名信息和密钥放在服务器中

Java 编译选项

android {
	...
	
	compileOptions {
		encoding = 'utf-8'
		// Java 源代码的编译级别
		sourceCompatibility = JavaVersion.VERSION_1_8
		// 生成Java 字节码的版本
		targetCompatibility = JavaVersion.VERSION_1_8
	}
} 

adb 操作选项配置

android {
	...
	
	adbOptions{
		//设置超时时间 --  CommondRejectException
		timeOutInMs = 5*1000 //秒
		// -l : 锁定该应用程序 lock
		// -r : 替换已存在的应用程序 replace
		// -t : 允许测试包 test
		// -s : 将APP安装到 SD 卡上 sdcard
		// -d : 允许APP降级安装 degrade
		// -g : 为该应用授予所有运行时权限 god
		intallOptions '-r','-s'
	}
} 

参考文章:
《Android Gradle 权威指南》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值