Skip to content

[google_sign_in_android] res/raw/keep.xml should be uniquely named to prevent resource override by app/libraries #194943

Closed

Description

@akurnaz

What package does this bug report belong to?

google_sign_in

What target platforms are you seeing this bug on?

Android

Have you already upgraded your packages?

Yes

Dependency versions

pubspec.lock snippet
google_sign_in:
  dependency: "direct main"
  description:
    name: google_sign_in
    url: "https://pub.dev"
  source: hosted
  version: "7.2.0"
google_sign_in_android:
  dependency: transitive
  description:
    name: google_sign_in_android
    url: "https://pub.dev"
  source: hosted
  version: "7.2.18"

Steps to reproduce

  1. Create a Flutter app with google_sign_in: ^7.2.0 (using google_sign_in_android >= 7.2.16) and configure Firebase / google-services.json.
  2. In android/app/build.gradle.kts, enable resource shrinking for the release build:
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
  3. Create an application-level keep rules file at android/app/src/main/res/raw/keep.xml (the exact location and filename suggested in the official Android Developer Documentation), for example to keep a custom notification icon:
    <?xml version="1.0" encoding="utf-8"?>
    <resources xmlns:tools="http://schemas.android.com/tools"
        tools:keep="@drawable/ic_notification" />
  4. Build the release APK/AAB: flutter build apk --release (or with flavors flutter build apk --release --flavor development).
  5. Run the app and trigger Google Sign-In without manually passing serverClientId in Dart (GoogleSignIn.instance.authenticate()).

Expected results

The Android Resource Shrinker should combine the keep rules from both the app and the library dependencies. Both @drawable/ic_notification and @string/default_web_client_id should be preserved, allowing Google Sign-In to read the Web Client ID successfully.

Actual results

Because res/raw/ resources are file-based (unlike res/values/ XML tags which are merged), Android Gradle Plugin's resource merger prioritizes the app's raw/keep.xml over library dependencies (App source set > Library AAR). As a result:

  1. The app's res/raw/keep.xml completely overrides google_sign_in_android's res/raw/keep.xml.
  2. In build/app/intermediates/merged-not-compiled-resources/<variant>/raw/keep.xml, only @drawable/ic_notification remains.
  3. In build/app/outputs/mapping/<variant>/resources.txt:
    string:default_web_client_id:2131820609 is not reachable.
    
  4. At runtime, _hostApi.getGoogleServicesJsonServerClientId() returns null because the string resource was stripped.
  5. The application throws:
    Unhandled Exception: GoogleSignInException(code GoogleSignInExceptionCode.clientConfigurationError, serverClientId must be provided on Android, null)
    

Code sample

Root Cause:
In flutter/packages#12075 (v7.2.16), google_sign_in_android added android/src/main/res/raw/keep.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@string/default_web_client_id" />

Because the filename is generically keep.xml, any consuming app or library that declares keep.xml will collide and override it per Android Resource Merging Precedence.

Proposed Solution:
Rename android/src/main/res/raw/keep.xml in google_sign_in_android to a uniquely namespaced file, such as:

  • android/src/main/res/raw/google_sign_in_keep.xml

Android Resource Shrinker automatically parses all XML files containing <resources xmlns:tools="..." tools:keep="..."> under res/raw/, regardless of their filename.

This aligns with standard best practices adopted across the Android ecosystem:

  • firebase_common_keep.xml in com.google.firebase:firebase-common
  • firebase_crashlytics_keep.xml in com.google.firebase:firebase-crashlytics
  • glance_appwidget_keep.xml in androidx.glance:glance-appwidget

Screenshots or Videos

Screenshots / Video demonstration

[Upload media here]

Logs

