Android security advice that expired: fourteen statements, and the version that ended each one
Fourteen statements about Android security that were correct when somebody learned them and are not correct now. Each one is paired with the API level, the Android Gradle Plugin version or the Google turndown that falsified it, the platform page it was read from, and that page's own last-updated stamp. Google revises these pages independently, and a claim without a stamp cannot be re-checked. Read 3 September 2026.
Almost everything below was correct when somebody learned it. That is what makes it dangerous: it was not picked up from a bad blog post, it was picked up from a good one, and the platform moved underneath it.
Fourteen statements follow. Each is paired with what falsified it, an API level or an Android Gradle Plugin version or a Google turndown, and with the page it was read from and that page's own last-updated stamp. Google revises these pages independently, and the spread across the nine behind this article runs from 2026-08-28 to 2025-03-10. A claim with no stamp behind it is one you cannot re-check.
Read 3 September 2026, from the raw pages and not from a search result.
1 · The transport layer
1.1 “Android trusts certificates the user installs”
It stopped being the default for anything targeting API 24 or above. The Network Security Configuration page states it plainly: "By default, secure connections (using protocols like TLS and HTTPS) from all apps trust the pre-installed system CAs, and apps targeting Android 6.0 (API level 23) and lower also trust the user-added CA store by default."
The boundary is the level your app targets, not the version of Android the device runs. An app targeting API 24 or above on a device running Android 6 does not trust the user store either.
This is the most consequential row for anyone testing. An intercepting proxy that used to just work now needs a debug-overrides block or a rebuilt artefact, and an app that appears to resist interception may simply be targeting API 24 or above.
Page stamp: 2026-08-28.
1.2 “Cleartext was switched off in Android 7”
Android 9, API level 28. The same page gives the whole history in two sentences: "Up to Android 8.1 (API level 27), cleartext support is enabled by default", and "Starting with Android 9 (API level 28), cleartext support is disabled by default."
The adjacent change is what makes this one easy to misremember. API 24 is where the default base-config stopped including the user CA store (compare the two default blocks on the same page), so a real change did happen at API 24, but to the CA store and not to cleartext.
Page stamp: 2026-08-28.
1.3 “Android does not do certificate transparency”
True until API 36, and it is now three different answers depending on the level. Verbatim, in order:
- "On Android 15 (API level 35) and lower, certificate transparency is not available."
- "On Android 16 (API level 36), certificate transparency is disabled by default. Apps can opt in to the feature either globally or on a per-domain basis."
- "Starting with Android 17 (API level 37), certificate transparency is enabled by default. Apps can opt out of the feature either globally or on a per-domain basis."
The answer flips from unavailable to available but off to on unless you turn it off, across two releases. An assessment reporting "not supported on Android" is describing the pre-API-36 platform.
One line beside it catches people out during testing: "Certificate transparency verification isn't performed on connections that use custom trust anchors."
Page stamp: 2026-08-28.
2 · The manifest and the components
2.1 “Leaving android:exported unset is a common finding”
It has not been possible to ship one since Android 12. The behaviour-changes page carries it as a warning: "If an activity, service, or broadcast receiver uses intent filters and doesn't have an explicitly-declared value for android:exported, your app can't be installed on a device that runs Android 12 or higher."
Two conditions are doing work in that sentence and they are easy to run together. The declaration is required of apps that target Android 12 or higher; the install failure happens on devices that run it. A shipped app therefore cannot have one unset; the build would not have installed.
The real finding now is android:exported="true" set deliberately, on a component that did not need it.
Page stamp: 2026-08-14.
2.2 “You can enumerate the installed packages to detect root tools”
Not since apps started targeting API 30. The package-visibility page: "When an app targets Android 11 (API level 30) or higher and queries for information about the other apps that are installed on a device, the system filters this information by default. This filtering behavior means that your app can't detect all the apps installed on a device."
Increased visibility is declarable through the <queries> element, or, as Google frames it, "in the rare cases where the <queries> element doesn't provide adequate package visibility", through the QUERY_ALL_PACKAGES permission, whose use "is subject to approval" if you publish on Play.
Our reading, not a quotation: a package-name check written before this and never revisited does not throw and does not warn. It returns a clean result on a filtered view, which reads as an absence. Whether that matters depends on what the check gates, which is a question about your app.
Page stamp: 2026-08-14.
2.3 “Intent redirection is something you have to defend against yourself”
Android 16 does some of it by default. "Android 16 introduces a by-default security hardening solution to Intent redirection exploits. In most cases, apps that use intents normally won't experience any compatibility issues."
There is an opt-out, and an opt-out sitting in a codebase is a decision somebody made: "In Android 16, you can opt out of security protections by using the removeLaunchSecurityProtection() method on the Intent object."
Page stamp: 2025-03-10. The oldest of the nine, and the one to re-check first.
3 · The integrity signals
3.1 “Check SafetyNet”
There is nothing to check. "The SafetyNet Attestation API was deprecated in 2022 and fully turned down in January 2025."
Page stamp: 2026-03-06.
3.2 “Play Integrity tells you whether the device is rooted”
By default it does not return the labels people mean by that. MEETS_BASIC_INTEGRITY and MEETS_STRONG_INTEGRITY are among the "optional device labels" a developer has to opt in to receive: "If you opt in to receive additional labels in the integrity verdict, deviceRecognitionVerdict can contain the following additional labels."
An integration that was set up and never revisited is reading a narrower verdict than the people relying on it assume.
Page stamp: 2026-05-01.
3.3 “MEETS_STRONG_INTEGRITY means the device is patched”
On some Android versions, and not on others. The same constant carries two meanings. "On Android 13 and higher, the MEETS_STRONG_INTEGRITY verdict requires MEETS_DEVICE_INTEGRITY and security updates in the last year for all partitions of the device." And then: "On Android 12 and lower, the MEETS_STRONG_INTEGRITY verdict only requires hardware-backed proof of boot integrity and does not require the device to have a recent security update."
Google's own recommendation follows from it: "when using the MEETS_STRONG_INTEGRITY, it is recommended to also take into account the Android SDK version in the deviceAttributes field."
Page stamp: 2026-05-01.
3.4 “Our attestation verifier pins the Google root, so it is fine”
A second root certificate starts signing on 1 February 2026. From the key attestation page, above the certificate block: "Important: The following root certificate will begin signing attestation certificate chains on February 1, 2026."
This is the only row in the list with a date ahead of it, and the only one that fails hard. A verifier that hard-codes the single earlier root will reject genuine attestations from new devices, and the refusals look exactly like the attack the verifier exists to stop.
Page stamp: 2026-07-09.
4 · The build
4.1 “Turn on R8 full mode”
The flag that exists is the opt-out. It used to be the opt-in, and the sense of it reversed. The version history states both ends of it. At AGP 7.0: "Full mode available: Introduced as an opt-in feature using android.enableR8.fullMode=true." At AGP 8.0: "Full mode by default: R8 full mode provides significantly more powerful optimization. It is enabled by default. You can opt out using android.enableR8.fullMode=false."
So android.enableR8.fullMode in a gradle.properties file means opposite things depending on when it was written and what it is set to. A line added in 2021 to switch full mode on may now be switching it off, if it was flipped while debugging and never flipped back. Grep for it.
Page stamp: 2026-08-27.
4.2 “Add -repackageclasses to flatten the package structure”
Not needed from AGP 9.1. "Classes repackaged by default: R8 repackages classes (moving them to the unnamed package, at the top level) to compact DEX further, eliminating the need to specify -repackageclasses option."
Page stamp: 2026-08-27.
4.3 “Use getDefaultProguardFile('proguard-android.txt')”
Support for it was dropped at AGP 9.0. "Support for getDefaultProguardFile("proguard-android.txt") has been dropped, because it includes -dontoptimize, which should be avoided. Instead, use "proguard-android-optimize.txt"."
So a project using the default file was not being optimised. That sat inside a one-line build configuration for years, and it is the first thing to check on an older codebase you inherit.
Page stamp: 2026-08-27.
5 · The Keystore
5.1 “Call isInsideSecurityHardware() to check the key is in hardware”
For anything targeting API 29 or above, the method to call is getSecurityLevel(). The Keystore page splits it by target SDK: "If your app targets Android 9 (API level 28) or lower, inspect the boolean return value of KeyInfo.isInsideSecurityHardware()", and elsewhere, "for apps targeting Android 10 (API level 29) or higher, KeyInfo.getSecurityLevel()".
The old method answers yes or no; the new one returns a level. The page describes what counts as hardware as "Return values matching KeyProperties.SecurityLevelEnum.TRUSTED_ENVIRONMENT or KeyProperties.SecurityLevelEnum.STRONGBOX": two values, not one.
Page stamp: 2026-03-06.
6 · How to check any of this yourself
Every claim above was read from a page you can open. The method matters more than the list:
- Go to the platform page. All nine sources here are on
developer.android.com. None of them is behind a login and none needed anything but a fetch. - Read the page's own stamp. It is at the foot of every page on that site, in the form
Last updated YYYY-MM-DD UTC. If a claim in front of you has no stamp behind it, that is the missing piece. - Check whether the boundary is about targeting or about running. Most rows above turn on it, and most wrong versions of them get it backwards.
- Search the page for the constant, not for the concept.
MEETS_STRONG_INTEGRITY,android.enableR8.fullMode,QUERY_ALL_PACKAGES,isInsideSecurityHardware. Concepts get paraphrased in both directions; identifiers do not.
7 · This page expires too
Nine pages were read on one day, and Google revises them independently: one already carries a 2025 stamp, and more than seventeen months separate the newest from the oldest.
On 3 September 2026 each row matched the page it cites, character for character, and the pages are named so you can check them in less time than it took to read this.
If a row here disagrees with the page it cites, the page is right.
About the authors
Abhinav A
Lead — VAPT & Security Assessments
Leads Security Brigade's VAPT delivery team, having progressed from Security Consultant to Team Lead. Has executed advanced penetration tests across BFSI, fintech, QSR and telecom.
Siddarth G
Practice Director — Cybersecurity
Leads Security Brigade's offensive security practice with deep expertise in vulnerability research, penetration testing, and red team operations. Ranked Top 80 globally on Bugcrowd.
Continue reading
All articles →What a Play Integrity verdict actually returns, and who it is evidence for
The Play Integrity API returns three families of verdict, and the labels most conversations about it are really about are not among the ones you get by default. This is what Google documents it returning, the limits Google publishes about its own product, and the reason every documented Android integrity primitive ends up producing evidence for a server rather than an answer for a device. Read 3 September 2026.
Android 16 is now the submission gate: target API 36, and what the 1 November window actually is
Since 31 August 2026, Google Play has applied two requirements to two different sets of apps under one date, with two very different verbs. A new app or an app update must target Android 16 (API level 36) or higher to be submitted. An app already on Play must target Android 15 (API level 35) or higher to stay available to new users on newer devices. A team that has not shipped an update since it moved to API 35 is compliant on availability and blocked on submission the moment it tries to ship. Checked 2 September 2026.
Every Play package must be registered by 30 September 2026 — and the install-side milestone is a different obligation
Two obligations, one date. Install-side verification enforcement begins on 30 September 2026 for users installing from seven named stores in Brazil, Indonesia, Singapore and Thailand, on certified devices running Android 7+. Separately, on the same date, all Play packages must be registered under Android developer verification, and Google's own word for the consequence is global removal from Google Play. Registration is decided on app signing key ownership and install share, so a rotated upload key, an agency-held key, or one package name shipping from two keys has to be resolved before the package can be registered. Every quotation checked 2 September 2026.