diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-12 02:06:27 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-04-12 02:06:27 +0000 |
commit | e8b2db3b1803448076eefe2d1d06f8d4f9bb98f4 (patch) | |
tree | 66d01fef09cbfe2cf7f6d349165849a2be87bcc7 | |
parent | be01f9dc3761594ecf2f4daec30ddf764e92e9db (diff) | |
parent | 43ee1f20e3ca158e639480cb54ed28474e51a643 (diff) | |
download | gradle-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
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 |