Gradle介绍
Gradle is an advanced build system as well as an advanced build toolkit allowing to create custom build logic through plugins.Gradle是一个先进的构建系统,也是一个允许通过插件创建自定义构建逻辑先进的构建工具。
Gradle
允许通过插件创建自定义的构建逻辑,它的一些特点:
- 采用了
Domain Specific Language(DSL语言)
来描述和控制构建逻辑。 - 构建文件基于
Groovy
,并且允许通过混合声明DSL
元素和使用代码来控制DSL
元素以控制自定义的构建逻辑。 - 支持
Maven
或者Ivy
的依赖管理。 - 非常灵活。允许使用最好的实现,但是不会强制实现的方式。
- 插件可以提供自己的
DSL
和API
以供构建文件使用。 - 良好的
API
工具供IDE
集成。
Gradle全局配置
一般我们各个module
的build.gradle
中都有这一段配置:
android {
compileSdkVersion 25
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
}
假如我们项目中有多个module
,如果升级targetSdk
等,那么每个module
都需要改值,不仅麻烦,还有可能导致module
之间的版本不统一而出现问题,解决方法是Gradle
配置全局变量供各个module
使用,在你的Project
的根目录下的build.gradle
定义ext
全局变量:
ext {
compileSdkVersion = 25
buildToolsVersion = '25.0.0'
minSdkVersion = 15
targetSdkVersion = 25
versionCode = 1
versionName = "1.0"
}
然后在各module
中的build.gradle
中引用如下:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
}
这样每次修改Project
的build.gradle
配置就可以实现全局配置了。
在release版本中关闭Log
我们在调试代码的时候希望显示Log
日志信息,但是当我们发布到应用市场的时候我们又不希望我们的应用显示Log
信息,因为这样会拖慢应用的运行速度甚至是暴露关键信息,那么该怎么办呢?可以通过配置buildTypes
来达到在release
版本中自动关闭Log
的效果:
buildTypes {
release {
minifyEnabled false
buildConfigField "boolean", "IS_SHOW_LOG", "false"
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
buildConfigField "boolean", "IS_SHOW_LOG", "true"
}
}
配置的buildConfigField
参数,编译后会在..\app\build\generated\source\buildConfig
文件夹下会自动生成对应版本对应module
的BuildConfig.java
文件,该文件可以在代码中直接使用。其实可以直接使用系统的BuildConfig.DEBUG
来判断,这里为了使用buildConfigField
,自己来控制。
- 看下上面
buildConfigField
的写法:
buildConfigField "boolean", "IS_SHOW_LOG", "true"
buildConfigField
各参数含义:
buildConfigField | 备注 |
---|---|
String type | 要创建的字段类型,如上面的boolean |
String name | 要创建的字段名,如上面的IS_SHOW_LOG |
String value | 创建此字段的值,如上面的true |
配置好上面的信息后,在项目中编写一个MyLog.java
类如下:
public class MyLog {
public static int v(String tag, String msg) {
if (BuildConfig.IS_SHOW_LOG) {
return Log.v(tag, msg);
} else {
return -1;
}
}
---------其他方法----------
}
上面对Log
类做了一层封装,根据BuildConfig.IS_SHOW_LOG
的值来决定是否打印Log
,我们在buildTypes
的release
里面配置的IS_SHOW_LOG
是false
,在debug
里面配置的IS_SHOW_LOG
是true
,这样当我们调试的时候会显示log
日志,而当我们打的是release
包的时候就会自动屏蔽了Log
。
Build Variant 管理
- buildTypes:定义了编译类型,针对每个类型可以有不同的编译配置(通常在混淆代码、可调试、资源压缩上做一些区分)。默认的有
debug、release
类型,除了这两种外还可以手动添加编译类型(如preview
)。 - productFlavors:如果针对同一个
BuildType
还想编译出多个版本(如友盟多渠道打包,根据不同的meta-data
中的值来区分不同的渠道),这时候就需要ProductFlavors
了。
所以最后可以编出的APK的个数 = BuildTypes x ProductFlavors
,即:
Build Variant = BuildTypes x ProductFlavors
- flavorDimensions:用于定义不同的产品风味维度,这些维度可以是任意的字符串标识符。而
productFlavors
则是在这些维度上定义具体的产品风味。一个产品风味可以定义应用程序的特定设置,如应用程序的名称、图标、默认配置等。示例:
android {
flavorDimensions "versionCode"
productFlavors {
free {
dimension "versionCode"
applicationId "com.example.free"
versionCode 1
versionName "1.0"
}
pro {
dimension "versionCode"
applicationId "com.example.pro"
versionCode 2
versionName "2.0"
}
}
}
上面的例子中,我们定义了一个名为 versionCode
的维度,它有两个产品风味:free
和 pro
。这两个产品风味都属于 versionCode
维度,但是它们的应用程序 ID
、版本代码和版本名称都不同。这意味着我们可以根据需要选择使用哪个产品风味来构建应用程序。
在使用 Gradle
构建系统构建应用程序时,可以使用 --variant
命令行参数来选择要构建的产品风味和构建类型。例如:
./gradlew assembleFreeDebug
./gradlew assembleProRelease
上面的命令分别选择了 freeDebug
和 proRelease
两个构建类型的不同产品风味进行构建。
通过使用 flavorDimensions
和 productFlavors
,我们可以轻松地构建多个应用程序变体,以便在不同的环境中使用不同的应用程序设置。
< meta-data >元素
在 AndroidManifest.xml
文件中,meta-data
元素用于在应用程序中添加任意键值对数据。它可以被应用程序的其他组件使用。在 meta-data
元素中,name
属性指定键的名称,value
属性指定键的值。
以下是一个示例,展示了如何在 AndroidManifest.xml
文件中使用 meta-data
元素:
<application
android:name=".MyApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--存数据 可以分别在application activity service等里面取出来,注意取的方式是不一样的-->
<meta-data
android:name="com.nine.tripods.key"
//${}是占位符,在build.gradle中赋值
android:value="${KEY_VALUE}" />
</application>
继续在build.gradle
中添加:
defaultConfig {
//......其他......
manifestPlaceholders = [KEY_VALUE: "123456"]
}
在上面的示例中,在应用程序中添加了一个 meta-data
元素。该元素的 name
属性为 "com.nine.tripods.key"
,值为 在build.gradle
中赋值的${KEY_VALUE}
,如果是固定值,可以直接写在这里。
其他组件可以使用此键值对的数据,例如,可以在应用程序的任何地方使用以下代码获取此键的值:
String apiKey = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA)
.metaData.getString("com.nine.tripods.key");
这里的 getPackageName()
和 getPackageManager()
是 Context
对象提供的方法。getApplicationInfo()
方法可以返回一个包含应用程序的各种信息的 ApplicationInfo
对象。我们可以从这个对象的 metaData
字段中获取 meta-data
元素中定义的值。
在实际开发中,meta-data
元素通常用于将应用程序与第三方服务或库集成。例如,将 Google Maps API
密钥添加到 meta-data
中,以在应用程序中使用 Google Maps
等。
注意:如果声明在Activity
下,那么取数据的方式也有点区别,如:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="com.nine.tripods.key"
android:value="1234567890" />
...
</activity>
取数据:
try {
ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
String apiKey = info.metaData.getString("com.nine.tripods.key");
// Do something with apiKey
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}