Gradle插件開發(fā)-上傳apk文件到Bugly

前言

上一篇文章已經(jīng)給大家詳細(xì)介紹了如何通過(guò)Gradle將我們開發(fā)好的Library上傳到JCenter,基本上就是一系列配置,最后通過(guò)Gradle腳本將Library打包成jar或者aar包上傳到maven倉(cāng)庫(kù),然后添加到JCenter倉(cāng)庫(kù)進(jìn)行審核,通過(guò)之后就能讓開發(fā)者在gradle腳本進(jìn)行引用。本篇博客還是基于Gradle,但稍微進(jìn)階一下,將跟大家分享一下如何開發(fā)一個(gè)Gradle插件,這個(gè)插件是我為Bugly開發(fā)的自動(dòng)上傳apk文件的Gradle插件,目前已經(jīng)開源,有興趣的朋友可以到github看看:https://github.com/BuglyDevTeam/BuglyBetaUploader。

什么是Gradle插件?

這個(gè)問(wèn)題問(wèn)得很好,我們來(lái)舉個(gè)例子,在使用Android Studio進(jìn)行開發(fā)的時(shí)候,我們創(chuàng)建一個(gè)Android工程,會(huì)默認(rèn)生成一個(gè)build.gradle腳本,打開腳本你會(huì)看到以下代碼:

apply plugin: 'com.android.application'

大家有沒有想過(guò)為什么會(huì)有這么一句代碼?如果我們創(chuàng)建一個(gè)Library的話,就會(huì)變成:

apply plugin: 'com.android.library'

其實(shí)這就是在gradle腳本引用android為我們提供的插件,plugin表示插件,'com.android.application’表示我們引用的插件名,通常是以包名來(lái)命名。

這里還有一個(gè)問(wèn)題,這個(gè)插件是怎么被引用進(jìn)來(lái)的?我們可以在根目錄找到另外一個(gè)build.gradle文件,打開可以看到以下代碼:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

稍微解釋下,buildscript方法是定義了全局的相關(guān)屬性,repositories定義了jcenter作為倉(cāng)庫(kù)。一個(gè)倉(cāng)庫(kù)代表著你的依賴包的來(lái)源,例如maven倉(cāng)庫(kù)。dependencies用來(lái)定義構(gòu)建過(guò)程。classpath 'com.android.tools.build:gradle:2.0.0',就是將遠(yuǎn)程的插件下載到本地并將其構(gòu)建到我們工程當(dāng)中。

那怎么找到插件下載的路徑呢,如下圖所示 :

android插件

你可以看到我們?cè)赼ndroid studio所用到的所有插件和Library都會(huì)下載這個(gè)目錄下,這下子你應(yīng)該對(duì)gradle引用插件的原理有一定的理解了吧。

如何開發(fā)Gradle插件?

這個(gè)也是本篇博客要講的內(nèi)容,要理解這部分內(nèi)容需要大家先去了解Groovy這個(gè)語(yǔ)言,因?yàn)槲覀冮_發(fā)Gradle插件使用的就是Groovy語(yǔ)言,可以看看在開源中國(guó)對(duì)這門語(yǔ)言的描述:

這里寫圖片描述

這部分內(nèi)容同學(xué)們自己去研究,本篇博客不會(huì)過(guò)多的講解它的語(yǔ)法,其實(shí)你完全可以將它作為Java來(lái)用,后面你可以看到我寫的一些代碼其實(shí)跟Java沒有太大差別。

步驟1:創(chuàng)建groovy工程

在Android Studio不能直接創(chuàng)建groovy工程,但我們可以按照下面步驟來(lái)創(chuàng)建:

  1. 創(chuàng)建一個(gè)Android項(xiàng)目
  2. 新建一個(gè)module,選擇Androd Library
  3. 刪除除build.gradle之外的所有文件
  4. 按照Groovy工程模板創(chuàng)建對(duì)應(yīng)的目錄

最終創(chuàng)建出來(lái)的工程如下圖所示:

betauploader

第4步:在新建的module中新建文件夾src,接著在src文件目錄下新建main文件夾,在main目錄下新建groovy目錄,這時(shí)候groovy文件夾會(huì)被Android識(shí)別為groovy源碼目錄。除了在main目錄下新建groovy目錄外,你還要在main目錄下新建resources目錄,同理resources目錄會(huì)被自動(dòng)識(shí)別為資源文件夾。在groovy目錄下新建項(xiàng)目包名,就像Java包名那樣。resources目錄下新建文件夾META-INF,META-INF文件夾下新建gradle-plugins文件夾

