Android Gradle 插件开发入门指南(三)

2,606 阅读9分钟

image.png Android Gradle 插件开发入门指南一共规划了三篇文档:

前言、Bintry & JCenter

bintray全称JFrog Bintray,是JFrog这家公司提供的包存储管理服务,而JCenter只是bintray里的一个官方仓库,在Android项目根目录的build.gradle构建脚本里,我们能见到jcenter的身影。

buildscript {
    repositories {
        google()
        jcenter() // 我在这
        ......
    }
}

allprojects {
    repositories {
        google()
        jcenter() // 我在这
    }
}

一、准备bintray的账户

1. 注册账户信息

如果已经有bintray账户,直接从第二步开始
进入bintray官网:bintray.com/,点击右上角的"Sign In",进入到登录页面,然后注册账户。这里要注意选择开源账户,免费试用账户有限制! image.png

2. 创建仓库

登录你的bintray账户,创建仓库 image.png image.png

3. 定位账户信息

登录你的bintray账户,Edit Your Profile -> API Key 找到你的key信息 image.pngimage.png

二、应用gradle-bintray-plugin

修改插件module下的构建脚本,应用gradle-bintray-plugin插件,具体到我们的例子就是apkrename-plugin/build.gradle

plugins {
    id "com.jfrog.bintray" version "1.8.5"
}

三、配置gradle-bintry-plugin

1. 配置账户信息

就是要告诉gradle-bintray-plugin我们要把包上传到哪个账户下面,需要前面注册的bintray的用户名称和Api Key。由于我们的插件源码可能公开或者上传到git,所以我们不能直接在插件的构建脚本里填写我们的配置信息,有两种处理方式:

  • local.properties

每一个gradle项目的根目录下都有一个local.properties文件,用来存放本地属性信息,这个文件默认不会上传到版本管理系统(git),我们可以将我们的bintray账户信息保存到这里,然后在插件的构建脚本里读取(apkrename-plugin/build.gradle)image.png

// 读取bintay账户信息
Properties properties = new Properties()
InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream()
properties.load(inputStream)
inputStream.close()

bintray {
    user = properties.getProperty('bintray.user')
    key = properties.getProperty('bintray.key')
}
  • System Environment Variables

如果我们不小心将local.properties文件上传到了git或者发送给了别人,仍然有账户信息泄露的风险,更为安全的做法是把bintray的账户信息保存到系统环境变量里,只能在本机才能读取。我用的是zsh shell,zsh环境变量配置是在~/.zshrc里添加以下语句,其他的shell环境变量的配置大家自行搜索,就不一一说明了。 image.png 然后在插件的构建脚本里读取(apkrename-plugin/build.gradle)bintray的账户信息

bintray {
    user = System.getenv('BINTRAY_USER')
    key = System.getenv('BINTRAY_KEY')
}

2. 配置包信息

就是添加包的身份信息,详细的说明在代码注释里,结合着代码看应该更清晰点

bintray {
    // bintray账户信息,告知gradle-bintray-plugin把包上传到哪个账户下
    user = System.getenv('BINTRAY_USER')
    key = System.getenv('BINTRAY_KEY')
    
    // 这里配置包信息
    pkg {
        // 必填项,前面我们创建的仓库名称
        repo = 'maven'

        // 必填项,我们要上传的包的名称
        name = 'apk_rename'

        // 可选项,用户组,付费账户才能使用的功能
        userOrg = 'lenebf'

        // 开原许可,如果是开源包必须有,否则可选,翻译的不是很准确。
        // 文档原话:your package licenses (mandatory if the package doesn't exist 
        // yet and must be created, and if the package is an OSS package; optional
        // otherwise)
        licenses = ['Apache-2.0']

        // 版本控制系统地址(一般为git地址),如果是开源包必须有,否则可选,翻译的不是很准确。
        // 文档原话:your VCS URL (mandatory if the package doesn't exist yet and 
        // must be created, and if the package is an OSS package; optional otherwise)
        vcsUrl = 'https://github.com/lenebf/GradlePluginTutorial'

        // 包的版本信息
        version {
            // 必填,版本名称
            name = '0.0.1'
            // 选填,版本描述
            desc = 'ApkRename Plugin 0.0.1'
            // 选填,版本发布日期
            released  = new Date()
            // 选填,版本控制系统的对象的tag名称
            vcsTag = 'tag_0.0.1'
            // 选填,该版本的附件属性信息,可以任意填写
            attributes = ['apk-rename': 'Hello, Word!']
        }
    }
}

信息配置完成后,我们同步image.png下项目,我们看看gradle任务列表有没有出现我们想要的任务呢? image.png image.png bintrayUpload 就是我们的上传任务,执行下: image.png 执行成功后我们bintray账户下的maven仓库多了一个apk_rename的包,但是包里面没有任何文件,空空如也: image.png 因为我们前面的配置只是告诉bintray-gradle-plugin我们要上传包到哪个bintray账户下,并没有告诉插件要包含那些文件到包里面,这个插件着实有点蠢,好在我们不蠢,我们继续教它做人!

四、发布包到bintray

1. 配置工件组信息

包里面的文件称之为工件,bintray-gradle-plugin支持三种方式创建工件组(一个包里不只有一个文件,所以叫工件组):

  • Configurations(配置)
  • Publications(发布)
  • Copying specific files using filesSpec(使用文件规范复制文件)

这里我们选择Publications(发布),因为在指南一指南二里面我们已经用过了,其他两个我也不熟悉😝。
Maven Publish Plugin 文档:docs.gradle.org/current/use… 先应用Maven Publish Plugin,然后配置发布信息:

