日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

拥抱 Android Studio 之五:Gradle 插件开发

發布時間:2025/3/15 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 拥抱 Android Studio 之五:Gradle 插件开发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實踐出真知

筆者有位朋友。每次新學一門語言,都會用來寫一個貪吃蛇游戲,以此來檢驗自己學習的成果。筆者也有相似體會。所謂紙上得來終覺淺,絕知此事要躬行。這一章。筆者將以開發和公布一個 Gradle 插件作為目標,加深學習成果。

官方文檔給出了比較具體的實現步驟,本文的脈絡會跟官方文檔差不了太多。額外增補實際樣例和一些實踐經驗。文中的代碼已經托管到了 github 項目中。

需求

默認的 Android 打包插件會把 apk 命名成 module-productFlavor-buildType.apk,比如 app-official-debug.apk,而且會把包文件公布到固定的位置: module/build/outputs/apk 有的時候,這個命名風格并非你所要的,你也想講 apk 輸出到別的目錄。咱們通過 gradle 插件來實現自己定義。這個插件的需求是:

  • 輸入一個名為 nameMap 的 Closure。用來改動 apk 名字
  • 輸入一個名為 destDir 的 String,用于輸出位置

原理簡述

插件之于 Gradle

依據官方文檔定義,插件打包了可重用的構建邏輯。能夠適用于不同的項目和構建過程。

Gradle 提供了非常多官方插件。用于支持 Java、Groovy 等工程的構建和打包。同一時候也提供了自己定義插件的機制,讓每個人都能夠通過插件來實現特定的構建邏輯,并能夠把這些邏輯打包起來。分享給其它人。

插件的源代碼能夠使用 Groovy、Scala、Java 三種語言,筆者不會 Scala,所以平時僅僅是使用 Groovy 和 Java。前者用于實現與 Gradle 構建生命周期(如 task 的依賴)有關的邏輯,后者用于核心邏輯。表現為 Groovy 調用 Java 的代碼。

另外,還有非常多項目使用 Eclipse 或者 Maven 進行開發構建,用 Java 實現核心業務代碼,將有利于實現高速遷移。

插件打包方式

Gradle 的插件有三種打包方式。主要是依照復雜程度和可見性來劃分:

Build script

把插件寫在 build.gradle 文件里,一般用于簡單的邏輯,僅僅在該 build.gradle 文件里可見,筆者經常使用來做原型調試。本文將簡要介紹此類。

buildSrc 項目

將插件源代碼放在 rootProjectDir/buildSrc/src/main/groovy 中,僅僅對該項目中可見,適用于邏輯較為復雜,但又不須要外部可見的插件,本文不介紹,有興趣能夠參考此處。

獨立項目

一個獨立的 Groovy 和 Java 項目,能夠把這個項目打包成 Jar 文件包,一個 Jar 文件包還能夠包括多個插件入口,將文件包公布到托管平臺上,供其它人使用。本文將著重介紹此類。

Build script 插件

首先來直接在 build.gradle 中寫一個 plugin:

class ApkDistPlugin implements Plugin<Project> {@Overridevoid apply(Project project) {project.task('apkdist') << {println 'hello, world!'}} }apply plugin: ApkDistPlugin

命令行執行

$ ./gradlew -p app/ apkdist :app:apkdist hello, world!

這個插件創建了一個名為 apkdist 的 task。并在 task 中打印。

插件是一個類,繼承自 org.gradle.api.Plugin 接口,重載 void apply(Project project) 方法。這種方法將會傳入使用這個插件的 project 的實例。這是一個重要的 context。

接受外部參數

通常情況下,插件使用方須要傳入一些配置參數,如 bugtags 的 SDK 的插件須要接受兩個參數:

bugtags {appKey "APP_KEY" //這里是你的 appKeyappSecret "APP_SECRET" //這里是你的 appSecret。管理員在設置頁能夠查看 }

相同,ApkDistPlugin 這個 plugin 也希望接受兩個參數:

apkdistconf {nameMap { name ->println 'hello,' + namereturn name}destDir 'your-distribution-dir' }

參數的內容后面繼續完好。那這兩個參數怎么傳到插件內呢?

org.gradle.api.Project 有一個 ExtensionContainer getExtensions() 方法。能夠用來實現這個傳遞。

聲明參數類

聲明一個 Groovy 類,有兩個默認值為 null 的成員變量:

class ApkDistExtension {Closure nameMap = null;String destDir = null; }

接受參數

project.extensions.create('apkdistconf', ApkDistExtension);

要注意,create 方法的第一個參數就是你在 build.gradle 文件里的進行參數配置的 dsl 的名字,必須一致。第二個參數。就是參數類的名字。

獲取和使用參數

在 create 了 extension 之后,假設傳入了參數,則會攜帶在 project 實例中,

def closure = project['apkdistconf'].nameMap; closure('wow!');println project['apkdistconf'].destDir

進化版本號一:參數

class ApkDistExtension {Closure nameMap = null;String destDir = null; }class ApkDistPlugin implements Plugin<Project> {@Overridevoid apply(Project project) {project.extensions.create('apkdistconf', ApkDistExtension);project.task('apkdist') << {println 'hello, world!'def closure = project['apkdistconf'].nameMap;closure('wow!');println project['apkdistconf'].destDir}} }apply plugin: ApkDistPluginapkdistconf {nameMap { name ->println 'hello, ' + namereturn name}destDir 'your-distribution-directory' }

執行結果:

$ ./gradlew -p app/ apkdist :app:apkdist hello, world! hello, wow! your-distribution-directory

獨立項目插件

代碼寫到如今,已經不適合再放在一個 build.gradle 文件里面了,那也不是我們的目的。

建立一個獨立項目,把代碼搬到相應的地方。

理論上,IntelliJ IDEA 開發插件要比 Android Studio 要方便一點點,由于有相應 Groovy module 的模板。

但事實上假設我們了解 IDEA 的項目文件結構。就不會受到這個局限,無非就是一個 build.gradle 構建文件加 src 源代碼目錄。

最終項目的目錄結構是這樣:

以下我們來一步步解說。

創建項目

在 Android Studio 中新建 Java Library module “plugin”。

改動 build.gradle 文件

加入 Groovy 插件和相應的兩個依賴。

//removed java plugin apply plugin: 'groovy'dependencies {compile gradleApi()//gradle sdkcompile localGroovy()//groovy sdkcompile fileTree(dir: 'libs', include: ['*.jar']) }

改動項目目錄

src/main 項目文件下:

  • 移除 java 目錄,由于在這個項目中用不到 java 代碼
  • 加入 groovy 目錄,基本的代碼文件放在這里
  • 加入 resources 目錄,存放用于標識 gradle 插件的 meta-data

建立相應文件

. ├── build.gradle ├── libs ├── plugin.iml └── src└── main├── groovy│ └── com│ └── asgradle│ └── plugin│ ├── ApkDistExtension.groovy│ └── ApkDistPlugin.groovy└── resources└── META-INF└── gradle-plugins└── com.asgradle.apkdist.properties

注意:

  • groovy 目錄中的類,一定要改動成 .groovy 后綴,IDE 才會正常識別。

  • resources/META-INF/gradle-plugins 這個目錄結構是強制要求的,否則不能識別成插件。

com.asgradle.apkdist.properties 文件

假設寫過 Java 的同學會知道,這是一個 Java 的 properties 文件,是 key=value 的格式。

這個文件內容例如以下:

implementation-class=com.asgradle.plugin.ApkDistPlugin

按其語義判斷,是指定這個插件的入口類。

  • 英文敏感的同學可能會問了,為什么這個文件的承載目錄是叫做 gradle-plugins,使用復數?沒錯,這里能夠指定多個 properties 文件,定義多個插件,擴展性一流。能夠參考 linkedin 的插件的組織方式。
  • 使用這個插件的時候。將會是這樣:

    apply plugin:'com.asgradle.apkdist'

    因此。com.asgradle.apkdist 這個字符串在這里,又稱為這個插件的 id。不同意跟別的插件反復,取你擁有的域名的反向就不會錯。

將 plugin module 傳到本地 maven 倉庫

參考上一篇:擁抱 Android Studio 之四:Maven 倉庫使用與私有倉庫搭建。和相應的 demo 項目,將包傳到本地倉庫中進行測試。

加入 gradle.properties

PROJ_NAME=gradleplugin PROJ_ARTIFACTID=gradleplugin PROJ_POM_NAME=Local RepositoryLOCAL_REPO_URL=file:///Users/changbinhe/Documents/Android/repo/PROJ_GROUP=com.as-gradle.demoPROJ_VERSION=1.0.0 PROJ_VERSION_CODE=1PROJ_WEBSITEURL=http://kvh.io PROJ_ISSUETRACKERURL=https://github.com/kevinho/Embrace-Android-Studio-Demo/issues PROJ_VCSURL=https://github.com/kevinho/Embrace-Android-Studio-Demo.git PROJ_DESCRIPTION=demo apps for embracing android studioPROJ_LICENCE_NAME=The Apache Software License, Version 2.0 PROJ_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt PROJ_LICENCE_DEST=repoDEVELOPER_ID=your-dev-id DEVELOPER_NAME=your-dev-name DEVELOPER_EMAIL=your-email@your-mailbox.com

在 build.gradle 加入上傳功能

apply plugin: 'maven'uploadArchives {repositories.mavenDeployer {repository(url: LOCAL_REPO_URL)pom.groupId = PROJ_GROUPpom.artifactId = PROJ_ARTIFACTIDpom.version = PROJ_VERSION} }

上傳能夠通過執行:

$ ./gradlew -p plugin/ clean build uploadArchives

在 app module 中使用插件

在項目的 buildscript 加入插件作為 classpath

buildscript {repositories {maven{url 'file:///Users/your-user-name/Documents/Android/repo/'}jcenter()}dependencies {classpath 'com.android.tools.build:gradle:2.1.0-alpha3' classpath 'com.as-gradle.demo:gradleplugin:1.0.0'} }

在 app module 中使用插件:

apply plugin: 'com.asgradle.apkdist'

命令行執行:

$ ./gradlew -p app apkdist :app:apkdist hello, world! hello, wow! your-distribution-directory

可能會遇到問題

Error:(46, 0) Cause: com/asgradle/plugin/ApkDistPlugin : Unsupported major.minor version 52.0 <a href="openFile:/Users/your-user-name/Documents/git/opensource/embrace-android-studio-demo/s5-GradlePlugin/app/build.gradle">Open File</a>

應該是本機的 JDK 版本號是1.8。默認將 plugin module 的 groovy 源代碼編譯成了1.8版本號的 class 文件。放在 Android 項目中,無法兼容。須要對 plugin module 的 build.gradle 文件加入兩個參數:

sourceCompatibility = 1.6 targetCompatibility = 1.6

真正的實現插件需求

讀者可能會觀察到,到眼下為止。插件僅僅是跑通了流程,并沒有實現本文提出的兩個需求,

那接下來就具體實現一下。

class ApkDistPlugin implements Plugin<Project> {@Overridevoid apply(Project project) {project.extensions.create('apkdistconf', ApkDistExtension);project.afterEvaluate {//僅僅能夠在 android application 或者 android lib 項目中使用if (!project.android) {throw new IllegalStateException('Must apply \'com.android.application\' or \'com.android.library\' first!')}//配置不能為空if (project.apkdistconf.nameMap == null || project.apkdistconf.destDir == null) {project.logger.info('Apkdist conf should be set!')return}Closure nameMap = project['apkdistconf'].nameMapString destDir = project['apkdistconf'].destDir//枚舉每個 build variantproject.android.applicationVariants.all { variant ->variant.outputs.each { output ->File file = output.outputFileoutput.outputFile = new File(destDir, nameMap(file.getName()))}}}} }

必須指出。本文插件實現的需求。事實上能夠直接在 app module 的 build.gradle 中寫腳本就能夠實現。這里做成插件,僅僅是為了做示范。

上傳到 bintray 的過程,就不再贅述了,能夠參考擁抱 Android Studio 之四:Maven 倉庫使用與私有倉庫搭建。

后記

至此。這系列開篇的時候挖下的坑。最終填完了。

非常多人借助這系列的解說,真正理解了 Android Studio 和它背后的 Gradle、Groovy。筆者十分高興。

筆者也得到了非常多讀者的鼓舞和支持。心中十分感激。

寫博客真的是一個非常講究執行力和耐力的事情,但既然挖下了坑,就得填上,對吧?

這半年來,個人在 Android 和 Java 平臺上也做了很多其它的事情,也有了很多其它的體會。

AS 系列,打算擴充幾個主題:

  • Proguard 混淆
  • Java & Android Testing
  • Maven 私有倉庫深入
  • 持續集成
  • ……待發掘

記得有人說,僅僅懂 Android 不懂 Java,是非常可怕的。在這半年以來。筆者在工作中使用 Java 實現了一些后端服務,也認真學習了 JVM 字節碼相關的知識并把它使用到了工作中。在這個過程中,真的非常為 Java 平臺的活力、豐富的庫資源、差點兒無止境的可能性所折服。接下來,會寫一些跟有關的學習體會,比如:

  • Java 多線程與鎖
  • JVM 部分原理
  • 字節碼操作
  • Java 8部分特性
  • ……待學習

隨著筆者工作的進展,我也有機會學習使用了別的語言,比如 Node.js。并實現了一些后端服務。這個語言的活力非常強。一些比 Java 現代的地方,非常吸引人。

有精力會寫一寫。

由于業務所需。筆者所經歷的系統,正在處于像面向服務的演化過程中,我們期望建立統一的通訊平臺和規范,抽象系統的資源,拆分業務。容器化。這是一個非常有趣的過程,也是對我們的挑戰。

筆者也希望有機會與讀者分享。

一不小心又挖下了好多明坑和無數暗坑,僅僅是為了激勵自己不斷往前。

在探索事物本質的旅途中。必定十分艱險,又十分有趣,沿途一定風光絢麗,讓我們共勉。

參考文獻

官方文檔

系列導讀

本文是筆者《擁抱 Android Studio》系列第四篇。其它篇請點擊:

擁抱 Android Studio 之中的一個:從 ADT 到 Android Studio

擁抱 Android Studio 之二:Android Studio 與 Gradle 深入

擁抱 Android Studio 之三:溯源,Groovy 與 Gradle 基礎

擁抱 Android Studio 之四:Maven 公共倉庫使用與私有倉庫搭建

擁抱 Android Studio 之五:Gradle 插件使用與開發

有問題?在文章下留言或者加 qq 群:453503476,希望能幫到你。

番外

筆者 kvh 在開發和運營 bugtags.com,這是一款移動時代首選的 bug 管理系統,能夠極大的提升 app 開發人員的測試效率,歡迎使用、轉發推薦。

筆者眼下關注點在于移動 SDK 研發。后端服務設計和實現。

我們團隊長期求 PHP 后端研發,有興趣請加以下公眾號勾搭:

?

轉載于:https://www.cnblogs.com/llguanli/p/8410021.html

總結

以上是生活随笔為你收集整理的拥抱 Android Studio 之五:Gradle 插件开发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。