用IntelliJ实现android gradle插件

登山则情满于山,观海则意溢于海。这篇文章主要讲述用IntelliJ实现android gradle插件相关的知识,希望能为你提供帮助。
用IntelliJ实现android gradle插件 android的gradle插件用了不少了, 比如说官方的应用构建插件( com.android.application) ,lib构建插件( com.android.library) , 还有第三方的比如辅助multidex的DexKnifePlugin。但是怎么自己创建一个gradle插件一直不明白, 今天就试一试自己撸一个android gradle插件,毕竟实践出真知。
基础知识 首先得知道一个gradle插件有需要哪些元素。
我们以android的application插件为例, 往往有如下代码, 这些代码到底是什么?

//root build.gradle dependencies { classpath ' com.android.tools.build:gradle:2.2.3' } //app build.gradle apply plugin: ' com.android.application'

属性备注
pluginIdcom.android.application对应一个Plugin类
groupIdcom.android.tools.build
artifactIdgradle
version2.2.3
以上是一个gradle插件必须的属性。然后既然是gradle 插件必须实现Plugin< Project> 接口。groupId、artifactId、version指定了一个插件工程, 每个插件工程下可以有若干个插件( 每个插件一个pluginId)
创建gradle插件 首先选择科学工具IntelliJ, 之前在groovy入门指南1里面已经配置好了groovy和IntelliJ的环境, 所以可以直接搞起来。
  • 1、打开IJ( IntelliJ) , new-> gradle-> 选上java和groovy-> Next,如下图所示
用IntelliJ实现android gradle插件

文章图片

  • 2、选择groupId和artifactId以及版本。这3个是就是我们说的gradle插件四属性的3个, 他们可以确定classpath
用IntelliJ实现android gradle插件

文章图片

这里我们配置如下, 注意版本号写1.0
  • 3、勾上use auto-import和 create directories for empty.., 这样会帮我们自动导包并创建好groovy和java根目录
用IntelliJ实现android gradle插件

文章图片

  • 4、just next
  • 5、第一次创建gradle工程, 他会去下载2个jar, junit:4.11和org.codehaus.groovy:groovy-all:2.3.11, 这个下载过程非常慢( 好吧, 其实是公司网络比较坑) , 耐心等待。
用IntelliJ实现android gradle插件

文章图片

  • 6、jar包下载好之后, 会自动创建main和test文件夹( 其实gradle默认工程的创建也是在执行gradle任务) , 此时文件结构如下, 注意groovy和java文件夹为蓝色的
用IntelliJ实现android gradle插件

文章图片

  • 7、在build.gradle的dependencies里面加入
compile gradleApi() compile localGroovy()

  • 8、在groovy文件夹下创建一个package, 包名随便起, 就叫com.fish好了,然后在里面new一个groovy类就叫FirstPlugin好了, 并且让FirstPlugin实现Plugin接口, 这个Plugin是org.gradle.api.Plugin。然后实现apply接口, 加点代码, 最后代码如下, 我们创建了一个task叫做showTipTask, task在funny这个group内( 我们可以对task进行分组, 待会会明白) , showTipTask只是打印出一行文字。description是对这个task的描述, 当用户执行./gradlew tasks会显示出来。
package com.fishimport org.gradle.api.Plugin import org.gradle.api.Project/** * Created by fish on 17/1/24. */ class FirstPlugin implements Plugin< Project> { void apply(Project project) { def showTipTask = project.tasks.create(" showTips" ) < < { println(' hello I am the first custom plguin' ) } showTipTask.group = " funny" showTipTask.description = " Hello baby" } }

  • 9、此时plugin已经有了, 就是FirstPlugin, 我们需要把他传到Maven Central或者jcenter上, 这样大家都可以用了, 这里只是个demo, 我就不上传了, 我把他放在本地。如何配置:
    在build.gradle内加如下代码,这些代码事件上是定义了一个task叫uploadArchives, 执行uploadArchives就会把gradle插件打包然后上传到本地或者远端。
apply plugin: ' maven' uploadArchives { repositories { mavenDeployer { repository(url: uri(' repo' )) } } }

  • 10、此时可以尝试生成插件, 执行uploadArchives这个任务就行, 有2种方法。方法1是点击view-tool windows-gradle, 在右边找到uploadArchives, 找不到的话可以点击蓝色刷新按钮刷新一下, 如下所示
用IntelliJ实现android gradle插件

文章图片

方法2是还可以在IJ的terminal窗口执行./gradlew uploadArchives, 推荐使用这种方法, 可以看到清楚的日志, 特别是失败时日志信息很关键
10、不幸的是, 失败了,日志如下
Starting a Gradle Daemon (subsequent builds will be faster) :compileJava UP-TO-DATE :compileGroovy FAILEDFAILURE: Build failed with an exception.

可以用./gradlew uploadArchives --stacktrace看更详细的信息, 得到信息如下所示
Caused by: groovy.lang.GroovyRuntimeException: Conflicting module versions. Module [groovy-all is loaded in version 2.4.7 and you are trying to load version 2.3.11 ... 10 more

看来是有2个groovy-all, 原来IJ依赖了我默认的groovy是2.4.7版本的, 然后这里工程又依赖了2.3.11版本的, 所以当然会出错了, 解决方法是在build.gradle里注释掉compile ' org.codehaus.groovy:groovy-all:2.3.11' 这行代码。
【用IntelliJ实现android gradle插件】11、我们再执行./gradlew uploadArchives --stacktrace又会发现如下问题, miss了一个file, 想想漏了什么, 我们没有指明pluginId
用IntelliJ实现android gradle插件

文章图片

补上它, 在main/resources下创建META-INF/gradle-plugins文件夹, 在里面建一个properties文件, 文件名随便起( 包名格式) , 比如就叫com.apple.propeties, 文件里配置类名
implementation-class= com.fish.FirstPlugin

好了run it, 此时插件就生成了,生成的插件是主要是jar包和配置文件,结构如下
用IntelliJ实现android gradle插件

文章图片

使用插件 现在插件已经写好了, 怎么使用他呢?
new一个AS工程, 叫UseShip好了。然后在根目录的build.gradle加依赖 classpath ' com.netease:ship:1.0'
, 在app的build.gradle加apply plugin: ' com.apple'
。现在插件就导进来了, 我们在执行apply plugin: ' com.apple'
的时候会调用FirstPlugin的apply方法, 在apply方法内我们定义了一个showTipTask, 这个task在funny这个group下, 来, 我们验证下, 如下所示 , 果然找到了这个task
用IntelliJ实现android gradle插件

文章图片

此时可以在terminal下执行./gradlew showTips, 得到了正确结果, 显示 “hello I am the first custom plguin”
192:UseShip fish$ ./gradlew showTips To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.14.1/userguide/gradle_daemon.html. Incremental java compilation is an incubating feature. :app:showTips hello I am the first custom plguinBUILD SUCCESSFULTotal time: 9.344 secs

其他 我们这里pluginId故意起的跟GroupId、ArtifictId没什么关系, 是为了区分清楚, 但实际上他们往往是关联的。
THANKS TO http://tools.android.com/build/gradleplugin
http://blog.bugtags.com/2016/03/28/embrace-android-studio-gradle-plugin/
https://docs.gradle.org/current/userguide/custom_plugins.html
Create a Standalone Gradle plugin for Android - a step-by-step guide

    推荐阅读