Android Gradle插件開發

文章目錄

    • 1. Gradle插件是什么
    • 2. 為什么需要插件
    • 3. 編寫插件位置
    • 4. 編寫插件
    • 5. 自定義插件擴展
      • 5.1 訂閱擴展對象
      • 5.2 把擴展添加給Plugin并使用
      • 5.3 配置參數
      • 5.4 嵌套擴展
        • 5.4.1 定義擴展
        • 5.4.2 獲取擴展屬性
        • 5.4.3 使用
        • 5.4.4 執行
        • 5.4.5 輸出
    • 6. 編寫在單獨項目里
      • 6.1 新建Module
      • 6.2 新建文件添加依賴
        • 6.2.1 添加依賴
        • 6.2.2 新建類
      • 6.3 本地發布
        • 6.3.1 Maven插件
        • 6.3.2 發布配置
        • 6.3.3 執行發布操作
      • 6.4 使用
      • 6.5 具體功能實現

1. Gradle插件是什么

Gradle插件(Plugin)是一種用于擴展和定制Gradle構建系統功能的機制。Gradle插件可以執行各種任務,包括編譯代碼、執行測試、打包文件、生成文檔等等。插件可以訪問和操作Gradle的構建模型,如項目、任務、依賴關系等等,從而實現對構建過程的控制和定制。
許多流行的工具和框架,例如Kotlin,Spring Boot,Android都有相應的Gradle插件。
比如熟悉的Android插件com.android.application

plugins {id 'com.android.application'
}

2. 為什么需要插件

  • 定制:如果需要在編譯期做一些插樁,Hook之類的自定義操作,也需要用到編譯插件
  • 封裝:把具體的邏輯抽出去,只需運行插件,不需要寫在某個build.gradle文件中
  • 復用:把通用的邏輯抽離出去,需要用的時候apply應用插件即可,不需要一遍遍的復制,也可以提供給別的項目使用

3. 編寫插件位置

  • 寫在build.gradle文件中,作用域當前project
  • 寫在buildSrc里,作用域為當前項目所有
  • 寫在單獨項目里,發布后可提供給所有項目

4. 編寫插件

編寫一個插件Plugin,只需要實現Plugin接口,并實現唯一apply方法即可。
在build.gradle文件中

class YiRanPlugin implements Plugin<Project>{@Overridevoid apply(Project target) {println("this is plugin ${this.class.name}")}
}apply plugin: YiRanPlugin

apply方法是調用的PluginAware接口的apply()方法,參數是一個map,用來映射Plugin id

點擊sync,輸出結果
在這里插入圖片描述
Task是Project里的方法,我們可以通過Project取創建一個Task,apply方法中提供了Project對象,可以通過Plugin去創建一個Task

class YiRanPlugin implements Plugin<Project>{@Overridevoid apply(Project target) {println("this is plugin ${this.class.name}")target.task("YiRanPluginTask"){task ->task.doLast{println("this is Plugin ${this.class.name},create a task ${task.name}")}}}
}apply plugin: YiRanPlugin

我們在Plugin里創建了一個Task,這時候sync是不會執行Task里面打印的東西,因為是doLast在 task 執?過程中被執?,發?在 execution 階段。因此需要單獨執行

./gradlew YiRanPluginTask    

輸出

> Configure project :app
this is plugin YiRanPlugin> Task :app:YiRanPluginTask
this is Plugin YiRanPlugin,create a task YiRanPluginTask

當我們依賴YiRanPlugin插件的時候,這個apply就會把插件放到PluginContainer里,同時這個apply也是在編譯階段執行Plugin接口的apply()方法,所有sync同步后構建會有輸出。

5. 自定義插件擴展

自定義插件的時候經常會有這種自定義配置的需求,通過自定義的配置可以讓我們的插件提供更豐富的能力。這些配置就是通過擴展插件來的。

5.1 訂閱擴展對象

可以是一個接口,也可以是一個類

interface YiRanPluginExtension{Property<String> getTitle()
}

5.2 把擴展添加給Plugin并使用

