summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-04-12 02:06:27 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-04-12 02:06:27 +0000
commite8b2db3b1803448076eefe2d1d06f8d4f9bb98f4 (patch)
tree66d01fef09cbfe2cf7f6d349165849a2be87bcc7
parentbe01f9dc3761594ecf2f4daec30ddf764e92e9db (diff)
parent43ee1f20e3ca158e639480cb54ed28474e51a643 (diff)
downloadgradle-recipes-studio-main.tar.gz
Snap for 9922117 from 43ee1f20e3ca158e639480cb54ed28474e51a643 to studio-giraffe-releasestudio-2022.3.1-rc1studio-2022.3.1-beta2studio-2022.3.1studio-main
Change-Id: I64f21d127fafea14e1177d679fec113a25550024
-rw-r--r--recipes/allProjectsApkAction/README.md23
-rw-r--r--recipes/allProjectsApkAction/app/build.gradle.kts29
-rw-r--r--recipes/allProjectsApkAction/app/src/main/AndroidManifest.xml26
-rw-r--r--recipes/allProjectsApkAction/app2/build.gradle.kts29
-rw-r--r--recipes/allProjectsApkAction/app2/src/main/AndroidManifest.xml26
-rw-r--r--recipes/allProjectsApkAction/build-logic/gradle.properties4
-rw-r--r--recipes/allProjectsApkAction/build-logic/gradle/libs.versions.toml9
-rw-r--r--recipes/allProjectsApkAction/build-logic/plugins/build.gradle.kts39
-rw-r--r--recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/AllProjectsApkTask.kt58
-rw-r--r--recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/CustomSettings.kt79
-rw-r--r--recipes/allProjectsApkAction/build-logic/settings.gradle.kts26
-rw-r--r--recipes/allProjectsApkAction/build.gradle.kts20
-rw-r--r--recipes/allProjectsApkAction/gradle/libs.versions.toml7
-rw-r--r--recipes/allProjectsApkAction/recipe_metadata.toml23
-rw-r--r--recipes/allProjectsApkAction/settings.gradle.kts40
15 files changed, 438 insertions, 0 deletions
diff --git a/recipes/allProjectsApkAction/README.md b/recipes/allProjectsApkAction/README.md
new file mode 100644
index 0000000..4be63c9
--- /dev/null
+++ b/recipes/allProjectsApkAction/README.md
@@ -0,0 +1,23 @@
+# Iterating over all modules in a project and extract produced APKs
+
+The recipe shows how to use a [Settings](https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html) plugin to iterate over every modules in a project
+and take specific action if the Android application plugin is applied.
+When it is applied, the plugin will select the "release" variant APK output and add those to the input of a
+single task. That single 'allProjectsAction` task, will then display the list. This can be
+modified to instead zip up APKs, sign APKs, etc...
+
+This recipe contains the following directories :
+
+| Module | Content |
+|----------------------------|-------------------------------------------------------------------|
+| [build-logic](build-logic) | Contains the Settings plugin that is the core of the recipe |
+| [app](app) | A small Android application sample used to demonstrate the recipe |
+| [app2](app2) | Another small Android application sample |
+
+
+The build-logic sub-project contains the Plugin called [CustomSettings.kt](build-logic/plugins/src/main/kotlin/CustomSettings.kt) that will
+iterate over all sub-project "release" variant.
+
+The [AppProjectsApkTask.kt](build-logic/plugins/src/main/kotlin/AllProjectsApkTask.kt) is the "allProjectsAction" task implementation.
+
+To run the recipe : `gradlew allProjectsAction` \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/app/build.gradle.kts b/recipes/allProjectsApkAction/app/build.gradle.kts
new file mode 100644
index 0000000..70db511
--- /dev/null
+++ b/recipes/allProjectsApkAction/app/build.gradle.kts
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+}
+
+android {
+ namespace = "com.example.android.recipes.all_project_action_app"
+ compileSdk = $COMPILE_SDK
+ defaultConfig {
+ minSdk = $MINIMUM_SDK
+ targetSdk = $COMPILE_SDK
+ }
+}
diff --git a/recipes/allProjectsApkAction/app/src/main/AndroidManifest.xml b/recipes/allProjectsApkAction/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..2cdd78c
--- /dev/null
+++ b/recipes/allProjectsApkAction/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <!--
+ Copyright 2022 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+ <application android:label="Minimal">
+ <!-- The actual activity name will be injected during the manifest processing -->
+ <activity
+ android:name="com.app.test"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest> \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/app2/build.gradle.kts b/recipes/allProjectsApkAction/app2/build.gradle.kts
new file mode 100644
index 0000000..54cb225
--- /dev/null
+++ b/recipes/allProjectsApkAction/app2/build.gradle.kts
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+}
+
+android {
+ namespace = "com.example.android.recipes.all_projects_action_app2"
+ compileSdk = $COMPILE_SDK
+ defaultConfig {
+ minSdk = $MINIMUM_SDK
+ targetSdk = $COMPILE_SDK
+ }
+}
diff --git a/recipes/allProjectsApkAction/app2/src/main/AndroidManifest.xml b/recipes/allProjectsApkAction/app2/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4fabda8
--- /dev/null
+++ b/recipes/allProjectsApkAction/app2/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <!--
+ Copyright 2022 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+ <application android:label="Minimal">
+ <!-- The actual activity name will be injected during the manifest processing -->
+ <activity
+ android:name="com.app.test2"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest> \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/build-logic/gradle.properties b/recipes/allProjectsApkAction/build-logic/gradle.properties
new file mode 100644
index 0000000..1c9073e
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/gradle.properties
@@ -0,0 +1,4 @@
+# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534
+org.gradle.parallel=true
+org.gradle.caching=true
+org.gradle.configureondemand=true
diff --git a/recipes/allProjectsApkAction/build-logic/gradle/libs.versions.toml b/recipes/allProjectsApkAction/build-logic/gradle/libs.versions.toml
new file mode 100644
index 0000000..d009d76
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/gradle/libs.versions.toml
@@ -0,0 +1,9 @@
+[versions]
+androidGradlePlugin = $AGP_VERSION
+kotlin = $KOTLIN_VERSION
+
+[libraries]
+android-gradlePlugin-api = { group = "com.android.tools.build", name = "gradle-api", version.ref = "androidGradlePlugin" }
+
+[plugins]
+kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/build-logic/plugins/build.gradle.kts b/recipes/allProjectsApkAction/build-logic/plugins/build.gradle.kts
new file mode 100644
index 0000000..32892f2
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/plugins/build.gradle.kts
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ `java-gradle-plugin`
+ alias(libs.plugins.kotlin.jvm)
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+}
+
+dependencies {
+ implementation(libs.android.gradlePlugin.api)
+ implementation(gradleKotlinDsl())
+}
+
+gradlePlugin {
+ plugins {
+ create("allProjectsApkActionSettings") {
+ id = "android.recipes.all_projects_apk_action"
+ implementationClass = "CustomSettings"
+ }
+ }
+}
diff --git a/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/AllProjectsApkTask.kt b/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/AllProjectsApkTask.kt
new file mode 100644
index 0000000..6b50208
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/AllProjectsApkTask.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.gradle.api.Plugin
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.file.Directory
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+
+abstract class AllProjectsApkTask: DefaultTask() {
+
+ @get:InputFiles
+ abstract val inputDirectories: ListProperty<Directory>
+
+ @get:OutputFile
+ abstract val outputFile: RegularFileProperty
+
+ @TaskAction
+ fun taskAction() {
+ val output = outputFile.get().asFile
+ java.nio.file.Files.deleteIfExists(output.toPath())
+
+ // inputDirectories contains a list of directories.
+ //
+ // Each directory contains the APKs for a particular module. We only
+ // selected the RELEASE variant (see the CustomSettings.kt for the
+ // variant selection).
+ inputDirectories.get()
+ .forEach {
+ // Each directory contains one to many APKs in case of
+ // multi-apk builds.
+ // When AGP produces more than one file in a directory,
+ // it also produces a small json file that indicates each
+ // file particular attributes.
+ // In this case, I am only interested at getting all the APKs
+ // so I ignore this json file and store the APK file path
+ // in my result file.
+ it.asFile.walkTopDown()
+ .filter { it.name.endsWith(".apk") }
+ .forEach { output.appendText("${it.absolutePath}\n") }
+ }
+ }
+} \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/CustomSettings.kt b/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/CustomSettings.kt
new file mode 100644
index 0000000..8ed9442
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/plugins/src/main/kotlin/CustomSettings.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.android.build.api.artifact.SingleArtifact
+import com.android.build.api.variant.AndroidComponentsExtension
+import com.android.build.gradle.AppPlugin
+import org.gradle.api.Plugin
+import org.gradle.api.tasks.TaskProvider
+import org.gradle.api.initialization.Settings
+import org.gradle.kotlin.dsl.register
+
+/**
+ * This [Settings] plugin is applied to the settings script.
+ * The settings script contains the list of modules applied to the project
+ * which allows us to hook up on sub-project's creation.
+ */
+class CustomSettings: Plugin<Settings> {
+
+ override fun apply(settings: Settings) {
+ var taskProvider: TaskProvider<AllProjectsApkTask>? = null
+
+ settings.gradle.beforeProject { project ->
+ // since we want a single task that will consume all APKs produced by a
+ // sub-project's RELEASE variant, let's create it in the rootProject only.
+ if (project == project.rootProject) {
+ taskProvider = project.tasks.register<AllProjectsApkTask>(
+ "allProjectsAction"
+ ) {
+ // set the Task output file inside the build's output folder
+ outputFile.set(
+ project.layout.buildDirectory.file("list_of_apks.txt")
+ )
+ }
+ }
+
+ // Registers a callback on the application of the Android Application plugin.
+ // This allows the CustomPlugin to work whether it's applied before or after
+ // the Android Application plugin.
+ project.plugins.withType(AppPlugin::class.java) { _ ->
+
+ // so we now know that the application plugin has been applied so
+ // let's look up its extension so we can invoke the AGP Variant API.
+ val androidComponents =
+ project.extensions.getByType(AndroidComponentsExtension::class.java)
+
+ // Registers a callback to be called, when a RELEASE variant is configured
+ androidComponents.onVariants(
+ androidComponents.selector().withBuildType("release")
+ ) { variant ->
+
+ // for each RELEASE variant, let's configure the unique task we created
+ // in the root project and add the APK artifact to its input file.
+ taskProvider?.configure { task ->
+ println("Adding variant ${variant.name} APKs from ${project.path}")
+ // look up the APK directory artifact as a Provider<Directory> and
+ // add it to the task's inputDirectories FileCollection.
+ task.inputDirectories.add(
+ variant.artifacts.get(SingleArtifact.APK)
+ )
+ }
+ }
+ }
+
+ }
+ }
+
+} \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/build-logic/settings.gradle.kts b/recipes/allProjectsApkAction/build-logic/settings.gradle.kts
new file mode 100644
index 0000000..56bf9c8
--- /dev/null
+++ b/recipes/allProjectsApkAction/build-logic/settings.gradle.kts
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rootProject.name = "build-logic"
+
+dependencyResolutionManagement {
+ repositories {
+$AGP_REPOSITORY
+$DEPENDENCY_REPOSITORIES
+ }
+}
+
+include(":plugins")
diff --git a/recipes/allProjectsApkAction/build.gradle.kts b/recipes/allProjectsApkAction/build.gradle.kts
new file mode 100644
index 0000000..a30e11d
--- /dev/null
+++ b/recipes/allProjectsApkAction/build.gradle.kts
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.kotlin.android) apply false
+}
diff --git a/recipes/allProjectsApkAction/gradle/libs.versions.toml b/recipes/allProjectsApkAction/gradle/libs.versions.toml
new file mode 100644
index 0000000..28fab8d
--- /dev/null
+++ b/recipes/allProjectsApkAction/gradle/libs.versions.toml
@@ -0,0 +1,7 @@
+[versions]
+androidGradlePlugin = $AGP_VERSION
+kotlin = $KOTLIN_VERSION
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } \ No newline at end of file
diff --git a/recipes/allProjectsApkAction/recipe_metadata.toml b/recipes/allProjectsApkAction/recipe_metadata.toml
new file mode 100644
index 0000000..dd1e0e0
--- /dev/null
+++ b/recipes/allProjectsApkAction/recipe_metadata.toml
@@ -0,0 +1,23 @@
+title = "allProjectsApkAction"
+
+description ="""
+ allProjectsAction recipe show how to iterate over all projects and recover produced APKs for each of them.
+ """
+
+[agpVersion]
+min = "8.0.0-rc01"
+
+# Relevant Gradle tasks to run per recipe
+[gradleTasks]
+tasks = [
+ "allProjectsAction",
+]
+
+# All the relevant metadata fields to create an index based on language/API/etc'
+[indexMetadata]
+index = [
+ "settings plugin",
+ "onVariant",
+ "All projects",
+ "APK",
+]
diff --git a/recipes/allProjectsApkAction/settings.gradle.kts b/recipes/allProjectsApkAction/settings.gradle.kts
new file mode 100644
index 0000000..b64d4e0
--- /dev/null
+++ b/recipes/allProjectsApkAction/settings.gradle.kts
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rootProject.name = "allProjectsApkAction"
+
+pluginManagement {
+ includeBuild("build-logic")
+ repositories {
+$AGP_REPOSITORY
+$PLUGIN_REPOSITORIES
+ }
+}
+
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+$AGP_REPOSITORY
+$DEPENDENCY_REPOSITORIES
+ }
+}
+
+include(":app")
+include(":app2")
+
+plugins {
+ id("android.recipes.all_projects_apk_action")
+} \ No newline at end of file