步驟2:配置gradle

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    compile gradleApi()
    compile localGroovy()
}

repositories {
    mavenCentral()
}
group = 'com.tencent.bugly.plugin'
version = '1.0.0'

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('../repo'))
        }
    }
}

group將會(huì)表示插件的groupId,version表示插件的版本,這段代碼會(huì)在gradle toolbar生成一個(gè)task,執(zhí)行這個(gè)task會(huì)將插件發(fā)布到本地的repo目錄下,這里注意下,我們正在開發(fā)階段,不需要將gradle插件上傳到maven,我們將它發(fā)布到自己指定的目錄下即可。

uploadArchives

執(zhí)行uploadArchives這個(gè)task,就會(huì)在repo目錄下生成指定版本的插件:

gradle插件生成

步驟3:創(chuàng)建BetaPlugin

這里就不把完整的實(shí)現(xiàn)代碼貼出來(lái),只貼大體的框架:

public class BetaPlugin implements Plugin<Project> {
    ...
    
     @Override
    void apply(Project project) {
        ...
    }

    ...

}

創(chuàng)建一個(gè)Plugin就需要實(shí)現(xiàn)Plugin接口,并且重寫它的apply方法,這個(gè)類當(dāng)中就是用來(lái)實(shí)現(xiàn)插件的邏輯的,比如創(chuàng)建task,獲取外部的參數(shù)都需要在這里面完成。

代碼開發(fā)完畢之后,在resources/META-INF/gradle-plugins目錄下新建一個(gè)properties文件,注意該文件的命名就是你使用插件的名字,這里命名為com.tencent.bugly.plugin.betauploader.properties,在里面輸入:

implementation-class=com.tencent.bugly.plugin.BetaPlugin

這樣就完成插件的配置了。

步驟4:接收外部參數(shù)

apply plugin: 'com.tencent.bugly.plugin.betauploader' // 應(yīng)用上傳apk插件

// beta配置
beta {
    appId = '900037672'
    appKey = 'bQvYLRrBNiqUctfi'
    title = "測(cè)試"
    desc = "beta apk uploader "
    enable = true
    autoUpload = false
    debugOn = false
}

基本上插件的使用就是這樣,beta包含的配置都是用戶設(shè)置讓我們插件接收的外部參數(shù),每個(gè)參數(shù)基本以key = value的形式設(shè)置。

要實(shí)現(xiàn)接收外部參數(shù)就需要自定義一個(gè)定義外部參數(shù)的類,如下所示:

package com.tencent.bugly.plugin

/**
 * Beta extension params
 * @author wenjiewu
 */
public class BetaExtension {
    public String appId = null // AppID 【必選】
    public String appKey = null // AppKey 【必選】
    //  【option】
    // 【接口參數(shù)】
    public String title = null // 標(biāo)題
    public String desc = null // 版本描述
    public int secret = 1 // 公開范圍(1:所有人,2:密碼,4管理員,5QQ群,6白名單)
    public String users = null // 如果公開范圍是"QQ群"填QQ群號(hào);如果公開范圍是"白名單"填QQ號(hào)碼,并使用;切分開,5000個(gè)以內(nèi)。其他場(chǎng)景無(wú)需設(shè)置
    public String password = null // 密碼(如果公開范圍是"密碼"需設(shè)置)
    public int download_limit = 1000 // 下載上限(大于0,默認(rèn)1000)
    public String expId = null // 需替換安裝包的版本id

    // 【插件配置】
    public String apkFile = null // 指定上傳的apk文件
    public Boolean enable = true // 插件開關(guān)
    public Boolean autoUpload = false // 是否自動(dòng)上傳
    public Boolean debugOn = false // debug模式是否上傳
}

這些參數(shù)都是可以讓用戶配置的。

在插件里面,我們可以通過(guò)下面這種方式取得參數(shù)的值:

     // 接收外部參數(shù)
     project.extensions.create("beta", BetaExtension)
     def appId = project.beta.appId
     ...

步驟5: 創(chuàng)建Task

我們最終要實(shí)現(xiàn)的是通過(guò)task能夠?qū)pk文件上傳到bugly平臺(tái),代碼實(shí)現(xiàn)如下:

   /**
     * 創(chuàng)建上傳任務(wù)
     *
     * @param variant 編譯參數(shù)
     * @return
     */
    private Task createUploadTask(Object variant) {
        String variantName = variant.name.capitalize()
        Task uploadTask = project.tasks.create("upload${variantName}BetaApkFile") << {
            // if debug model and debugOn = false no execute upload
            if (variantName.contains("Debug") && !project.beta.debugOn) {
                println("Bugly: the option debugOn is closed, if you want to upload apk file on debug model, you can set debugOn = true to open it")
                return
            }
            uploadApk(generateUploadInfo(variant))
        }

        println("Bugly:create upload${variantName}BetaApkFile task")
        return uploadTask
    }

