build.gradle结构分析与常见gradle命令

什么是gradle

一种构建工具,用来管理项目中的依赖,编译,打包,部署等操作。前身类似如Apache Ant和Maven 使用Groovy编写,不需要使用繁琐的XML形式


可以在AndroidStudio右侧的Gradle中,查看项目的各个gradle,并且可以在某个gradle的Tasks->other下,查看各个任务 并且进行相关运行或者Exclude


application的build.gradle

android application(应用)级别的构建配置,作用于整个application(所有module)的 如常见以下配置:

// 引入某个gradle
apply from: 'xx.gradle'  

// 作用于整个项目的通用配置
buildscript {
    ext.kotlinVersion = '1.3.50'
    ext.gradleVersion = '3.5.1'
    repositories {
        maven {
            url "https://"
        }
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:${gradleVersion}"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    }
    
allprojects {
    repositories {
        maven {
         url "https://"
        }
    }
}

// 定义项目级别的环境变量
env.CI = isCI()

// 定义项目级别的宏
def ABI_FILTERS = ['armeabi-v7a']

// 定义项目级别的task
def task1() {
}

module的build.gradle

android module(一个模块/库)级别的构建配置,如常见以下配置:

apply plugin: 'com.android.application'

android {	
	// 编译版本
	compileSdkVersion 27
    buildToolsVersion "27.0.2"
    
    // 默认配置
    defaultConfig {   
        applicationId "com.xxx.xxx"  // 包名
        minSdkVersion 16     // 最小兼容版本
        targetSdkVersion 27  // 最大兼容版本

		// 版本码 给设备程序识别版本(升级)用的,必须是一个interger值
        versionCode 4    
        // 版本号 给用户看的    
        versionName "2.0"
        
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"


 设置cmake的位置
externalNativeBuild {
        cmake {
            path "${sdk_android_lib_dir}/CMakeLists.txt".toString()
        }
    }
    
        /*ndk {
            //选择要添加的对应cpu类型的.so库
            abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
            def ABI_FILTERS = ['armeabi-v7a','x86', 'arm64-v8a']
            // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
        }*/

		// gradle(动态)设置manifest中的 内容
        manifestPlaceholders = [
                JPUSH_PKGNAME: applicationId,
                JPUSH_APPKEY : "xxxxxxxxxxxxxx", //JPush上注册的包名对应的appkey.
                JPUSH_CHANNEL: "developer-default", //暂时填写默认值即可.
        ]

    }

    //签名配置
    signingConfigs {
        config {
            keyAlias 'key0' //key别名
            keyPassword 'xxxx' //key密码,最好不要配置在脚本里
            storeFile file('F:/xxxx/xxxxx.jks') //证书路径,证书最好不要放入项目源码
            storePassword 'xxxx' //证书密码,最好不要配置在脚本里
        }
    }

    buildTypes {
	        release {    // 发行版设置 
	        // 打开混淆
	        minifyEnabled true 
	        // 打开压缩资源 没有使用的资源不会加载
            shrinkResources true   
            // 混淆规则
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            // 加入签名配置
            signingConfig signingConfigs.config 
        }
    }
}

//设置源文件、manifest、assets jniLibs目录位置,这样就不用一定要在工程目录中 可以放到祈祷目录
    sourceSets {
        main {
            manifest.srcFile "${sdk_android_lib_dir}/src/main/AndroidManifest.xml".toString()
            java.srcDirs = ["${sdk_android_lib_dir}/src/main/java".toString()]
            res.srcDirs = ["${sdk_android_lib_dir}/src/main/res".toString()]
            assets.srcDirs = ["${sdk_android_lib_dir}/src/main/assets".toString()]
            jniLibs.srcDirs = ["${sdk_android_lib_dir}/src/main/jniLibs".toString()]
        }
    }

//产品风格配置,ProductFlavor类型 可用于多渠道打包
productFlavors{ }

//测试配置,TestOptions类型
testOptions{ } 

//aapt配置,AaptOptions类型
aaptOptions{ } 

//lint配置,LintOptions类型
lintOptions{ } 

//dex配置,DexOptions类型
dexOptions{ } 

//编译配置,CompileOptions类型
compileOptions{ } 

//PackagingOptions类型
packagingOptions{ } 

//JacocoExtension类型。 用于设定 jacoco版本
jacoco{ } 

//Splits类型
splits{ } 

dependencies {
    // 添加的各种第三方库
}


local.properties

可以设置系统的参数 如ndk.dir sdk.dir 也可以自定义一些变量 这个文件不会上传到git 而是进行的本地配置


settings.gradle

用来进行 include相应的modlue


gradle常用命令

gradle即为编译命令
用于执行build.gradle里面编写的task

gradlew clean 清除工程目录下的build文件夹
gradlew build 检查依赖并编译打包
gradle assembleDebug/assembleRelease 编译和输出debug/Release包
gradle :app:assembleDebug 编译指定包名以及输出debug包
gradle installRelease 编译和输出Release包并安装

2 选择构建的文件
gradle -b(–build-file) /xx/xx/build.gradle taskName(如:app:resguardDebug)
调用 gradle 时,默认情况下总是会构建当前目录下的文件,可以使用-b 参数指定构建的文件

3 通过-p来设置目录
gradle -p /xx/xx taskName

4 获取build过程中的信息

gradle --profile

会存放到< build_dir>/reports/profile 目录下

5 不执行某个task

gradle AATask -x BBTask

6 遇到错误继续执行

gradle --continue

Gralde会调用每一个任务以及它们依赖的任务。而不是一旦出现错误就会中断执行。所有错误信息都会在最后被列出来

7 设置JVM参数
-D指定宏 org.gradle.jvmargs="-Xmx2048M" 指定堆的大小

gradle -Dorg.gradle.jvmargs="-Xmx2048M"

gradlew 即 gradle wrapper 对gradle封装了一层
会绑定到一个特定版本的Gradle,当用户第一次执行上面的命令时,Wrapper会自动地下载并安装对应版本的Gradle

gradle文件中打日志 :print/println即可


gradle脚本自动化生成APK

1 在android{} 标签中

//签名配置
    signingConfigs {
        config {
            keyAlias 'key0' //key别名
            keyPassword 'xxxx' //key密码,最好不要配置在脚本里
            storeFile file('F:/xxxx/xxxx.jks') //证书路径,证书最好不要放入项目源码
            storePassword 'xxxx' //证书密码,最好不要配置在脚本里
        }
    }

2 在buildType中加入签名配置

buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //加入签名配置
            signingConfig signingConfigs.config 
        }
    }

