文章目录
compileSdkVersion,targetSdkVersion,minSdkVersion
compileSdkVersion ; 表示应用程序编译的时候使用的SDK版本
minSdkVersion : 应用程序支持的最低的SDK版本
targetSdkVersion: 目标软件开发版本。表示创建的Android项目使用哪个API版本:
- targetSDKVersion作用:
高版本手机兼容低版本apk: 当你的targetSDKVersion=20时,当运行在系统10.0,SDK_INT=29的设备上时,调用SDK 20的版本API,及时当前10.0手机的特性已经改变,但是还是运行SDK20的API。
一般情况下:minSdkVersion <= targetSdkVersion <= compileSdkVersion
打包语言
gradle打包使用的是Groovy语言,GroovyAPI参考文档:Groovy文档
在AOP,构建渠道包,热修复,插件化时,groovy都有着重要的作用。
在Android Studio中可以使用 Tools->Groovy Console 来调试项目中的groovy语言。
Groovy写法:
def a = "groovy test"
println(a)
def input = 'input'
def d = test(input)
println(d)
def test(input) {
println("test function ${input}")
return 1;
}
// 输出
groovy test
test function input
1
对比Groovy和java的写法,有以下几点区别:
- groovy结尾不需要分号
- 变量类型和方法返回类型可以省略,def 可以推断出来
- 字符串可以使用单引号,也可以使用双引号包裹起来
在使用Groovy语言进行编写的时候,对一些日常通用的类,String,List,Map等,Java有的方法它都有,在使用的时候可以参考该类的api - groovy可以使用java的所有的库
编译命令
- gradlew查看命令帮助:gradlew -help:显示帮助信息,即会打印可选参数及参数说明信息
- 编译debug包:./gradlew assembleDebug
编译release包:./gradlew assembleRelease
上面的代码中可以分别加上clean参数,./gradlew clean XXX这样会清除工程目录下的build文件夹 - gradlew installDebug 编译并安装debug包
-P 增加参数
- gradlew编译的时候增加参数:-P -P后面就是我们携带的参数及它的值
./gradlew assembleDebug -Pcustom=true
// 可以在代码中使用下面的方式获取
if (project.hasProperty('custom')&& "true"==project.getProperty("custom")){
// buildConfigField可以在BuildConfig类中
buildConfigField("boolean", "custom", custom)
}else{
buildConfigField("boolean", "custom", "false")
}
-D, --system-prop
Sets a system property of the JVM, for example -Dmyprop=myvalue.
如果在 gradle 中需要读取 -D 携带的参数,可以使用下面的方式去读取
def customProperty = System.getProperty("myCustomProperty")
if (customProperty != null) {
println "Custom property value: $customProperty"
} else {
println "Custom property is not set."
}
-x , --exclude-task
You can exclude a task from being executed using the -x or --exclude-task command-line option and providing the name of the task to exclude:
gradlew编译中增加-x参数,不执行特定的task
- -x, --exclude-task Specify a task to be excluded from execution.
项目中的gradle文件
gradle文件是一个脚本文件,文件中的内容会按照顺序执行,一个项目中的多个.gradle文件也会按照先后顺序执行。
Android项目中会有多个gradle配置文件
- settings.gradle作为全局的配置文件,项目最开始构建的时候,会读取文件中的配置,我们可以在这里面进行一些全局参数的配置,开关的配置等
- 外层的build.gradle也就是项目的配置脚本,模块中的build.gradle也就是子模块的配置
分别在.gradle文件中加入println语句可以得到下面的输出:
settings 开始配置
settings 结束配置
> Configure project :
根 build.gradle开始
根 build.gradle结束执行
> Configure project :app
模块 build.gradle开始
模块 build.gradle结束
可以得到执行顺序为settings.gradle->根build.gradle->模块build.gradle
使用Task
task hello() {
//可以使用 dependsOn 指定这个task执行的时候所依赖的task,这里表示hello task在执行的时候会先执行clean task
dependsOn(clean)
//将给定的闭包 添加到此task操作链表的开头
doFirst {
println "hello task doFirst"
}
//配置阶段就会输出这行打印
println "hello world"
doLast {
println "hello task doLast"
}
}
编写一个hello名称的task,task中的doFirst方法将在task的最开始执行,doLast方法将在task的最后执行,文档
gradle DSL中DSL的含义Domain Specific Language 的缩写,既领域专用语言,只用于打包构建。
编写Gradle脚本代码
创建一个buildSrc模块,该目录是Android 官方插件默认的脚本模块名称,将模块中的其它内容删除,
目录中只留下下面红框中的几个文件
buildGradle文件中的内容替换为:
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
}
apply {
plugin 'groovy'
plugin 'java-gradle-plugin'
}
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation "commons-io:commons-io:2.6"
}
如果报错‘buildSrc‘ cannot be used as a project name as it is a reserved name 将settings.gradle中的include ":buildSrc"这一行删除
然后我们可以在groovy目录添加对应的代码,编写相应的脚本。
渠道包
下面的代码可以用来构建apk的变体:
主要是使用productFlavors实现构建,productFlavors中增加我们每一个产品的配置,对应的会有fiavorNameDebug,flavorNameRelease两种构建方式:
// 指定flavorDimensions为channel
flavorDimensions "channel"
// 渠道包
productFlavors {
// 根据每一个产品可以配置相应的
free {
dimension "channel"
//程序包名
applicationId "com.example.androidstart"
//替换清单文件中的标签
manifestPlaceholders = [
APP_ICON: "@mipmap/ic_launcher",
APP_NAME: "xx免费版",
]
//versionName
versionName "2.0.0"
//versionCode
versionCode 2
}
vip {
...
}
}
如果右manifestPlaceholders进行替换的话,manifest中要修改需要替换的字符串为gradle中的变量:
android:icon="${APP_ICON}"
android:label="${APP_NAME}"
通过获取构建变体的集合根据构建的产品增加对应的变量控制和产物名称修改:
// 根据不同的构建变体
applicationVariants.all { variant ->
// 获取构建变体的flavor名称
switch (variant.flavorName) {
case 'free':
buildConfigField("String", "BASE_URL", "\"http://31.13.66.23\"")
buildConfigField("String", "TOKEN", "\"dhaskufguakfaskfkjasjhbfree\"")
break
case 'vip':
buildConfigField("String", "BASE_URL", "\"http://31.13.66.24\"")
buildConfigField("String", "TOKEN", "\"dhaskfagafkjasjhbvip\"")
break
}
// 修改产物的名称
variant.outputs.all {
def type = variant.buildType.name
def channel = variant.flavorName
outputFileName = "demo_${variant.versionName}_lxd_${channel}_${type}.apk"
}
}
buildConfigField向BuildConfig中放置了相对应的变量。
如果不同的变体有不同的资源,可以创建对应的app/src/flavorName/assets,app/src/flavorName/src,app/src/flavorName/res,只要切换整个项目的Build Varient就会切换项目整体的变体依赖(Android studio左下角->Build Varients),这样在构建的时候就会拿到对应变体的资源,代码。
如果默认的变体依赖方式不满足,可以在sourceSets中进行相应的配置,修改资源路径,代码路径:
// 指定文件目录结构
sourceSets {
main {
java.srcDirs = ['src/main/java']
// java.excludes 排除src中的部分java代码
}
free {
java.srcDirs = ['src/common/java']
}
vip {
java.srcDirs = ['src/vip/java']
}
}
./gradlew :app:assemblevipDebug 构建指定的flavor,其中vip是flavor的name,可以根据实际更改
修改library产物的名称
libraryVariants.all { variant ->
variant.outputs.all { output ->
def outputName = output.outputFile
if (outputName != null && outputName.name.endsWith(".aar")) {
// 修改aar的名称
outputFileName = "xxxx" + defaultConfig.versionCode + "@" + defaultConfig.versionName + "-" + buildType.name + ".aar"
}
}
}
指定jniLibs
在gradle中增加下面的代码指定不同的jni so打包路径
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs','libs1'] //修改本行
}
}
}
参考:
https://blog.csdn.net/xfhy_/article/details/103329430
https://github.com/Blankj
依赖冲突解决
编译项目的时候,项目中会有很多模块,这些模块又会依赖某个模块,会报错:
Conflict with dependency 'xxx' in project ':'
解决办法:
1.
添加依赖的时候将冲突的依赖模块排除掉,我们假设下面的okhttp3会产生依赖冲突
implementation 'xxx', {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
打包的时候./gradlew assembleXXX 后面增加-Pandroid.dependency.useConstraints=false
gradle 中如何查找下在的远程的aar包
gradle 在远程下载的aar包,会在本地存储一份,我们可以直接通过gradle 本地的缓存路径找到下载的文件。
以mac为例,在当前用户目录的下面的目录中,我们可以找到对应的aar 文件:
.gradle/caches/modules-2/files-2.1
查找 aar 的时候我们可以借助 find 命令取查找例如自己查找arengine:find . -type d -name “arenginesdk”
依赖分析
分析某个模块的依赖树
./gradlew app:dependencies
查看项目的编译依赖(可以看到 App 编译的时候使用的依赖版本)
./gradlew :app:dependencies --configuration compile
混淆文件配置 Androidx Keep 注解
-keep,allowobfuscation @interface androidx.annotation.Keep
-keep @androidx.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <init>(...);
}
-keepclassmembers,allowobfuscation class * {
@androidx.annotation.DoNotInline <methods>;
}
参考:
https://docs.gradle.org/current/userguide/command_line_interface.html#sec:excluding_tasks_from_the_command_line