├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── plugin ├── build.gradle.kts ├── gradle │ └── wrapper ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ └── org │ └── sample │ ├── GreetingExtension.kt │ ├── GreetingPlugin.kt │ └── GreetingTask.kt ├── renovate.json ├── sample ├── build.gradle.kts └── src │ └── main │ ├── AndroidManifest.xml │ ├── kotlin │ └── org │ │ └── sample │ │ └── app │ │ ├── MainActivity.kt │ │ └── MyApplication.kt │ └── res │ └── values │ └── strings.xml └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/kotlinc.xml 2 | 3 | # Kotlin 4 | .kotlin 5 | 6 | # Created by https://www.toptal.com/developers/gitignore/api/macos,android,windows,androidstudio,intellij 7 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,android,windows,androidstudio,intellij 8 | 9 | ### Android ### 10 | # Gradle files 11 | .gradle/ 12 | build/ 13 | 14 | # Local configuration file (sdk path, etc) 15 | local.properties 16 | 17 | # Log/OS Files 18 | *.log 19 | 20 | # Android Studio generated files and folders 21 | captures/ 22 | .externalNativeBuild/ 23 | .cxx/ 24 | *.apk 25 | output.json 26 | 27 | # IntelliJ 28 | *.iml 29 | #.idea/ 30 | 31 | # Keystore files 32 | *.jks 33 | *.keystore 34 | 35 | # Google Services (e.g. APIs or Firebase) 36 | google-services.json 37 | 38 | # Android Profiling 39 | *.hprof 40 | 41 | ### Android Patch ### 42 | gen-external-apklibs 43 | 44 | # Replacement of .externalNativeBuild directories introduced 45 | # with Android Studio 3.5. 46 | 47 | ### Intellij ### 48 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 49 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 50 | 51 | # User-specific stuff 52 | .idea/**/workspace.xml 53 | .idea/**/tasks.xml 54 | .idea/**/usage.statistics.xml 55 | .idea/**/dictionaries 56 | .idea/**/shelf 57 | 58 | # AWS User-specific 59 | .idea/**/aws.xml 60 | 61 | # Generated files 62 | .idea/**/contentModel.xml 63 | 64 | # Sensitive or high-churn files 65 | .idea/**/dataSources/ 66 | .idea/**/dataSources.ids 67 | .idea/**/dataSources.local.xml 68 | .idea/**/sqlDataSources.xml 69 | .idea/**/dynamic.xml 70 | .idea/**/uiDesigner.xml 71 | .idea/**/dbnavigator.xml 72 | 73 | # Gradle 74 | .idea/**/gradle.xml 75 | .idea/**/libraries 76 | 77 | # Gradle and Maven with auto-import 78 | # When using Gradle or Maven with auto-import, you should exclude module files, 79 | # since they will be recreated, and may cause churn. Uncomment if using 80 | # auto-import. 81 | .idea/artifacts 82 | .idea/compiler.xml 83 | .idea/jarRepositories.xml 84 | .idea/modules.xml 85 | .idea/*.iml 86 | .idea/modules 87 | *.iml 88 | *.ipr 89 | 90 | # CMake 91 | cmake-build-*/ 92 | 93 | # Mongo Explorer plugin 94 | .idea/**/mongoSettings.xml 95 | 96 | # File-based project format 97 | *.iws 98 | 99 | # IntelliJ 100 | out/ 101 | 102 | # mpeltonen/sbt-idea plugin 103 | .idea_modules/ 104 | 105 | # JIRA plugin 106 | atlassian-ide-plugin.xml 107 | 108 | # Cursive Clojure plugin 109 | .idea/replstate.xml 110 | 111 | # SonarLint plugin 112 | .idea/sonarlint/ 113 | 114 | # Crashlytics plugin (for Android Studio and IntelliJ) 115 | com_crashlytics_export_strings.xml 116 | crashlytics.properties 117 | crashlytics-build.properties 118 | fabric.properties 119 | 120 | # Editor-based Rest Client 121 | .idea/httpRequests 122 | 123 | # Android studio 3.1+ serialized cache file 124 | .idea/caches/build_file_checksums.ser 125 | 126 | ### Intellij Patch ### 127 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 128 | 129 | # *.iml 130 | # modules.xml 131 | # .idea/misc.xml 132 | # *.ipr 133 | 134 | # Sonarlint plugin 135 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 136 | .idea/**/sonarlint/ 137 | 138 | # SonarQube Plugin 139 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 140 | .idea/**/sonarIssues.xml 141 | 142 | # Markdown Navigator plugin 143 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 144 | .idea/**/markdown-navigator.xml 145 | .idea/**/markdown-navigator-enh.xml 146 | .idea/**/markdown-navigator/ 147 | 148 | # Cache file creation bug 149 | # See https://youtrack.jetbrains.com/issue/JBR-2257 150 | .idea/$CACHE_FILE$ 151 | 152 | # CodeStream plugin 153 | # https://plugins.jetbrains.com/plugin/12206-codestream 154 | .idea/codestream.xml 155 | 156 | ### macOS ### 157 | # General 158 | .DS_Store 159 | .AppleDouble 160 | .LSOverride 161 | 162 | # Icon must end with two \r 163 | Icon 164 | 165 | 166 | # Thumbnails 167 | ._* 168 | 169 | # Files that might appear in the root of a volume 170 | .DocumentRevisions-V100 171 | .fseventsd 172 | .Spotlight-V100 173 | .TemporaryItems 174 | .Trashes 175 | .VolumeIcon.icns 176 | .com.apple.timemachine.donotpresent 177 | 178 | # Directories potentially created on remote AFP share 179 | .AppleDB 180 | .AppleDesktop 181 | Network Trash Folder 182 | Temporary Items 183 | .apdisk 184 | 185 | ### Windows ### 186 | # Windows thumbnail cache files 187 | Thumbs.db 188 | Thumbs.db:encryptable 189 | ehthumbs.db 190 | ehthumbs_vista.db 191 | 192 | # Dump file 193 | *.stackdump 194 | 195 | # Folder config file 196 | [Dd]esktop.ini 197 | 198 | # Recycle Bin used on file shares 199 | $RECYCLE.BIN/ 200 | 201 | # Windows Installer files 202 | *.cab 203 | *.msi 204 | *.msix 205 | *.msm 206 | *.msp 207 | 208 | # Windows shortcuts 209 | *.lnk 210 | 211 | ### AndroidStudio ### 212 | # Covers files to be ignored for android development using Android Studio. 213 | 214 | # Built application files 215 | *.ap_ 216 | *.aab 217 | 218 | # Files for the ART/Dalvik VM 219 | *.dex 220 | 221 | # Java class files 222 | *.class 223 | 224 | # Generated files 225 | bin/ 226 | gen/ 227 | 228 | # Gradle files 229 | .gradle 230 | 231 | # Signing files 232 | .signing/ 233 | 234 | # Local configuration file (sdk path, etc) 235 | 236 | # Proguard folder generated by Eclipse 237 | proguard/ 238 | 239 | # Log Files 240 | 241 | # Android Studio 242 | /*/build/ 243 | /*/local.properties 244 | /*/out 245 | /*/*/build 246 | /*/*/production 247 | .navigation/ 248 | *.ipr 249 | *~ 250 | *.swp 251 | 252 | # Keystore files 253 | 254 | # Google Services (e.g. APIs or Firebase) 255 | # google-services.json 256 | 257 | # Android Patch 258 | 259 | # External native build folder generated in Android Studio 2.2 and later 260 | .externalNativeBuild 261 | 262 | # NDK 263 | obj/ 264 | 265 | # IntelliJ IDEA 266 | /out/ 267 | 268 | # User-specific configurations 269 | .idea/caches/ 270 | .idea/libraries/ 271 | .idea/shelf/ 272 | .idea/workspace.xml 273 | .idea/tasks.xml 274 | .idea/.name 275 | .idea/compiler.xml 276 | .idea/copyright/profiles_settings.xml 277 | .idea/encodings.xml 278 | .idea/misc.xml 279 | .idea/modules.xml 280 | .idea/scopes/scope_settings.xml 281 | .idea/dictionaries 282 | .idea/vcs.xml 283 | .idea/jsLibraryMappings.xml 284 | .idea/datasources.xml 285 | .idea/dataSources.ids 286 | .idea/sqlDataSources.xml 287 | .idea/dynamic.xml 288 | .idea/uiDesigner.xml 289 | .idea/assetWizardSettings.xml 290 | .idea/gradle.xml 291 | .idea/jarRepositories.xml 292 | .idea/navEditor.xml 293 | 294 | # OS-specific files 295 | .DS_Store? 296 | 297 | # Legacy Eclipse project files 298 | .classpath 299 | .project 300 | .cproject 301 | .settings/ 302 | 303 | # Mobile Tools for Java (J2ME) 304 | .mtj.tmp/ 305 | 306 | # Package Files # 307 | *.war 308 | *.ear 309 | 310 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 311 | hs_err_pid* 312 | 313 | ## Plugin-specific files: 314 | 315 | # mpeltonen/sbt-idea plugin 316 | 317 | # JIRA plugin 318 | 319 | # Mongo Explorer plugin 320 | .idea/mongoSettings.xml 321 | 322 | # Crashlytics plugin (for Android Studio and IntelliJ) 323 | 324 | ### AndroidStudio Patch ### 325 | 326 | !/gradle/wrapper/gradle-wrapper.jar 327 | 328 | # End of https://www.toptal.com/developers/gitignore/api/macos,android,windows,androidstudio,intellij 329 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Gradle Plugin Template 2 | 3 | Template repository for modern Android Gradle Plugin Project. 4 | 5 | * Kotlin 2.1.10 6 | * Android Gradle Plugin 8.9.1 7 | * Sample App's compileSdk = 35 (Android 15) 8 | * Sample App's minSdk = 29 (Android 10) 9 | * Gradle 8.13 10 | * Version Catalog 11 | * Kotlin DSL (*.kts) 12 | * pluginManagement / dependencyResolutionManagement (settings.gradle.kts) 13 | * Composite Build 14 | * Gradle Plugin Publish Plugin 15 | * Gradle Signing Plugin 16 | 17 | ## Publish Plugin 18 | 19 | docs: https://docs.gradle.org/8.7/userguide/publishing_gradle_plugins.html 20 | 21 | * register Maven Plugin Portal Account 22 | * https://plugins.gradle.org/user/register 23 | * Using login with Github account is recommended to use `io.github.{user}.{plugin}` plugin id. 24 | 25 | Set your API Key and signing key to gradle.properties, or specify it as command line arguments. 26 | 27 | `~/.gradle/gradle.properties` 28 | 29 | ```properties 30 | gradle.publish.key=... 31 | gradle.publish.secret=... 32 | signingKey="-----BEGIN PGP PRIVATE KEY BLOCK-----\ 33 | \ 34 | ...\ 35 | -----END PGP PRIVATE KEY BLOCK-----\ 36 | " 37 | signingPassword=... 38 | ``` 39 | 40 | Configure your plugin publications. 41 | 42 | Plugin id must have your owned domain or `io.github.{user}`. see this 43 | document: https://plugins.gradle.org/docs/publish-plugin#approval 44 | 45 | `plugin/build.gradle.kts` 46 | 47 | ```kotlin 48 | group = 49 | "io.github.{user}.{plugin name}" // maven artifact groupId, it's recommended to same as plugin id. 50 | version = "0.1.0" 51 | 52 | gradlePlugin { 53 | website = "https://github.com/example/example" 54 | vcsUrl = "https://github.com/example/example" 55 | plugins { 56 | create("plugin") { // unique name in your config 57 | id = "io.github.{user}.{plugin name}" // plugin id 58 | displayName = "Sample Plugin" 59 | description = "A Sample Plugin" 60 | tags = listOf("example") 61 | implementationClass = "org.sample.GreetingPlugin" 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | publish command 68 | 69 | ```shell 70 | ./gradle :plugin:publishPlugins 71 | ``` 72 | 73 | or command with API Key args 74 | 75 | ```shell 76 | ./gardlew :plugin:publishPlugins -Pgradle.publish.key= -Pgradle.publish.secret= 77 | ``` 78 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension 2 | 3 | plugins { 4 | alias(libs.plugins.android.application) apply false 5 | alias(libs.plugins.kotlin.android) apply false 6 | alias(libs.plugins.kotlin.jvm) apply false 7 | alias(libs.plugins.compose.compiler) apply false 8 | } 9 | 10 | subprojects { 11 | afterEvaluate { 12 | extensions.findByType()?.apply { 13 | jvmToolchain(libs.versions.gradle.jvmToolchain.get().toInt()) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | org.gradle.jvmargs=-Xmx16g -XX:MaxMetaspaceSize=8g 3 | org.gradle.parallel=true 4 | org.gradle.caching=true 5 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | sampleplugin = "0.1.0" 3 | kotlin = "2.1.10" 4 | gradle-android = "8.9.1" 5 | gradle-jvmToolchain = "21" 6 | 7 | [libraries] 8 | kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } 9 | android-gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle-android" } 10 | androidx-appcompat = { module = "androidx.appcompat:appcompat", version = "1.7.0" } 11 | androidx-lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version = "2.8.3" } 12 | compose-bom = { group = "androidx.compose", name = "compose-bom", version = "2025.04.00" } 13 | compose-activity = { module = "androidx.activity:activity-compose", version = "1.10.0" } 14 | compose-material3 = { module = "androidx.compose.material3:material3" } 15 | compose-uiTooling = { module = "androidx.compose.ui:ui-tooling" } 16 | 17 | [bundles] 18 | compose = ["compose-activity", "compose-material3", "compose-uiTooling"] 19 | 20 | [plugins] 21 | kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 22 | kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 23 | compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } 24 | android-application = { id = "com.android.application", version.ref = "gradle-android" } 25 | android-library = { id = "com.android.library", version.ref = "gradle-android" } 26 | publish = { id = "com.gradle.plugin-publish", version = "1.3.0" } 27 | sampleplugin = { id = "org.sample.plugin", version.ref = "sampleplugin" } 28 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/irgaly/android-gradle-plugin-template/991d995767602a7fb2596644d2fbeeb4bceafdb4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | org.gradle.wrapper.GradleWrapperMain \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.kotlin.jvm) 3 | alias(libs.plugins.publish) 4 | signing 5 | } 6 | 7 | group = "org.sample.plugin" 8 | version = libs.versions.sampleplugin.get() 9 | 10 | gradlePlugin { 11 | website = "https://github.com/example/example" 12 | vcsUrl = "https://github.com/example/example" 13 | plugins { 14 | create("plugin") { 15 | id = "org.sample.plugin" 16 | displayName = "Sample Plugin" 17 | description = "A Sample Plugin" 18 | tags = listOf("example") 19 | implementationClass = "org.sample.GreetingPlugin" 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | compileOnly(gradleKotlinDsl()) 26 | implementation(libs.kotlin.gradle) 27 | implementation(libs.android.gradle) 28 | } 29 | 30 | kotlin { 31 | jvmToolchain(libs.versions.gradle.jvmToolchain.get().toInt()) 32 | } 33 | 34 | java { 35 | withSourcesJar() 36 | withJavadocJar() 37 | } 38 | 39 | signing { 40 | useInMemoryPgpKeys( 41 | providers.gradleProperty("signingKey").orNull, 42 | providers.gradleProperty("signingPassword").orNull 43 | ) 44 | } 45 | 46 | /* 47 | // For GItHub Actions CI signing 48 | if (providers.environmentVariable("CI").isPresent) { 49 | apply(plugin = "signing") 50 | extensions.configure { 51 | useInMemoryPgpKeys( 52 | providers.environmentVariable("SIGNING_PGP_KEY").orNull, 53 | providers.environmentVariable("SIGNING_PGP_PASSWORD").orNull 54 | ) 55 | } 56 | } 57 | */ 58 | -------------------------------------------------------------------------------- /plugin/gradle/wrapper: -------------------------------------------------------------------------------- 1 | ../../gradle/wrapper -------------------------------------------------------------------------------- /plugin/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 2 | pluginManagement { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | gradlePluginPortal() 7 | } 8 | } 9 | dependencyResolutionManagement { 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | versionCatalogs { 15 | create("libs") { 16 | from(files("../gradle/libs.versions.toml")) 17 | } 18 | } 19 | } 20 | plugins { 21 | id("org.gradle.toolchains.foojay-resolver-convention") version ("0.9.0") 22 | } 23 | rootProject.name = "plugin" 24 | -------------------------------------------------------------------------------- /plugin/src/main/kotlin/org/sample/GreetingExtension.kt: -------------------------------------------------------------------------------- 1 | package org.sample 2 | 3 | abstract class GreetingExtension { 4 | var who: String? = null 5 | } 6 | -------------------------------------------------------------------------------- /plugin/src/main/kotlin/org/sample/GreetingPlugin.kt: -------------------------------------------------------------------------------- 1 | package org.sample 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | class GreetingPlugin : Plugin { 7 | override fun apply(target: Project) { 8 | val extension = target.extensions.create("greeting", GreetingExtension::class.java) 9 | val task = target.tasks.register("greeting", GreetingTask::class.java) 10 | task.configure { target -> 11 | target.who.set(extension.who) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /plugin/src/main/kotlin/org/sample/GreetingTask.kt: -------------------------------------------------------------------------------- 1 | package org.sample 2 | 3 | import org.gradle.api.DefaultTask 4 | import org.gradle.api.provider.Property 5 | import org.gradle.api.tasks.Input 6 | import org.gradle.api.tasks.Optional 7 | import org.gradle.api.tasks.TaskAction 8 | 9 | abstract class GreetingTask : DefaultTask() { 10 | @get:Optional 11 | @get:Input 12 | abstract val who: Property 13 | 14 | @TaskAction 15 | fun greet() { 16 | val w = who.getOrElse("mate") 17 | println("Hi $w!!!") 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:recommended", 4 | "schedule:quarterly" 5 | ], 6 | "packageRules": [ 7 | { 8 | "matchUpdateTypes": [ 9 | "patch" 10 | ], 11 | "enabled": false 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /sample/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | alias(libs.plugins.kotlin.android) 4 | alias(libs.plugins.compose.compiler) 5 | alias(libs.plugins.sampleplugin) 6 | } 7 | 8 | android { 9 | namespace = "org.sample.app" 10 | compileSdk = 35 11 | defaultConfig { 12 | applicationId = "org.sample.app" 13 | minSdk = 29 14 | targetSdk = 35 15 | versionCode = 1 16 | versionName = "1.0.0" 17 | } 18 | } 19 | 20 | kotlin { 21 | jvmToolchain(libs.versions.gradle.jvmToolchain.get().toInt()) 22 | } 23 | 24 | greeting { 25 | who = "mate" 26 | } 27 | 28 | dependencies { 29 | implementation(dependencies.platform(libs.compose.bom)) 30 | implementation(libs.androidx.appcompat) 31 | implementation(libs.androidx.lifecycle) 32 | implementation(libs.bundles.compose) 33 | } 34 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sample/src/main/kotlin/org/sample/app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package org.sample.app 2 | 3 | import android.os.Bundle 4 | import androidx.activity.compose.setContent 5 | import androidx.activity.enableEdgeToEdge 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.compose.foundation.layout.Box 8 | import androidx.compose.foundation.layout.fillMaxSize 9 | import androidx.compose.material3.MaterialTheme 10 | import androidx.compose.material3.Text 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.graphics.toArgb 15 | import androidx.core.view.WindowCompat 16 | import androidx.core.view.WindowInsetsControllerCompat 17 | 18 | class MainActivity : AppCompatActivity() { 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | enableEdgeToEdge() 22 | WindowInsetsControllerCompat( 23 | window, 24 | findViewById(android.R.id.content) 25 | ).isAppearanceLightStatusBars = true 26 | setContent { 27 | MaterialTheme { 28 | Box( 29 | Modifier.fillMaxSize(), 30 | contentAlignment = Alignment.Center 31 | ) { 32 | Text("Plugin Sample") 33 | } 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sample/src/main/kotlin/org/sample/app/MyApplication.kt: -------------------------------------------------------------------------------- 1 | package org.sample.app 2 | 3 | import android.app.Application 4 | 5 | class MyApplication: Application() 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Plugin Sample 3 | 4 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 2 | pluginManagement { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | gradlePluginPortal() 7 | } 8 | } 9 | dependencyResolutionManagement { 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | plugins { 16 | id("org.gradle.toolchains.foojay-resolver-convention") version ("0.9.0") 17 | } 18 | rootProject.name = "android-gradle-plugin-template" 19 | include(":sample") 20 | // if you want to use your plugin from Maven Plugin Portal, comment out below `includeBuild("plugin")` line. 21 | includeBuild("plugin") 22 | --------------------------------------------------------------------------------