注意 signingConfigs 一定要在 buildTypes 之前 否则 找不到config

3 执行编译打包命令

若 gradle 加入了环境变量 则直接用 gradle命令即可
将gradle加入环境变量中

右键 我的电脑 ---》属性 ---》左边有个:高级系统设置 ---》高级 ---》环境变量 ---》系统变量 选项中 ---》新建 --》变量名:GRADLE_HOME,变量值:你复制的gradle 最高版本的gradle 根目录 ---》确定。

   再在 系统变量 选项中 ---》找到:path 系统路径 ---》在变量值最后加入:%GRADLE_HOME%/bin (因为在bin文件夹下才有gradle.bat 可运行文件)---如果加入之前的系统路径最后没有“;”,要记得加入----》确定。

在windows开始菜单中,输入cmd,打开dos桌面,输入:gradle -v,回车
若出现了 Build time 等信息 而非 不是内部命令即成功

若没有安装gradle
./gradlew [task] (UNIX/Linux)
gradlew [task] (Windows)
(只能在项目根目录下使用)


用 gradle命令 生成 apk
在 项目的 根目录下 按着 shift+鼠标右键 打开cmd
输入命令

gradle assembleRelease

即可生成 发行版的 apk包

生成文件在 :G:\项目名\app\build\outputs\apk\release 下