class YiRanPlugin implements Plugin<Project>{@Overridevoid apply(Project target) {println("this is plugin ${this.class.name}")def extension = target.extensions.create("YiRan",YiRanPluginExtension)target.task("YiRanPluginTask"){task ->task.doLast{println("this is Plugin ${this.class.name},create a task ${task.name}")println("-------")println(extension.title.get())}}}
}

target.extensions.create方法接收兩個參數:

  • 1.名字,比如android,YiRan
  • 2.擴展對象,然后返回這個擴展對象,通過這個擴展對象的方法可以獲取自定義的配置參數

5.3 配置參數

有兩種方式可以寫

YiRan.title = "YiRan"
YiRan{title = "YiRan"
}

如果沒有設置配置參數的話,Gradle也提供了默認值的配置

extension.title.convention("YiRan")

5.4 嵌套擴展

向我們app目錄下的build.gradle文件中,android{}里面還有defaultConfig{}

android {namespace 'com.example.gradlestudy'compileSdk 35defaultConfig {applicationId "com.example.gradlestudy"minSdk 24targetSdk 34versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}
}

嵌套擴展其實就是套娃

5.4.1 定義擴展
class YiRanPluginExtension{String titleint chapterNumSubExtension subExtensionYiRanPluginExtension(Project project){subExtension = project.extensions.create("sub",SubExtension.class)}
}class SubExtension{String author
}

增加定義了一個SubExtension類,然后在YiRanPluginExtension實例化的時候加到ExtensionContainer中。
類嵌套的話,不能寫成內部類,不然編譯識別不過。

5.4.2 獲取擴展屬性
class YiRanPlugin implements Plugin<Project>{@Overridevoid apply(Project target) {println("this is Plugin:${this.class.name}")def extension = target.extensions.create("YiRan",YiRanPluginExtension)target.task("YiRanTaskPluginTask"){ task ->task.doLast{println("this is Plugin ${this.class.name},create a task ${task.name}")println("title = ${extension.title}")println("chapter = ${extension.chapterNum}")println("author = ${extension.subExtension.author}")}}}
}

可以看到和上面的例子,少了Property對象的.get()方法,如果需要的話,在類對象定義即可,例如
增加setter/getter方法

class YiRanPluginExtension{String titleint chapterNumSubExtension subExtensionYiRanPluginExtension(Project project){subExtension = project.extensions.create("sub",SubExtension.class)}void setTitle(String name){title = name}String getTitle(){return title}
}

使用的時候

extension.setTitle("調用get方法")
extension.getTitle()
5.4.3 使用
YiRan{title = "測試一下"chapterNum = 100sub{author = "YiRan"}
}

閉包配置中多了一個sub{}的閉包,就是在YiRanPluginExtension類中定義的

5.4.4 執行
./gradlew YiRanTaskPluginTask       
5.4.5 輸出

在這里插入圖片描述

6. 編寫在單獨項目里

上面的例子,我們的Plugin是寫在build.gradle文件中,而在實際項目中,為了復用,一般都是寫在buildSrc或者單獨項目中。
測試寫一個打印項目中所有依賴的插件

6.1 新建Module

類型選擇Library,或下面的Java or Kotlin Library
在這里插入圖片描述

6.2 新建文件添加依賴

6.2.1 添加依賴

在plugin>build.gradle文件中依賴插件:

//java、gradleApi()依賴
apply plugin:'java-gradle-plugin'
//kotlin
apply plugin: 'org.jetbrains.kotlin.jvm'
6.2.2 新建類

新建一個DependenciesPlugin類
在這里插入圖片描述

6.3 本地發布

6.3.1 Maven插件

在plugin>build.gradle文件中先依賴一個maven發布的插件’maven-publish’

apply plugin: 'maven-publish'dependencies {implementation 'com.android.tools.build:gradle:8.6.1'}
6.3.2 發布配置

添加發布配置


group 'com.example.plugin'
version '1.0.1'publishing {//配置Plugin GAVpublications {maven(MavenPublication){groupId = groupartifactId = 'dependencies'version = version}}//配置倉庫地址repositories {maven {url layout.buildDirectory.dir("maven-repo")}}
}
6.3.3 執行發布操作
./gradlew publish

