前端开发

Android Gradle插件开发

2021-01-08 18:21:50 阅读数 5105 收藏 0

Gradle

Gradle简介

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具,支持maven、 Ivy仓库,支持传递性依赖管理,而不需要远程仓库或者是pom.xml和ivy.xml配置文件。
Gradle使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。

当前,Gradle其支持的语言有Java、Kotlin、Groovy 和 Scala,未来将支持更多的语言。在平时Android开发中,Android项目就是使用Gradle来构建的,如下所示。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.xzh.gradleplugin"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

同时,Android Studio也集成了Gradle的构建工具,例如下面是我们项目构建的常见场景。

常用命令

命令 说明
-v, --version 查看当前 Gradle 版本信息
-h: 查看帮助信息
-s, --stacktrace / -S, --full-stacktrace 如果发生异常则输出异常栈信息
-i, --info / -d, --debug 控制日志级别
–stop 停止正在运行的 Daemon
-D, --system-prop / -P, --project-prop 传入特定参数
-m, --dry-run / -x, --exclude-task 运行构建,但不执行任务的实际操作
–offline / --refresh-dependencies 离线模式构建,强制刷新依赖构建
b, --build-file / -c, --settings-file 指定 build 脚本,指定 settings 脚本
Ctrl + c 终止当前运行
./gradlew aFR > log.txt 2>&1 输出所有内容到 log.txt

Gradle Wrapper

Gradle Wrapper的作用是简化Gradle本身的安装、部署。不同版本的项目可能需要不同版本的Gradle,手工部署的话比较麻烦,而且可能产生冲突,所以需要Gradle Wrapper帮你搞定这些事情。Gradle Wrapper是Gradle项目的一部分。

在Android应用开发中,我们经常会看到如下一段代码:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

它的作用就是为了简化Gradle的配置。具体可以参考:彻底搞懂Gradle、Gradle Wrapper与Android Plugin for Gradle的联系

Gradle Task

在Android打包和apk构建时,经常会用到Gradle的Task命令,常见的有如下一些。

命令 说明
tasks [–all] 列出所有可运行的 task
help --task <task> 查看指定 task 的帮助信息
androidDependencies 查看当前 project 的 android 依赖树
dependencies --configuration <config> 查看 configuration 的 依赖树
clean 清除构建产出物
assemble, assemble{BuildVariant} 构建 apk,构建指定 Variant 的 apk
install 构建 apk 并安装
uploadArchives 构建 aar 并上传到指定依赖管理服务器

在一次Android项目构建过程中,assembleRelease依赖了许多task,如下是一些比较关键的task。

命令 说明
compileReleaseJavaWithJavac 编译Java文件
mergeReleaseAssets 收集所有的assets
mergeReleaseResources 收集所有的resources
processReleaseManifest 生成最终的AndroidManif.xml文件
transformClassesAndResourcesWithPro guardForRelease 混淆
transformClassesWithDexForRelease 生成dex
packageRelease 打包生成apk

构建生命周期

根据Build phases 文档 和 Settings file 文档可以知道,Gradle 构建周期可以分为:初始化(Initialization)、配置(Configuration)和执行(Execution)。

  • 初始化(Initialization)
    Gradle可以构建一个和多个项目。在初始化阶段,Gradle会确定哪些项目参与构建,并且为这些项目创建一个Project实例。

  • 配置(Configuration)
    在这个阶段,会配置project对象。将执行构建的所有项目的构建脚本。也就是说,会执行每个项目的build.gradle文件。

  • 执行(Execution)
    Gradle确定要在执行期间创建和配置的任务子集。子集由传递给gradle命令和当前目录的任务名称参数确定。 Gradle然后执行每个选定的任务。

Android apk构建过程

