Why I put forced in-app updates (IMMEDIATE) into 17 apps: users on old versions earned nothing after the ad SDK swap
When I replaced the ads SDK in July 2026, users who had not updated produced zero revenue. No fix, policy or consent form reaches an old version. How I added Play In-App Update in IMMEDIATE mode to every app, why it can only be verified on a Play-installed build, and what shipped alongside it.
Why forced
In mid-July 2026 every app I run dropped to zero real ad impressions. It was not an account issue or invalid traffic; the legacy ads SDK (play-services-ads) had broken. I moved every app to the next-generation SDK (ads-mobile-sdk) and re-released. Then, for weeks afterwards, the reports showed users who had not updated still earning nothing.
That changed the standard. Whether it is an ads SDK, a policy fix or a consent form, a fix you ship never reaches users who stay on the old version. A FLEXIBLE update can simply be postponed. So on 11 September 2026 I added IMMEDIATE (forced) in-app updates to all 17 apps and released them together. When a newer version exists on Play, Google's full-screen update UI appears at launch and the app cannot be used until it updates.
Implementation
One dependency: com.google.android.play:app-update:2.1.0. Each app gets a class with a single static method, called from the entry activity's onResume.
That is all there is to it:
- Request
appUpdateInfofromAppUpdateManagerFactory.create(context) - If
updateAvailability() == UPDATE_AVAILABLEandisUpdateTypeAllowed(IMMEDIATE) startUpdateFlowForResult(info, activity, AppUpdateOptions.newBuilder(IMMEDIATE).build(), REQUEST_CODE)- In
onResume, ifDEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS, do step 3 again (resumes when the user backed out mid-way)
No result callback, no strings, no snackbar. IMMEDIATE is handled entirely by Google's UI, so the app needs none. Apps with several entry points (the remote apps have main, Bluetooth and Wi-Fi activities) call it from every one of them. The one FLEXIBLE implementation I had was replaced with IMMEDIATE.
Verify only on a Play-installed build
On a debug build or a sideloaded APK, getAppUpdateInfo fails and nothing appears. That is why "I added it but nothing shows" is such a common report; usually the test method is wrong.
The check goes:
- Upload a lower-versionCode build to the internal testing track and install it via Play
- Upload a higher-versionCode build to the same track
- Launch the app on the device; the forced update screen must appear
In practice I also confirmed, after production release, that the Play-installed build showed the forced update screen and the EEA consent form on a physical phone.
What shipped with it
Two more things rode the same release:
- UMP (GDPR consent) code for the 14 apps that lacked it. Users on old versions would never see the form, so bundling it with the forced update was the right call.
- A data-safety form review, since releases were bundled anyway.
Building, signing and uploading 17 apps in a day produced incidents. I split the builds across agents and 9 came out unsigned, because the signing-key environment variable was not in the instructions. A pre-upload check that compares the versionName and signer inside the AAB with the source caught it. File timestamps cannot. One app was signed with an old keystore and Play rejected it as "wrong key"; it was re-signed with the shared keystore.
Version scheme
While releasing everything I also unified the versionCode rule: versionCode is versionName with the dots removed. 1.2.3 is 123, the next release is 1.2.4 / 124, one patch per release. Four apps were using values like 12 and 13 and were brought in line. Play never lets versionCode decrease, so apps that already had one extra digit (for example 10018) keep that width and only bump the patch.
Summary
- No fix reaches users on old versions. During the ads SDK incident, their revenue was zero.
- IMMEDIATE is short to implement and needs no app-side UI.
- It can only be verified on a Play internal-testing install.
- For bulk releases, check the AAB contents (signer, version) against the source. Do not trust timestamps.