build文件夾下生成有本地發布配置的maven-repo文件夾
在這里插入圖片描述

6.4 使用

1.settings.gradle文件中配置倉庫地址

pluginManagement {repositories {// ...maven {url './plugin/build/maven-repo'}
}
}
dependencyResolutionManagement {repositories {// ...maven {url './plugin/build/maven-repo'}}
}

libs.versions.toml中添加插件依賴

[plugins]
//-----
dependencies = { id = "com.example.plugin.dependencies", version.ref = "dependencies" }

app目錄build.gradle引入

plugins {
//------alias(libs.plugins.dependencies)
}

本地依賴使用的時候,要先發布,再依賴插件,否則就會出現cannot found找不到依賴的情況。
編譯查看效果

> Configure project :app
---> com.example.plugin.DependenciesPlugin

能夠正確打印

6.5 具體功能實現

上面只是一個打印,繼續實現我們的功能,把所有的依賴打印出來。
打印依賴的方式有很多,比如可以使用Gradle命令

./gradlew app:dependencies

改造Plugin

package com.example.pluginimport com.android.build.gradle.AppExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ModuleVersionIdentifierclass DependenciesPlugin:Plugin<Project> {companion object{const val TAG = "DependenciesPlugin  >>>>>"}override fun apply(target: Project) {println("---> ${this.javaClass.name}")//獲取擴展對象val extension:DependenciesPluginExtension = target.extensions.create("printDependencies",DependenciesPluginExtension::class.java)//配置階段完成才能讀取參數,才能拿到所有依賴target.afterEvaluate {extension.getEnable.convention(false)if(extension.getEnable.get()){println("$TAG 已開啟依賴打印")val androidExtension:AppExtension = target.extensions.getByType(AppExtension::class.java)androidExtension.applicationVariants.all { applicationVariant->println("$TAG >>>>>> applicationVariant.getName() = ${applicationVariant.name}")val configuration:Configuration = applicationVariant.compileConfigurationval allDependencies:Set<Dependency> = configuration.allDependenciesval androidLibs = ArrayList<String>()val otherLibs = ArrayList<String>()configuration.resolvedConfiguration.lenientConfiguration.allModuleDependencies.forEach {resolvedDependency ->val identifier: ModuleVersionIdentifier = resolvedDependency.module.idif(identifier.group.contains("androidx")||identifier.group.contains("com.google")||identifier.group.contains("org.jetbrains")){androidLibs.add(identifier.group+":"+identifier.name+":"+identifier.version)}else{otherLibs.add(identifier.group+":"+identifier.name+":"+identifier.version)}}println("--------------官方庫 start--------------");androidLibs.forEach(System.out::println);println("--------------官方庫 end--------------");println("--------------三方庫 start--------------");otherLibs.forEach(System.out::println);println("--------------三方庫 end--------------");}}else{println("$TAG 已關閉依賴打印")}}}
}

project.afterEvaluate方法中去獲取擴展配置,因為apply plugin的執行時機早于擴展配置,否則獲取不到擴展配置的值
擴展:

package com.example.pluginimport org.gradle.api.provider.Propertyinterface DependenciesPluginExtension {val getEnable:Property<Boolean>}

使用:

printDependencies {setGetEnable(true)
}

編譯輸出:
在這里插入圖片描述
通過獨立項目中定義插件,把所有依賴的區分打印出來了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77946.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77946.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77946.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PPIO X OWL:一鍵開啟任務自動化的高效革命

2024年&#xff0c;僅憑一PPIO X OWL&#xff1a;一鍵開啟任務自動化的高效革命篇技術論文&#xff0c;OWL的Github倉庫便在24小時斬獲了15k Star&#xff0c;成為2024年增速最快的多智能體協作框架&#xff0c;重新定義了任務自動化的效率邊界。Camel AI團隊開源全棧方案&…

分布式事務,事務失效,TC事務協調者

1. 概述 本方案書旨在解決分布式系統中事務一致性問題&#xff0c;重點闡述全局事務標識&#xff08;XID&#xff09;的傳遞與存儲機制、事務協調者&#xff08;TC&#xff09;的設計與部署&#xff0c;以及分布式事務失效場景的應對策略。基于業界成熟框架&#xff08;如Seat…

2025年“深圳杯”數學建模挑戰賽D題-法醫物證多人身份鑒定問題

法醫物證多人身份鑒定問題 小驢數模 犯罪現場法醫物證鑒定是關系到國家安全、公共安全、人民生命財產安全和社會穩定的重大問題。目前法醫物證鑒定依賴DNA分析技術不斷提升。DNA檢驗的核心是STR&#xff08;Short Tandem Repeat&#xff0c;短串聯重復序列&#xff09;分析技術…

Mysql查詢異常【Truncated incorrect INTEGER value】

文章目錄 異常原因分析1、數據類型不一致2、數據長度超長3、數據格式要正確 處理方案模擬案例創建表數據查詢 異常 在執行MySQL的語句時&#xff0c;在控制臺報錯如下所示。 Data truncation: Truncated incorrect INTEGER value 原因分析 1、數據類型不一致 必須要保證數據…

WPF性能優化舉例

WPF性能優化集錦 一、UI渲染性能優化 1. 虛擬化技術 ??ListView/GridView虛擬化??: <ListView VirtualizingStackPanel.IsVirtualizing="True"VirtualizingStackPanel.VirtualizationMode="Recycling"ScrollViewer.IsDeferredScrollingEnabled=…

C# 面向對象實例演示

C# 面向對象編程實例演示 一、基礎概念回顧 面向對象編程(OOP)的四大基本特性&#xff1a; ??封裝?? - 將數據和操作數據的方法綁定在一起??繼承?? - 創建新類時重用現有類的屬性和方法??多態?? - 同一操作作用于不同對象產生不同結果??抽象?? - 簡化復雜系…

大連理工大學選修課——機器學習筆記(3):KNN原理及應用

KNN原理及應用 機器學習方法的分類 基于概率統計的方法 K-近鄰&#xff08;KNN&#xff09;貝葉斯模型最小均值距離最大熵模型條件隨機場&#xff08;CRF&#xff09;隱馬爾可夫模型&#xff08;HMM&#xff09; 基于判別式的方法 決策樹&#xff08;DT&#xff09;感知機…

蔣新松:中國機器人之父

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 蔣新松:中國機器人之父 一、生平簡介 1. 早年經歷與求學道路 蔣新松出生于1931年8月3日,江蘇省江陰澄北鎮一個靠近長江的小鎮。他的名字來源于杜…

表征(Representations)、嵌入(Embeddings)及潛空間(Latent space)

文章目錄 1. 表征 (Representations)2. 嵌入 (Embeddings)3. 潛空間 (Latent Space)4. 關系總結5. 學習思考 1. 表征 (Representations) 定義: 表征是指數據的一種編碼或描述形式。在機器學習和深度學習中&#xff0c;它特指模型在處理數據時&#xff0c;將原始輸入數據轉換成…

【STM32實物】基于STM32的RFID多卡識別語音播報系統設計

演示視頻: 基于STM32的RFID多卡識別語音播報系統設計 前言:本項目可實現多個電子標簽IC卡RFID識別,刷卡識別后進行中文語音播報反饋,同時進行控制對應的燈光開關。以此也可擴展開發更多功能。 本項目所需主要硬件包括:STM32F103C8T6最小系統板、RFID-RC522模塊、五個IC電…

全面了解CSS語法 ! ! !

CSS&#xff08;層疊樣式表&#xff09;是網頁設計的靈魂之一&#xff0c;它賦予了網頁活力與美感。無論是為一個簡單的個人博客增添色彩&#xff0c;還是為復雜的企業網站設計布局&#xff0c;CSS都是不可或缺的工具。那么&#xff0c;CSS語法到底是什么樣的呢&#xff1f;它背…

青少年抑郁癥患者亞群結構和功能連接耦合的重構

目錄 1 研究背景及目的 2 研究方法 2.1 數據來源與參與者 2.1.1 MDD患者&#xff1a; 2.1.2 健康對照組&#xff1a; 2.2 神經影像分析流程 2.2.1 圖像采集與預處理&#xff1a; 2.2.2 網絡構建&#xff1a; 2.2.3 區域結構-功能耦合&#xff08;SC-FC耦合&#xff09…

【QT】編寫第一個 QT 程序 對象樹 Qt 編程事項 內存泄露問題

目錄 1. 編寫第一個 QT 程序 1.1 使用 標簽 實現 1.2 純代碼形式實現 1.3 使用 按鈕 實現 1.3.1 圖形化界面實現 1.3.2 純代碼形式實現 1.4 使用 編輯框 實現 1.4.1 圖形化界面實現 1.4.2 純代碼形式實現 1.4.3 內存泄露 2. 認識對象模型&#xff08;對象樹&…

在pycharm中創建Django項目并啟動

Django介紹 Django 是一個基于 Python 的開源 Web 應用框架&#xff0c;采用了 MTV&#xff08;Model - Template - View&#xff09;軟件設計模式 &#xff0c;由許多功能強大的組件組成&#xff0c;能夠幫助開發者快速、高效地創建復雜的數據庫驅動的 Web 應用程序。它具有以…

在Carla中構建自動駕駛:使用PID控制和ROS2進行路徑跟蹤

機器人軟件開發什么是 P、PI 和 PID 控制器&#xff1f;比例 &#xff08;P&#xff09; 控制器比例積分 &#xff08;PI&#xff09; 控制器比例-積分-微分 &#xff08;PID&#xff09; 控制器橫向控制簡介CARLA ROS2 集成縱向控制橫向控制關鍵要點結論引用 機器人軟件開發 …

【KWDB 創作者計劃】_深度解析KWDB存儲引擎

文章目錄 每日一句正能量引言一、存儲引擎核心模塊結構二、寫前日志 WAL&#xff08;Write-Ahead Log&#xff09;三、列式壓縮存儲&#xff08;Columnar Compression&#xff09;四、索引機制與混合查詢調度五、分布式核心功能&#xff1a;租約管理實戰六、時間序列數據處理&a…

Apache Tomcat 漏洞(CVE-2025-24813)導致服務器面臨 RCE 風險

CVE-2025-24813Apache Tomcat 中發現了一個嚴重安全漏洞,標識為,該漏洞可能導致服務器面臨遠程代碼執行 (RCE)、信息泄露和數據損壞的風險。 此缺陷影響以下版本: Apache Tomcat11.0.0-M1通過11.0.2Apache Tomcat10.1.0-M1通過10.1.34Apache Tomcat9.0.0-M1通過9.0.98了解 …

全面解析SimHash算法:原理、對比與Spring Boot實踐指南

一、SimHash算法概述 SimHash是一種局部敏感哈希算法&#xff0c;由Google工程師Moses Charikar提出&#xff0c;主要用于海量文本的快速去重與相似度檢測。其核心思想是將高維特征向量映射為固定長度的二進制指紋&#xff08;如64位&#xff09;&#xff0c;通過計算指紋間的…

臨床回歸分析及AI推理

在醫療保健決策越來越受數據驅動的時代&#xff0c;回歸分析已成為臨床醫生和研究人員最強大的工具之一。無論是預測結果、調整混雜因素、建模生存時間還是理解診斷性能&#xff0c;回歸模型都為將原始數據轉化為臨床洞察提供了統計學基礎。 AI推理 然而&#xff0c;隨著技術…

西門子PLC S7-1200 電動機的軟啟動控制

1 PWM 控制的基本概念 PWM 是 PulseWidth Modulation 的簡稱。 PWM 控制是一種脈沖寬度調制技術,通過對一系列脈沖的寬度進行調制來等效獲得所需要的波形(含形狀和幅值)。PWM 控制技術在逆變電路中應用比較廣泛,所應用的逆變電路絕大部分是PWM 型。除此之外, PWM 控制技術…