【Android】使用Gradle进行配置
Jan 14, 2016 · 3 minute read · Comments开发android
【Android】使用Gradle进行配置(记录)
摘要
- 介绍
- 需求
- 配置工程
概念介绍
直接推荐几篇文章入门。
ADT已经不在继续更新了。自然而然的,Android Studio成了新贵。虽说还是有一些别的IDE和别的方式去编写和构建Android,但由于谷歌的维护和升级,AS成了绝大多数Android开发者的选择。对于小团队来说(本人就是在小小小团队),AS + GRADLE 成了现阶段主流。
这是记录,所以概念型的东西就不做介绍了。
需求
由于团队本身有好多服务器(*开发,灰度,线上*),再加上有很多三方的引用(如:我们团队IM引用了环信),另外还有一些日志系统的调控等,再加上长时间不同人员对代码开发,导致这些配置非常混乱,散落于不同的类,还有一些在AndroidManifies.xml
等文件中,所以导致导报经常会出现一些莫名其妙的错误。
需求:实现 > 能合理地配置这些,并使用配置文件进行统一管理 >的需求。
目标如下:
- 只需更改一处(一行)就能实现不同需求打包的切换!(最重要)
- 简单
- 不影响Studio相关联的
gradle
文件(build.gradle
一旦改变,就会导致重新编译),但又可以及时更改相关配置。
配置工程
配置BuildConfig
BuildConfig
这个类是工程自动构建生成的。可以具体看一下这个类。
/**
* Automatically generated file. DO NOT MODIFY
*/
package ****;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "**.builddemo";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
}
注释说:这个类是自动生成的,别动,动了也没什么用~~~
然后可以看到,这里DEBUG
,APPLICATION_ID
,BUILD_TYPE
,FLAVOR
,VERSION_CODE
,VERSION_NAME
这些常量,这些常量有的是我们在AndroidManifest.xml
中配置的,有些是我们在module下的build.grade
中配置的(当然,这些其实全部可以在build.gradle
中进行配置)
就像这个样子:
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "**.builddemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard- rules.pro'
}
}
productFlavors {
}
}
由于工程中需要versionCode
参数,所以BuildConfig
便提供了很大的便利。
Tip: defaultConfig{} 这个闭包就是配置工程参数的,也就是直接对应
BuildConfig
的
既然如此,如果能给BuildConfig
配置自定义的参数,那么需求就解决了一半了!
显然,Android团队也肯定会留下一些自定义的API,保证大家能 “ 随便乱搞”。
下面是自定义API写法和使用
defaultConfig {
...
// 自定义的方法就是 buildConfigField ,这种是groovy写法
// 三个参数分别是 type (类型) , name (命名) , value(值)
buildConfigField 'int' , 'SEVER_CONFIG' , "1"
// 当然写成这种更容易看懂,这种写法更像java。
// 三个参数分别是 type (类型) , name (命名) , value(值)
buildConfigField("int" , "SEVER_CONFIG" , "1")
}
重新构建后,可以看到
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "**.builddemo";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from default config.
public static final int SEVER_CONFIG = 1;
}
可以看到int SEVER_CONFIG = 1;
正好对应 'int' , 'SEVER_CONFIG' , "1"
注意, “1” 对应的是 1 , ’ “1” ‘ 对应的是 “1”
是不是很简单。
简单看一下原理吧。
原来是本身构建的时候,android会将闭包转化成相关类,并调用方法。可以看一下buildConfigField
这个方法
// -- DSL Methods. TODO remove once the instantiator does what I expect it to do.
/**
* Adds a new field to the generated BuildConfig class.
*
* The field is generated as:
*
* <type> <name> = <value>;
*
* 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) {
ClassField alreadyPresent = getBuildConfigFields().get(name);
if (alreadyPresent != null) {
String flavorName = getName();
if (BuilderConstants.MAIN.equals(flavorName)) {
logger.info(
"DefaultConfig: buildConfigField '{}' value is being replaced: {} -> {}",
name, alreadyPresent.getValue(), value);
} else {
logger.info(
"ProductFlavor({}): buildConfigField '{}' "
+ "value is being replaced: {} -> {}",
flavorName, name, alreadyPresent.getValue(), value);
}
}
addBuildConfigField(AndroidBuilder.createClassField(type, name, value));
}
这是ProductFlavor
这个类里的方法,不详细说了,大家其实直接看注释就ok了。
解决AndroidManifest.xml
的Meta-data
等
拿AndroidManifest.xml
的Meta-data
出来说,其实别的字段也是一样的。
还是build.gradle
中的配置
defaultConfig {
applicationId "zhulonglong.builddemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
buildConfigField 'int' , 'SEVER_CONFIG' , "1"
manifestPlaceholders = [ CHANNEL_VALUE : "QQ" ]
}
对应的AndroidManifest.xml
的Meta-data
数据是
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<meta-data android:name="CHANNEL"
android:value="${CHANNEL_VALUE}"/>
</application>
${}
是替代符,在defaultConfig
中manifestPlaceholders
便是对应的AndroidManifest.xml配置文件。
合并,新建config.gradle
统一管理所有的配置
创建一个config.gradle
的好处:
- 无缝衔接
gradle
构建系统 - android studio 方便查看更改,且不会引起重新构建(IDE 自动识别的都是
build.gradle
文件,对于别的gradle文件不会在乎)
我创建的config.grade
是在项目根录下的。
def DEV = 0
def ONLINE = 2
ext{
SEVER_CONFIG = ONLINE
CHANNEL_DEV = "CHANNEL_DEV"
CHANNEL_ONLINE = "CHANNEL_ONLINE"
if (SEVER_CONFIG == DEV){
CHANNEL_NAME = CHANNEL_DEV
}else {
CHANNEL_NAME = CHANNEL_ONLINE
}
}
ext
保证了别的gradle
能顺利使用这个属性
在需要的build.gradle
中导入config.gradle
。
apply from: rootProject.getRootDir().getAbsolutePath() + "/config.gradle"
println "Project Name " + getName()
println "Project Path " + getPath()
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "**.builddemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
buildConfigField 'int' , 'SEVER_CONFIG' , "${SEVER_CONFIG}"
manifestPlaceholders = [ CHANNEL_VALUE : "${CHANNEL_NAME}" ]
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
然后就可以直接引用这个属性了。
如:
buildConfigField 'int' , 'SEVER_CONFIG' , "${SEVER_CONFIG}"
SEVER_CONFIG
就是在config.gradle
中定义的。
到此为止,目的达到了。
所有的配置都在文件config.gradle
中进行更改。当然,还需要在里面定义一个总开关,将具体参数配置分块。
在代码中可以直接使用BuildConfig
进行相关使用。
当然,更改config.gradle
不会进行重新构建,是不是棒棒哒!!!