publishing {
    publications {
        apkRename(MavenPublication) {
            // 插件的组ID,建议设置为插件的包名
            groupId = 'com.lenebf.plugin'
            // 翻译过来是 工件ID,我的理解是插件的名字
            artifactId = 'apk-rename'
            version = '0.0.1'
            // 组件类型,我们的插件其实就是Java组件
            from components.java
        }
    }

    repositories {
        maven {
            // $rootProject 表示你项目的根目录
            url = "$rootDir/repo"
        }
    }
}

然后告诉bintray-gradle-plugin上传apkRename这个工件组:

bintray {
    user = System.getenv('BINTRAY_USER')
    key = System.getenv('BINTRAY_KEY')
    // 我要上传apkRename这个工件组
    publications = ['apkRename']
    ......
}

重新执行bintrayUpload任务,我们的apk_rename插件下面就有文件了: image.png 同时在包描述页面我们看到了一个提示: image.png 这个提示是告诉你有新的文件已经上传成功,但是还没有对外公开,只有你自己可见,点击Publish发布出去即可。如果你想每次有新文件上传直接对外发布,而不是每次都来点击,可以添加配置告诉bintray-gradle-plugin直接发布:

bintray {
    ......
    pkg {
        ......
        // 每次上传直接发布
        publish = true
        ......
    }
}

2. 通过bintray引用包

到这里我们已经能够通过bintray引用我们的插件包了,首先找到仓库地址,我的仓库就是前面创建的maven,进入仓库页面右上角显示了仓库地址,比如我的是:dl.bintray.com/lenebf/mave… image.png 然后把之前项目根目录下build.gradle脚本里的本地仓库地址换成bintray仓库地址:

repositories {
    google()
    jcenter()
    // 如果是发布到MavenLocal就是用mavenLocal()
    // mavenLocal()
    // 自定义的发布地址
    // maven { url('./repo') }
    // 替换为bintray仓库地址
    maven { url('https://dl.bintray.com/lenebf/maven')}
}

同步项目,我们的插件已经应用成功了!

五、添加包到Jcenter

前面我们通过将自己的仓库地址加入包引用列表,已经能够引用到我们上传在bintray上的插件包了,但是每个人的bintray账户不同,对应的仓库地址也不一样,如果我们的项目使用的十个不同bintray账户下的包,就需要配置十个仓库地址,这也太啰嗦了。前面提到了Jcenter是bintray的一个官方仓库,这个仓库支持将我们的包加进来,我们照着文档一步一步来一遍。 文档地址:www.jfrog.com/confluence/…Including your Package in JCenter一节有详细的说明

1. 规范包信息

将包添加到jcenter,我们要满足几个条件:

  • 软件包必须在公共Maven存储库中,并且必须包含源码包

我们前面创建的仓库已经是一个公开的Maven类型的仓库了,但是我们上传的工件里没有源码包,所以需要改进我们的编译脚本,将源码包也包含进去:

// 源码包生成任务
task sourcesJar(type: Jar, dependsOn: classes) {
    def classifier = getArchiveClassifier()
    classifier.set('source')
    classifier.convention('source')
    from sourceSets.main.allSource
}

publishing {
    publications {
        apkRename(MavenPublication) {
            ......
            // 添加源码工件
            artifact sourcesJar
        }
    }
}

由于前面我们已经上传过0.0.1版本的包了,所以需要修改下版本号,然后重新执行bintrayUpload任务,然后就能看到sources.jar文件了 image.png

  • 文件路径必须符合Maven标准

主要是要求Group ID和Artifact ID组合必须是唯一的,不然我们的包和其他人的包就冲突了。有关Maven标准的更多信息,请参阅相应的Maven文档

  • 每个版本的包都必须包含POM文件

Maven Publish Plugin生成的包已经默认包含POM文件了

2. Try

现在万事具备,我们来点击image.png(在包主页的右下角)跳转到Add to Jcenter请求页面,然后点击Send按钮,发送消息给bintray,然后就等待审核邮件了。然后你就会和我一样收到一封私信,告诉你包不满足规范要求😂: image.png 因为我们前几个版本的包没有包含sources.jar文件,处理方法就是把这些版本的包删除,步骤见下图: image.png image.png

然后重新提交Add to Jcenter请求,等待审核消息,审核通过后,你bintray账户应该能收到一份私信,告诉你请求已认可: image.png 接下来就可以直接通过jcenter仓库引用我们的插件包了。

六、通过Jcenter仓库引用插件包

删除项目根目录里构建脚本中对我们自己仓库的引用代码:

buildscript {
    ......
    repositories {
        google()
        jcenter()
        // 已经发布到jcenter,不需要自己的仓库了
        // maven { url('https://dl.bintray.com/lenebf/maven')}
    }
}

然后同步image.png项目,即可引用我们的ApkRename插件了,是不是很Easy!

七、延伸

  • 其实Android项目里常见的仓库除了jcenter,还有maven仓库,bintray同样支持将包加入maven仓库里,但是要求更多一些,具体要求见文档:central.sonatype.org/pages/requi…。当你的包成功加入jcenter仓库,同时满足添加到maven仓库的要求,就可以进一步将包同步到maven仓库里

image.png

  • 还有一个更多傻瓜的包管理服务,那就是www.jitpack.io/,几乎不需要任何开发工作就可以将你的包包含在jitpack仓库了,然后依赖jitpack仓库即可引用包

八、代码

文章中代码地址:github.com/lenebf/Grad…