UYLLII

Blog › Engineering

Engineering

Stop the Google Play Games sign-in popup at launch: remove PlayGamesInitProvider

By David3 min read
Genesis feature graphic

Here's a rule I hold every game to: no game shows a Google Play Games sheet when it opens. Nobody installs a puzzle or an idle game to be asked to sign in to something. The sheet covers the first thing they see, and some players will just close the app.

Play Games should start only when the player taps Achievements, Leaderboards or Cloud save, or silently in the background for someone who has connected before.

I thought I'd implemented that. Three games proved otherwise.

The JavaScript gate (necessary, not sufficient)

My games are Capacitor apps, and Play Games comes in through a plugin. The obvious approach is to call the plugin's initialize() only when the player taps one of those buttons, and I did exactly that in Genesis.

The sheet still appeared at launch.

The real cause: a content provider

play-services-games-v2, the Play Games library, ships an Android content provider called com.google.android.gms.games.provider.PlayGamesInitProvider. Android creates every content provider in an app's manifest when the process starts, before your Activity, before the WebView and before any of your JavaScript runs. That provider initialises the Play Games SDK, and the SDK may show its sign-in sheet.

So the JS gate does nothing. By the time your code decides not to initialise Play Games, it already has.

The fix

Remove the provider in your app's AndroidManifest.xml, inside <application>, using the manifest merger's remove instruction:

<provider android:name="com.google.android.gms.games.provider.PlayGamesInitProvider" android:authorities="${applicationId}.playgamesinitprovider" tools:node="remove" />

(Your root <manifest> element needs xmlns:tools="http://schemas.android.com/tools".)

With the provider gone, the SDK starts only when your code calls it.

Then the next problem: Connect did nothing

Initialising late created a new bug. In Genesis the Connect button did nothing for several taps. The Play Games SDK learns which Activity is in the foreground from lifecycle callbacks it registers when it starts. Start it late and it has missed the current Activity's lifecycle, so it has nothing to show its UI on.

The fix in Genesis was to briefly open an invisible Activity right after initialising, so the SDK sees a foreground Activity arrive. After that, sign-in and cloud save worked end to end: connect, clear the app's data, restore.

Two smaller lessons from the same week:

How it slipped through twice more

The provider removal lived in Genesis's build script. When Backpack Battle and Tavern Heroes added Play Games later, they copied the JavaScript gate from Genesis, not the manifest change. Both showed the sheet at launch. Sovereign turned out to have the same hole.

All three were fixed and released the same evening. The general lesson is a good one: when you copy a fix between projects, copy the native and manifest parts too, not just the code you can see.

The check that prevents it

Every game's build script now writes the provider removal into the manifest and refuses to build without it. To verify a built APK yourself:

aapt2 dump xmltree app-release.apk --file AndroidManifest.xml | grep PlayGamesInitProvider

It must print nothing.

On Tavern Heroes, Play Games sign-in on an internal build failed with "Access blocked… has not completed the Google verification process". The Google Cloud project's OAuth consent screen was still in Testing mode with no test users. Publishing it needed branding details (home page, privacy policy, domain) filled in first.

A feature that needs setup in a console can be dead code even when the build is green. Test the tap itself on a real device, not just that the app boots.