问题:
Execution failed for task ‘:app:processReleaseResources’. > Failed to execute aapt
有可能是别的地方的错误,看看前面的出错
发现是找不到 dimen.xml这个文件
加上dimen.xml文件即可
dimen.xml 不是在 values.xml中加 (这个文件最好别修改)
而是自己新建dimen.xml 并且根据不同的 values适配 生成不同的 dimen.xml


**二、把签名配置从源码的build.gradle中移除 因为放在源码中不安全 并且 不同开发人员的证书路径不同 **

1 在项目根目录下新建config/signgradle.txt文件,在项目外部创建sign.gradle文件

//在该文件里指定了sign.gradle文件路径
xxx/xxx/sign.gradle

2 源gradle中配置的内容放在 sign.gradle中

android {
  //签名配置
    signingConfigs {
        config {
            keyAlias 'key0' //key别名
            keyPassword 'xxxxx' //key密码,最好不要配置在脚本里
            storeFile file('F:/xxxx/xxxx.jks') //证书路径,证书最好不要放入项目源码
            storePassword 'xxxx' //证书密码,最好不要配置在脚本里
        }
    }

	buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config //加入签名配置
        }
    }
}

3 在源gradle文件中加载 signgradle.txt文件

//加载签名信息  
File configFile = file('../.config/signgradle.txt')  
if (configFile.exists()) {  
	// 读取文件内容 即sign.gradle配置文件的地址 
    def signGradlePath = configFile.newReader().readLine().trim()  
    println 'lucher, path:' + signGradlePath  
    if (file(signGradlePath).exists()) {  
        apply from: signGradlePath  
    }  
}  

4 执行编译打包命令

4.1 编译所有productFlavor及对应所有buildType的apk.(productFlavor和buildType的笛卡尔积)

//如果当前Project包含多个Module,在Project根目录执行gradle assemble会编译所有的Module

$gradle assemble (简写:$gradle a)  //仅仅执行项目打包所必须的任务集

$gradle build    			  //执行项目打包所必须的任务集,以及执行自动化测试,所以会较慢


4.2 编译指定productFlavor及buildType的apk

//如果缺失某参数,则会把该参数的所有配置都进行编译,即如果运行gradle assembleflavor,则会编译出flavor所有buildType的apk
$gradle assemble[productFlavor][buildType]

//例如:
$gradle assemble (简写:$gradle a 、 $gradle ass)

$gradle assembleflavorRelease (简写:$gradle aR 、$gradle assflavorR)

$gradle assembleflavorDebug(简写:$gradle aD 、$gradle assflavorD)


5 不用手动输入 gradle命令 而是点击.bat文件自动批处理执行

在项目根目录下创建一个指定的文件夹(用于编译跑脚本用),例如config,然后在该目录下分别创建.bat文件(win上批处理后缀文件)和签名文件

批处理文件如下autoSignAndPackage.bat:

:快速编译打包apk脚本

echo  " **************************打包开始 ************************** "

:执行打包命令前,需要先定位到项目根目录(即这里的上一层目录)
cd ..
:执行打包命令
gradle aRelease

echo  "**************************打包完成************************** "


双击 bat文件 即可自动执行


shell脚本,即工程中.config/build.sh

#快速编译打包apk脚本

echo  " **************************打包开始 ************************** "
sleep 1
#执行打包命令前,需要先定位到项目根目录
cd ..
#执行打包命令
gradle a

echo -e "**************************打包完成************************** "

#桌面右上角弹出通知
notify-send build.sh "打包完成!"

然后就可以直接通过./build.sh或者在文件管理器里双击build.sh文件来打包了


三、gradle中添加自定义方法
在android标签外
如 获取当前时间

//获取当前时间  
def getCurrentTime() {  
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))  
}  

四、gradle修改apk文件名
结合三

    //apk文件重命名
    android.applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def buildType = variant.buildType.name
                //这里修改apk文件名,格式为 module_flavor-version-time-buildtype.apk
                def fileName = "app_${variant.productFlavors[0].name}-V${defaultConfig.versionName}-${getCurrentTime()}-${buildType}.apk"
                outputFileName = new File(fileName) 
               outputFileName  = new File(outputFile.parent, fileName)  // 该方式会加上前面的路径
            }
        }
    }

gradle (动态) 更改 manifest中的 内容

manifestPlaceholders = [APP_NAME : "app-百度"]
然后 manifest中 的 application的lable使用
android:label="${APP_NAME}" 

这样就可以 根据 gradle中 不同的渠道 去设置app不同的名称

通过该方式也可以添加产品风格配置脚本,用于多渠道打包

//产品风格配置,可用于多渠道打包  
productFlavors {  
    //百度推广渠道  
    baidu {  
        applicationId "com.lucher.myapplication"  
        versionCode 1  
        versionName "1.0"  
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]  
  manifestPlaceholders = [  APP_NAME  : "app-百度"] //自定义App名称,需要把AndroidManifest.xml里的label改为: android:label="${APP_NAME}"  
    }  
    //360推广渠道  
    qh360 {  
        applicationId "com.lucher.myapplication"  
        versionCode 1  
        versionName "1.0"  
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"]  
        manifestPlaceholders = [  APP_NAME  : "app-360"] //自定义App名称,需要把AndroidManifest.xml里的label改为: android:label="${APP_NAME}"  
    }  

AndroidStudio 查看 gradle的执行过程和输出信息
打开 gradle console 窗口,如下图:

即可以看到 gradle的执行过程和输出信息 如println


五、自定义res java manifest assets等的文件目录 还可以设置不同productFlavor的源目录
在module.gradle中 加上

    sourceSets {
    main {
        manifest.srcFile "${sdk_android_lib_dir}/src/main/AndroidManifest.xml".toString()
        java.srcDirs = ["${sdk_android_lib_dir}/src/main/java".toString()]
        res.srcDirs = ["${sdk_android_lib_dir}/src/main/res".toString()]
        assets.srcDirs = ["${sdk_android_lib_dir}/src/main/assets".toString()]
        jniLibs.srcDirs = ["${sdk_android_lib_dir}/src/main/jniLibs".toString()]
    }
        productFlavorBuildType{

        }
    }

六、构建时修改自定义的res或者java目录
1 将res目录和java目录移出去 RDM构建时代码或者资源文件的内容复制到src/main/下
2 用product flavor区分
还是gradle中指定source路径 然后构建改使用的product flavor

七、gradle生成apk或者jar、aar包
project的gradle是默认有 installRelease installDebug命令的
可以安装apk到手机或者模拟器中
而这个命令只是装到apk 并不会生成jar aar等文件

而 ./gradlew install
也是安装apk到手机或者模拟器中 但是却可以生成jar aar pom等文件
可以通过加上 clean 标签 不需要安装apk到手机或者模拟器 也去执行项目和包的构建

八、增加project层级的公共属性
可以在project的build.gradle或者在project层级中建立version.gradle common.gradle等
然后设置 ext{} 自定义project级别的属性 这样module级别的gradle可以通过
rootproject.ext.xx获取这个公共属性


问题:

1 gradlew build的时候 Could not determine java version from ‘10.0.1’.
因为gradlew版本太低了
升级gradlew版本
或者降低 java版本为1.8

可以去 gradle-wrapper.properties 修改 distributionUrl为对于的版本
参考:https://www.jianshu.com/p/00beddbe3dbc

classpath 'com.android.tools.build:gradle:3.1.2'

gradle是有两个类型的版本的:
上面的classpath 版本是gradle plugin 的版本
而类似 gradle-4.4 则是真正的gradle版本

对应的关系表可以查看:https://developer.android.google.cn/studio/releases/gradle-plugin

2 gradle: Permission denied
去gradle目录 开启运行权限

chmod +x /Applications/Android\ Studio.app/Contents/gradle/gradle-4.6/bin/gradle

你可能感兴趣的:(性能优化,android)