大概分为以下几个步骤
1、使用aapt工具将res资源文件生成R.java文件
2、使用aidl工具将aidl文件生成对应java文件
3、使用javac命令编译工程源代码和上面两步生成的文件,生成class文件
4、通过dex工具将class文件和第三方jar包打成dex文件
5、用aapt工具将res下的资源文件编译成二进制文件,然后将其和上一步中的dex文件以及assets中的文件通过apkbuilder工具打包成apk文件
6、通过jarsigner对apk进行签名
7、利用zipalign工具对apk进行字节对齐优化操作

可以用下面的图来描述Android apk的构建过程,如下所示。

Gradle 插件开发

创建Gradle插件

创建Gradle插件项目比较简单,如果你是macOS,可以先安装gradle插件,安装的命令如下:

brew install gradle

安装完成之后,新建一个空的项目工程,然后在项目目录下使用gradle init即可创建项目,创建时会让你选择很多的东西,如下图。

等待工程构建完成,会发现示例项目为我们构建了一个示例代码,如下所示:

public class GradlePlugin implements Plugin<Project> {
    public void apply(Project project) {
        // Register a task
        project.tasks.register("greeting") {
            doLast {
                println("Hello from plugin 'xzh.plugin.greeting'")
            }
        }
    }
}

该命令会向Gradle注册GradlePlugin插件,代码如下:

gradlePlugin {
    // Define the plugin
    plugins {
        greeting {
            id = 'xzh.plugin.greeting'
            implementationClass = 'xzh.plugin.GradlePlugin'
        }
    }
}

然后,在命令行中执行gradle copy命令,该命令对应的代码为:

task copy(type: Copy, group:"Custom", description:"task description") {
    from "src"
    into "dest"
}

上面的代码作用是将src的文件拷贝到dest目录。

开发插件并发布到本地

有时候,我们需要开发一些Gradle插件,并将插件发布到Maven或者Jcenter仓库,给其他人使用。此处为了方便,我们先发到本地,然后拉取时也拉取本地的插件。

假如我们已经开发好了一个插件项目,现在想将它发布到本地仓库(远端Maven仓库),如下图所示。

然后,我们在插件的build.gradle文件中,新增如下上传脚本:


apply plugin: 'maven'

uploadArchives{
    repositories.mavenDeployer{
        // 配置本地仓库路径,项目根目录下的repository目录中
        repository(url: uri('/Users/xiangzhihong/Maven/repository'))
        pom.groupId = "com.xzh.viewlib"// 唯一标识(通常为模块包名,也可以任意)
        pom.artifactId = "OXViewLib" // 项目名称(通常为类库模块名称,也可以任意)
        pom.version = "1.0.0"      // 版本号
    }
}

配置完成后点击【Sync Now】重新构建项目,然后在Gradle projects窗口会多出一个upload目录,里面就有一个名为uploadArchives的task,这个uploadArchives就是将类库发布到仓库的task。

然后,执行上面的Task即可,执行完后,会在对应的地址中生成repository目录,目录结构就是上面再build.gradle中的配置。repository目录文件结构如下图。


然后就可以在Android项目中引入这个Gradle插件了。打开项目工程的build.gradle,然后在repositories闭包中添加如下本地地址(后期换成Maven地址)。

allprojects {
    repositories {
        google()
        jcenter()
        //本地Maven仓库地址
        maven {
            url'/Users/xiangzhihong/Maven/repository'
        }
    }
}

然后,在app下build.script中添加依赖即可。

 implementation 'com.xzh.viewlib:OXViewLib:1.0.0'

然后点击【Sync Now】重新构建项目,接下来可以在Android项目中使用Gradle插件的代码了。当然,如果要发布到远端的Maven仓库,还需要进行Maven仓库的配置,不过流程都差不多。

插件调试

1, 执行编译

在命令行中执行App的编译命令,如下所示:

 ./gradlew assembleDebug -Dorg.gradle.daemon=false -Dorg.gradle.debug=true

后面两个参数是必须的,表示等待gradle调试。此时,程序会卡在等待调试的页面,如下图。

2,Remote配置

1,创建新的运行配置,本地调试默认配置即可直接点确定,如果远程调试请输入Host。


2,对remote配置点击调试按钮,如下图。