更加具體的代碼細(xì)節(jié),大家可以可以看我開源的代碼。

發(fā)布到JCenter

插件開發(fā)完畢之后,就可以通過(guò)gradle腳本將開發(fā)好的代碼打包上傳到JCenter,基本上步驟跟上傳Library是類似的,完整代碼如下:

apply plugin: 'com.jfrog.bintray'
apply plugin: 'maven-publish'


group = "com.tencent.bugly.plugin"
version = "1.0.2"

def baseUrl = 'https://github.com/BuglyDevTeam'
def siteUrl = baseUrl
def gitUrl = "${baseUrl}/BuglyBetaUploder.git"
def issueUrl = "${baseUrl}/BuglyBetaUploder/issues"

def projectName = "betauploader"
def mavenDesc = 'bugly beta uploader'
def licenseIds = ['Apache-2.0']

install {
    repositories.mavenInstaller {
        // This generates POM.xml with proper parameters
        pom.project {
            // packaging 'jar'
            // Add your description here
            name = 'Upload apk file to bugly platform'
            url siteUrl
            // Set your license
            licenses {
                license {
                    name = 'The Apache Software License, Version 2.0'
                    url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                }
            }
            developers {
                developer {
                    id 'YOUR_ID'
                    name 'YOUR_NAME'
                    email 'YOUR_EMAIL'
                }
            }
            scm {
                connection gitUrl
                developerConnection gitUrl
                url siteUrl
            }
        }
    }
}

task sourcesJar(type: Jar) {
    from 'src/main/groovy'
    exclude 'META-INF'
    classifier = 'sources'
}

groovydoc {
    includePrivate = true
    source = 'src/main/groovy'
}

task groovydocJar(type: Jar, dependsOn: groovydoc) {
    classifier = 'javadoc'
    from groovydoc.destinationDir
}

artifacts {
    archives groovydocJar
    archives sourcesJar
}

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

bintray {
    user = properties.getProperty("bintray.user")
    key = properties.getProperty("bintray.apikey")

    configurations = ['archives']

    pkg {
        repo = 'maven'
        name = projectName
        desc = mavenDesc
        websiteUrl = siteUrl
        issueTrackerUrl = issueUrl
        vcsUrl = gitUrl
        labels = ['gradle', 'com.tencent.bugly.plugin', 'betauploader']
        licenses = licenseIds
        publish = true
        publicDownloadNumbers = true
    }
}

至此,插件就已經(jīng)開發(fā)完畢啦,通過(guò)gradle bintrayUpload的命令將插件上傳到bintray中的maven倉(cāng)庫(kù),然后添加到JCenter倉(cāng)庫(kù)審核即可。

具體的使用方法,可以參考:https://bugly.qq.com/betaGradle

最后

關(guān)于Gradle插件的開發(fā)也告一段落啦,相對(duì)來(lái)說(shuō)這個(gè)插件的功能還比較單一,更加復(fù)雜的插件開發(fā)可以參考其他開源的項(xiàng)目,只要多查多實(shí)踐,相信開發(fā)一個(gè)你自己的插件并不是一件很難的事。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,001評(píng)論 25 709
  • 轉(zhuǎn)載注明出處:http://www.itdecent.cn/p/5255b100930e 0. 前言 完全由個(gè)人翻...
    王三的貓阿德閱讀 2,738評(píng)論 0 4
  • Groovy :是一種動(dòng)態(tài)語(yǔ)言。 1:這種語(yǔ)言比較有特點(diǎn),它和 Java 一樣,也運(yùn)行于 Java 虛擬機(jī)中。簡(jiǎn)單...
    PeytonWu閱讀 1,674評(píng)論 0 1
  • 向往著一場(chǎng)滂沱大雨 可以湮沒所有的痕跡 天地像混沌初開般 渾然一體 不曾有過(guò)任何人的來(lái)去 云天下默然佇立 任世間何...
    長(zhǎng)山n閱讀 273評(píng)論 1 2
  • 開車的都會(huì)有這么一個(gè)感覺!特別討厭路上那些騎電動(dòng)車、騎自行車的。因?yàn)樗齻兙拖裼芯艞l命似的,騎個(gè)車子在大馬路...
    A低調(diào)閱讀 1,234評(píng)論 12 6

友情鏈接更多精彩內(nèi)容