From ddb827212e21024e793401973d8950b1a0c68fb0 Mon Sep 17 00:00:00 2001 From: Matthew Robertson Date: Wed, 21 Oct 2026 16:59:12 -0400 Subject: [PATCH 1/3] Add support for com.android.library --- google-services-plugin/build.gradle.kts | 2 +- .../googleservices/GoogleServicesPlugin.kt | 20 ++++-- .../GoogleServicesPluginTest.kt | 16 +++++ .../values/values.xml | 10 +++ .../test/testData/project4/build.gradle.kts | 5 ++ .../test/testData/project4/gradle.properties | 25 +++++++ .../src/test/testData/project4/lib/.gitignore | 1 + .../testData/project4/lib/build.gradle.kts | 19 ++++++ .../project4/lib/google-services.json | 68 +++++++++++++++++++ .../project4/lib/src/main/AndroidManifest.xml | 6 ++ .../testData/project4/settings.gradle.kts | 18 +++++ 11 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 google-services-plugin/src/test/testData/project4-expected/processDebugGoogleServices/values/values.xml create mode 100644 google-services-plugin/src/test/testData/project4/build.gradle.kts create mode 100644 google-services-plugin/src/test/testData/project4/gradle.properties create mode 100644 google-services-plugin/src/test/testData/project4/lib/.gitignore create mode 100644 google-services-plugin/src/test/testData/project4/lib/build.gradle.kts create mode 100644 google-services-plugin/src/test/testData/project4/lib/google-services.json create mode 100644 google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml create mode 100644 google-services-plugin/src/test/testData/project4/settings.gradle.kts diff --git a/google-services-plugin/build.gradle.kts b/google-services-plugin/build.gradle.kts index 56f0093b..c7648084 100644 --- a/google-services-plugin/build.gradle.kts +++ b/google-services-plugin/build.gradle.kts @@ -23,7 +23,7 @@ plugins { } group = "com.google.gms" -version = "4.5.0" +version = "4.5.1" dependencies { compileOnly("com.android.tools.build:gradle-api:7.3.0") diff --git a/google-services-plugin/src/main/kotlin/com/google/gms/googleservices/GoogleServicesPlugin.kt b/google-services-plugin/src/main/kotlin/com/google/gms/googleservices/GoogleServicesPlugin.kt index d55518e3..73500ef8 100644 --- a/google-services-plugin/src/main/kotlin/com/google/gms/googleservices/GoogleServicesPlugin.kt +++ b/google-services-plugin/src/main/kotlin/com/google/gms/googleservices/GoogleServicesPlugin.kt @@ -17,7 +17,7 @@ package com.google.gms.googleservices import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.DynamicFeatureAndroidComponentsExtension -import com.android.build.api.variant.GeneratesApk +import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.api.variant.Variant import com.google.android.gms.dependencies.DependencyAnalyzer import com.google.android.gms.dependencies.DependencyInspector @@ -25,6 +25,7 @@ import java.io.File import java.util.* import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.provider.Provider class GoogleServicesPlugin : Plugin { @@ -56,14 +57,21 @@ class GoogleServicesPlugin : Plugin { pluginApplied = true project.extensions.configure(ApplicationAndroidComponentsExtension::class.java) { it.registerSourceType(SOURCE_TYPE) - it.onVariants { variant -> handleVariant(variant, project) } + it.onVariants { variant -> handleVariant(variant, variant.applicationId, project) } + } + } + project.pluginManager.withPlugin("com.android.library") { + pluginApplied = true + project.extensions.configure(LibraryAndroidComponentsExtension::class.java) { + it.registerSourceType(SOURCE_TYPE) + it.onVariants { variant -> handleVariant(variant, variant.namespace, project) } } } project.pluginManager.withPlugin("com.android.dynamic-feature") { pluginApplied = true project.extensions.configure(DynamicFeatureAndroidComponentsExtension::class.java) { it.registerSourceType(SOURCE_TYPE) - it.onVariants { variant -> handleVariant(variant, project) } + it.onVariants { variant -> handleVariant(variant, variant.applicationId, project) } } } @@ -73,11 +81,11 @@ class GoogleServicesPlugin : Plugin { } project.logger.error( "The google-services Gradle plugin needs to be applied on a project with " + - "com.android.application or com.android.dynamic-feature.") + "com.android.application, com.android.library, or com.android.dynamic-feature.") } } - private fun handleVariant(variant: T, project: Project) where T : Variant, T : GeneratesApk { + private fun handleVariant(variant: Variant, packageName: Provider, project: Project) { val jsonToXmlTask = project.tasks.register( "process${variant.name.capitalize()}GoogleServices", GoogleServicesTask::class.java) { @@ -90,7 +98,7 @@ class GoogleServicesPlugin : Plugin { variant.buildType.orEmpty(), variant.productFlavors.map { it.second }, project.projectDir)) - it.applicationId.set(variant.applicationId) + it.applicationId.set(packageName) it.gmpAppId.set(project.layout.buildDirectory.file("gmpAppId/${variant.name}.txt")) } diff --git a/google-services-plugin/src/test/kotlin/com/google/gms/googleservices/GoogleServicesPluginTest.kt b/google-services-plugin/src/test/kotlin/com/google/gms/googleservices/GoogleServicesPluginTest.kt index 00e912ef..22130908 100644 --- a/google-services-plugin/src/test/kotlin/com/google/gms/googleservices/GoogleServicesPluginTest.kt +++ b/google-services-plugin/src/test/kotlin/com/google/gms/googleservices/GoogleServicesPluginTest.kt @@ -194,6 +194,22 @@ class GoogleServicesPluginTest { compareResults(actualResults, expectedResults) } + @Test + fun `res file generation for library module`() { + val projectName = "project4" + + copyProjectToTemp(projectName) + val buildResult = runBuild(gradleVersion = "7.6", agpVersion = "7.4.1") + + Assert.assertEquals(TaskOutcome.SUCCESS, buildResult.task(":lib:assembleDebug")?.outcome) + Assert.assertEquals( + TaskOutcome.SUCCESS, buildResult.task(":lib:processDebugGoogleServices")?.outcome) + + val actualResults = tempFolder.root.resolve("lib/build/generated/res/") + val expectedResults = getExpectedResults(projectName) + compareResults(actualResults, expectedResults) + } + @Test fun testNoFlavor() { val output: List = GoogleServicesPlugin.getJsonLocations("release", emptyList()) diff --git a/google-services-plugin/src/test/testData/project4-expected/processDebugGoogleServices/values/values.xml b/google-services-plugin/src/test/testData/project4-expected/processDebugGoogleServices/values/values.xml new file mode 100644 index 00000000..750588dc --- /dev/null +++ b/google-services-plugin/src/test/testData/project4-expected/processDebugGoogleServices/values/values.xml @@ -0,0 +1,10 @@ + + + 123456789000-e4uksm38sne0bqrj6uvkbo4oiu4hvigl.apps.googleusercontent.com + https://mockproject-1234.firebaseio.com + 123456789000 + AIzbSzCn1N6LWIe6wthYyrgUUSAlUsdqMb-wvTo + 1:123456789000:android:f1bf012572b04063 + AIzbSzCn1N6LWIe6wthYyrgUUSAlUsdqMb-wvTo + mockproject-1234 + diff --git a/google-services-plugin/src/test/testData/project4/build.gradle.kts b/google-services-plugin/src/test/testData/project4/build.gradle.kts new file mode 100644 index 00000000..fbb69715 --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/build.gradle.kts @@ -0,0 +1,5 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.android.library") version System.getProperty("agpVersion") apply false + id("com.google.gms.google-services") version System.getProperty("pluginVersion") apply false +} \ No newline at end of file diff --git a/google-services-plugin/src/test/testData/project4/gradle.properties b/google-services-plugin/src/test/testData/project4/gradle.properties new file mode 100644 index 00000000..60b727c1 --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +android.nonFinalResIds=false +org.gradle.jvmargs=-Xmx2000m \ No newline at end of file diff --git a/google-services-plugin/src/test/testData/project4/lib/.gitignore b/google-services-plugin/src/test/testData/project4/lib/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/lib/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts b/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts new file mode 100644 index 00000000..d739a66c --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("com.android.library") + id("com.google.gms.google-services") +} + +import com.google.gms.googleservices.GoogleServicesPlugin.MissingGoogleServicesStrategy + +android { + namespace = "com.example.mylibrary" + compileSdk = 33 + + defaultConfig { + minSdk = 24 + } +} + +googleServices { + missingGoogleServicesStrategy = MissingGoogleServicesStrategy.ERROR +} diff --git a/google-services-plugin/src/test/testData/project4/lib/google-services.json b/google-services-plugin/src/test/testData/project4/lib/google-services.json new file mode 100644 index 00000000..ebc6d6c8 --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/lib/google-services.json @@ -0,0 +1,68 @@ +{ + "project_info": { + "project_id": "mockproject-1234", + "project_number": "123456789000", + "name": "FirebaseQuickstarts", + "firebase_url": "https://mockproject-1234.firebaseio.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:123456789000:android:f1bf012572b04063", + "client_id": "android:com.example.mylibrary", + "client_type": 1, + "android_client_info": { + "package_name": "com.example.mylibrary", + "certificate_hash": [] + } + }, + "oauth_client": [ + { + "client_id": "123456789000-hjugbg6ud799v4c49dim8ce2usclthar.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.mylibrary", + "certificate_hash": "4C20644DE36B8F89D25650C7D1FF9FBAE650FDF7" + } + }, + { + "client_id": "123456789000-e4uksm38sne0bqrj6uvkbo4oiu4hvigl.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzbSzCn1N6LWIe6wthYyrgUUSAlUsdqMb-wvTo" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "cloud_messaging_service": { + "status": 2, + "apns_config": [] + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "123456789000-e4uksm38sne0bqrj6uvkbo4oiu4hvigl.apps.googleusercontent.com", + "client_type": 3 + } + ] + }, + "google_signin_service": { + "status": 2 + }, + "ads_service": { + "status": 2, + "test_banner_ad_unit_id": "ca-app-pub-3940256099942544/6300978111", + "test_interstitial_ad_unit_id": "ca-app-pub-3940256099942544/1033173712" + } + } + } + ], + "client_info": [], + "ARTIFACT_VERSION": "1" +} diff --git a/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml b/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml new file mode 100644 index 00000000..7dc9b158 --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/google-services-plugin/src/test/testData/project4/settings.gradle.kts b/google-services-plugin/src/test/testData/project4/settings.gradle.kts new file mode 100644 index 00000000..ae4bfe98 --- /dev/null +++ b/google-services-plugin/src/test/testData/project4/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + maven { + val pluginRepo: String by settings + url = uri(pluginRepo) + } + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +include(":lib") From ec5e6b44bb91c9f711b9f9c22375ee9a4cdbca6c Mon Sep 17 00:00:00 2001 From: Matthew Robertson Date: Thu, 22 Oct 2026 09:11:09 -0400 Subject: [PATCH 2/3] Add test data dir to inputs and format --- google-services-plugin/build.gradle.kts | 3 +++ .../test/testData/project4/build.gradle.kts | 6 ++--- .../test/testData/project4/gradle.properties | 2 +- .../src/test/testData/project4/lib/.gitignore | 2 +- .../testData/project4/lib/build.gradle.kts | 16 ++++++------ .../project4/lib/src/main/AndroidManifest.xml | 4 +-- .../testData/project4/settings.gradle.kts | 26 ++++++++++--------- 7 files changed, 32 insertions(+), 27 deletions(-) diff --git a/google-services-plugin/build.gradle.kts b/google-services-plugin/build.gradle.kts index c7648084..38337ddd 100644 --- a/google-services-plugin/build.gradle.kts +++ b/google-services-plugin/build.gradle.kts @@ -71,6 +71,9 @@ tasks.withType().configureEach { // See GoogleServicesPluginTest.kt -> testResGeneration dependsOn("publishAllPublicationsToMavenRepository") systemProperties["plugin_version"] = project.version // value used by GoogleServicesPluginTest.kt + inputs.dir("src/test/testData") + .withPropertyName("testData") + .withPathSensitivity(PathSensitivity.RELATIVE) } tasks.withType().configureEach { diff --git a/google-services-plugin/src/test/testData/project4/build.gradle.kts b/google-services-plugin/src/test/testData/project4/build.gradle.kts index fbb69715..b33b313e 100644 --- a/google-services-plugin/src/test/testData/project4/build.gradle.kts +++ b/google-services-plugin/src/test/testData/project4/build.gradle.kts @@ -1,5 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.library") version System.getProperty("agpVersion") apply false - id("com.google.gms.google-services") version System.getProperty("pluginVersion") apply false -} \ No newline at end of file + id("com.android.library") version System.getProperty("agpVersion") apply false + id("com.google.gms.google-services") version System.getProperty("pluginVersion") apply false +} diff --git a/google-services-plugin/src/test/testData/project4/gradle.properties b/google-services-plugin/src/test/testData/project4/gradle.properties index 60b727c1..9ed4004b 100644 --- a/google-services-plugin/src/test/testData/project4/gradle.properties +++ b/google-services-plugin/src/test/testData/project4/gradle.properties @@ -22,4 +22,4 @@ kotlin.code.style=official # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true android.nonFinalResIds=false -org.gradle.jvmargs=-Xmx2000m \ No newline at end of file +org.gradle.jvmargs=-Xmx2000m diff --git a/google-services-plugin/src/test/testData/project4/lib/.gitignore b/google-services-plugin/src/test/testData/project4/lib/.gitignore index 42afabfd..796b96d1 100644 --- a/google-services-plugin/src/test/testData/project4/lib/.gitignore +++ b/google-services-plugin/src/test/testData/project4/lib/.gitignore @@ -1 +1 @@ -/build \ No newline at end of file +/build diff --git a/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts b/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts index d739a66c..1c53be4f 100644 --- a/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts +++ b/google-services-plugin/src/test/testData/project4/lib/build.gradle.kts @@ -1,19 +1,19 @@ plugins { - id("com.android.library") - id("com.google.gms.google-services") + id("com.android.library") + id("com.google.gms.google-services") } import com.google.gms.googleservices.GoogleServicesPlugin.MissingGoogleServicesStrategy android { - namespace = "com.example.mylibrary" - compileSdk = 33 + namespace = "com.example.mylibrary" + compileSdk = 33 - defaultConfig { - minSdk = 24 - } + defaultConfig { + minSdk = 24 + } } googleServices { - missingGoogleServicesStrategy = MissingGoogleServicesStrategy.ERROR + missingGoogleServicesStrategy = MissingGoogleServicesStrategy.ERROR } diff --git a/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml b/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml index 7dc9b158..2b37b753 100644 --- a/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml +++ b/google-services-plugin/src/test/testData/project4/lib/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - + - \ No newline at end of file + diff --git a/google-services-plugin/src/test/testData/project4/settings.gradle.kts b/google-services-plugin/src/test/testData/project4/settings.gradle.kts index ae4bfe98..35998fc5 100644 --- a/google-services-plugin/src/test/testData/project4/settings.gradle.kts +++ b/google-services-plugin/src/test/testData/project4/settings.gradle.kts @@ -1,18 +1,20 @@ pluginManagement { - repositories { - maven { - val pluginRepo: String by settings - url = uri(pluginRepo) - } - google() - mavenCentral() + repositories { + maven { + val pluginRepo: String by settings + url = uri(pluginRepo) } + google() + mavenCentral() + } } + dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } } + include(":lib") From 0dd1d214d49c68e975aa55db0db9fe6522abb22d Mon Sep 17 00:00:00 2001 From: Matthew Robertson Date: Fri, 23 Oct 2026 12:31:44 -0400 Subject: [PATCH 3/3] Minor version bump and update README --- google-services-plugin/README.md | 28 ++++++++++++------------- google-services-plugin/build.gradle.kts | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/google-services-plugin/README.md b/google-services-plugin/README.md index e999311a..e6fedded 100755 --- a/google-services-plugin/README.md +++ b/google-services-plugin/README.md @@ -21,36 +21,36 @@ Apply the plugin in your app's build.gradle.kts: ```kotlin plugins { - id("com.google.gms.google-services") version "4.4.4" + id("com.google.gms.google-services") version "4.6.0" } ``` Or in build.gradle: ```gradle plugins { - id 'com.google.gms.google-services' version '4.4.4' + id 'com.google.gms.google-services' version '4.6.0' } ``` -### New in version 4.4.0 - -#### `google-services.json` location +### `google-services.json` location Place the `google-services.json` file for your project in the `app/` directory. Alternatively, you can use variant specific source-sets, for example: `debug/google-services.json`. -#### Compatible Android plugins +### Compatible Android plugins + +The `com.google.gms.google-services` plugin can be applied to projects using +`com.android.application`, `com.android.library`, or `com.android.dynamic-feature`. -The `com.google.gms.google-services` plugin can only be applied to projects with -`com.android.application` or `com.android.dynamic-feature`, as it requires an `applicationId` -to function. +The plugin selects the `client` entry in `google-services.json` whose `package_name` matches the +module: -The plugin is not compatible with plugins such as `com.android.library` that do not -contain an `applicationId`. +- For `com.android.application` and `com.android.dynamic-feature`, the variant's `applicationId`. +- For `com.android.library`, the library's `namespace`. -#### Plugin configuration +### Plugin configuration Configure the plugin's behavior through the `googleServices` block in build.gradle.kts: @@ -72,7 +72,7 @@ googleServices { You can use `missingGoogleServicesStrategy` when some variants in your project do not require Google Play Services and are missing the `google-services.json` file. -#### Android Gradle plugin compatibility +### Android Gradle plugin compatibility The Google Services plugin requires AGP 7.3.0 or newer to work. @@ -82,7 +82,7 @@ Add the following to your buildscript classpath, obtained from Google’s [Maven repository](//developer.android.com/studio/build/dependencies#google-maven): ```gradle -classpath 'com.google.gms:google-services:4.4.4' +classpath 'com.google.gms:google-services:4.6.0' ``` Apply the plugin in your app's build.gradle: diff --git a/google-services-plugin/build.gradle.kts b/google-services-plugin/build.gradle.kts index 38337ddd..3a395b31 100644 --- a/google-services-plugin/build.gradle.kts +++ b/google-services-plugin/build.gradle.kts @@ -23,7 +23,7 @@ plugins { } group = "com.google.gms" -version = "4.5.1" +version = "4.6.0" dependencies { compileOnly("com.android.tools.build:gradle-api:7.3.0")