Runtime Exception & Resource Shrinker Log
E/flutter (10020): [ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: GoogleSignInException(code GoogleSignInExceptionCode.clientConfigurationError, serverClientId must be provided on Android, null)
E/flutter (10020): #0      GoogleSignInAndroid._authenticate (package:google_sign_in_android/google_sign_in_android.dart:219)
E/flutter (10020): <asynchronous suspension>
E/flutter (10020): #1      GoogleSignInAndroid.authenticate (package:google_sign_in_android/google_sign_in_android.dart:86)
E/flutter (10020): <asynchronous suspension>
E/flutter (10020): #2      GoogleSignIn.authenticate (package:google_sign_in/google_sign_in.dart:545)

From build/app/outputs/mapping/<variant>/resources.txt:

string:default_web_client_id:2131820609 is not reachable.

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.47.7, on macOS 27.0.1 26A434 darwin-arm64, locale tr-TR) [345ms]
    • Flutter version 3.47.7 on channel stable at /Users/alikurnaz/development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision abaf9c5237 (13 days ago), 2026-10-08 09:51:21 -0700
    • Engine revision deb287481e
    • Dart version 3.13.5
    • DevTools version 2.60.0
    • Feature flags: enable-web, enable-linux-desktop, no-enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use,
      enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration

[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1.663ms]
    • Android SDK at /Users/alikurnaz/Library/Android/sdk
    • Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)
    • Platform android-37.0, build-tools 36.0.0
    • Java binary at: /Users/alikurnaz/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.10+-117844308-b1163.108)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 27.1) [1.086ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 27A9275
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [6ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Connected device (3 available) [6,6s]
    • sdk gphone16k arm64 (mobile)     • emulator-5554             • android-arm64  • Android 17 (API 37) (emulator)
    • Ali iPhone’u (wireless) (mobile) • 00008110-001105DE1E61801E • ios            • iOS 26.6.2 23G90
    • Chrome (web)                     • chrome                    • web-javascript • Google Chrome 156.0.8078.47

[✓] Network resources [476ms]
    • All expected network resources are available.

• No issues found!

Activity

  1. saurabh-mirajkar commented on Oct 22, 2026

    @saurabh-mirajkar
    Contributor

    @akurnaz Thanks for the detailed report. I reproduced this on Flutter 3.47.7 with google_sign_in_android 7.2.18. Labelling this and routing it to the Android team.

    Related: #188363

  2. added
    platform-androidAndroid applications specifically
    packageflutter/packages repository. See also p: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-androidOwned by Android platform team
    fyi-ecosystemFor the attention of Ecosystem team
    and removed
    in triagePresently being triaged by the triage team
    on Oct 22, 2026
  3. RajKavadia commented on Oct 23, 2026

    @RajKavadia

    fwiw any plugin shipping res/raw/keep.xml has this problem since the app's file just wins in the resource merge. prefixing it, something like gsi_keep.xml, seems like the easy fix

  4. added a commit that references this issue on Oct 25, 2026
    f6c6c74
  5. added
    triaged-androidTriaged by Android platform team
    P2Important issues not at the top of the work list
    on Oct 28, 2026
  6. ybeshkarov commented on Oct 29, 2026

    @ybeshkarov

    Reproduced this with google_sign_in_android 7.2.18 (Flutter 3.44.2, Android 17 emulator). The app has its own android/app/src/main/res/raw/keep.xml that keeps only @mipmap/ic_launcher, and the release build drops the string:

    $ grep default_web_client_id build/app/outputs/mapping/release/resources.txt
    string:default_web_client_id:2131689529 is not reachable.
    

    GoogleSignIn.instance.authenticate() then throws GoogleSignInException(code GoogleSignInExceptionCode.clientConfigurationError, serverClientId must be provided on Android, null). Debug builds don't shrink resources, so they work.

    Until the rename ships, you can work around it in the app:

    1. Rename your file, e.g. to res/raw/app_keep.xml. The shrinker reads every keep file in res/raw, so the plugin's rule applies again: resources.txt says reachable from keep xml file, and the release build signs in.
    2. Or keep the name and add the string to your own rule. I checked that the release APK keeps the string this way:
      <resources xmlns:tools="http://schemas.android.com/tools"
          tools:keep="@mipmap/ic_launcher,@string/default_web_client_id" />
    3. Or pass serverClientId to GoogleSignIn.instance.initialize(). The plugin only looks up default_web_client_id when serverClientId is null (see google_sign_in_android.dart), so the stripped resource doesn't matter. I didn't run this one.

    If an app has no keep file of its own and still gets this error only in release, check flutter pub deps | grep google_sign_in_android. Before 7.2.16 the resource was stripped in every app (#188363).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listhas reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: google_sign_inThe Google Sign-In pluginpackageflutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyteam-androidOwned by Android platform teamtriaged-androidTriaged by Android platform teamwaiting for PR to land (fixed)A fix is in flight

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions