rea-reverse

Online APK & AAB analyzer and Google Play pre-launch check

Drop an APK or AAB to read its manifest, native libraries and signing certificates, and to check it against the Google Play and sideloading rules that most often block a release.

Your file never leaves your browser. Parsing runs locally in a Web Worker. Nothing is uploaded. How to verify this yourself

Drop an .apk or .aab file here

or

The file is read in your browser. Up to 1 GiB.

Where will you ship it?

Defaults to today. Pick a future date to see upcoming requirements.

Most release blockers on Google Play can be read straight out of the file you are about to ship. The targetSdkVersion is in AndroidManifest.xml. Whether a native library is 16 KB aligned is written in its ELF program headers. Whether the build was signed with the debug key is written in the certificate. None of that needs a server, and none of it needs your source code.

This tool reads those fields from the finished APK or AAB, entirely inside your browser, and compares them with the Google Play and sideloading rules that most often stop a release. Every finding comes with the evidence it is based on, a fix, and a link to the official page that states the rule.

What it checks

It runs 34 checks: Google Play requirements, sideloading and install problems, signing, privacy and app protection. The IDs match the rule list used across this site, so a link such as #PLAY-02 in a report always means the same thing. The “When it fires” column gives the exact condition, for example that SIGN-03 only rejects when targetSdk is 30 or higher. If you only care about Google Play, the Google Play compliance checker is the same tool with the Play scenario pre-selected.

IDWhat is checkedSeverityWhen it firesApplies to
PLAY-01targetSdkVersion below the Google Play requirementWill be rejectedPlay only. Phones/tablets: targetSdk ≥ 36 from 2026-08-31 (high risk while an extension to 2026-11-01 is possible, if ≥ 35); Wear OS / Automotive ≥ 35; TV ≥ 34; XR ≥ 34. Form factor from required <uses-feature>.Google Play
PLAY-0216 KB page size: ELF segments not 16 KB alignedWill be rejected (from 2027-02-01)Play only. .so files in lib/arm64-v8a and lib/x86_64 with any PT_LOAD p_align < 0x4000. High risk until 2027-02-01, reject from then.Google Play
PLAY-0316 KB page size: uncompressed .so not 16 KB aligned in the ZIPWill be rejected (from 2027-02-01)Play, APK only. Uncompressed (STORED) 64-bit .so whose data offset is not a multiple of 16384; skipped when extractNativeLibs="true". High risk until 2027-02-01.Google Play
PLAY-04Missing 64-bit native librariesWill be rejectedPlay only. armeabi-v7a/armeabi without arm64-v8a, or x86 without x86_64; or an ELF whose class/machine does not match its ABI directory.Google Play
PLAY-06Debuggable or test-only buildWill be rejectedPlay only. application android:debuggable="true" or android:testOnly="true".Google Play
PLAY-07Package name uses a reserved prefixWill be rejectedPlay only. Package name com.example.*, com.android.* or android.*.Google Play
PLAY-08SMS or Call Log permissionsWill be rejectedPlay only. Any SMS or Call Log permission is requested.Google Play
PLAY-09QUERY_ALL_PACKAGES permissionHigh riskPlay only. QUERY_ALL_PACKAGES is requested (high risk: declaration review).Google Play
PLAY-10All files accessWill be rejectedPlay only. MANAGE_EXTERNAL_STORAGE → reject; requestLegacyExternalStorage="true" alone → high risk.Google Play
PLAY-12REQUEST_INSTALL_PACKAGES permissionHigh riskPlay only. REQUEST_INSTALL_PACKAGES is requested. DEX evidence of self-update comes in a later version.Google Play
PLAY-13Background location permissionHigh riskPlay only. ACCESS_BACKGROUND_LOCATION is requested.Google Play
PLAY-16Photo and video permissionsWill be rejectedPlay only, and only when targetSdk ≥ 33: READ_MEDIA_IMAGES or READ_MEDIA_VIDEO is requested.Google Play
SIDE-01targetSdkVersion too low to install on new Android versionsWill be rejectedOutside Play. targetSdk < 24 (Android 15+ refuses to install) or < 23 (Android 14+).Outside Play (sideload)
SIGN-01Signed with an Android debug certificateWill be rejectedAny signer certificate whose subject CN is "Android Debug" (the SDK debug keystore is CN=Android Debug, O=Android, C=US; framework templates such as React Native use other O values). Reject on Play; high risk outside Play. Google states that Play does not accept apps signed with a debug certificate; that Play identifies them by this subject is likely but not documented.Google Play / Outside Play (sideload)
SIGN-03Only a v1 (JAR) signatureWill be rejectedAPK only. No v2/v3 signature: reject only when targetSdk ≥ 30 (cannot install), high risk below 30; no signature at all is reported separately.Google Play / Outside Play (sideload)
PLAY-05An APK instead of an Android App Bundle for Google PlayHigh riskPlay scenario, APK files only. High risk: new apps must be published as an AAB (since August 2021); Google’s pages state the requirement for new apps. Reject for Android TV apps (required <uses-feature android.software.leanback>): Play no longer accepts APK updates for TV apps since 2023-06-30.Google Play
PLAY-11Accessibility service declaredHigh riskPlay only. Any <service> protected by BIND_ACCESSIBILITY_SERVICE. Its android:isAccessibilityTool value is read from the service config XML when the resource table resolves it.Google Play
PLAY-14Exact alarm permissionHigh riskPlay only. USE_EXACT_ALARM → high risk (only for apps whose core function is an alarm clock or calendar). SCHEDULE_EXACT_ALARM alone → advice (users can deny it).Google Play
PLAY-15Foreground service types and full-screen intentsHigh riskOnly when targetSdk ≥ 34. Reject (everywhere): a service declares a foregroundServiceType without its FOREGROUND_SERVICE_<TYPE> permission (it crashes when started). High risk: FOREGROUND_SERVICE without any typed service; on Play also every typed foreground service (Play Console declaration) and USE_FULL_SCREEN_INTENT. Which untyped services are started in the foreground needs DEX (later version).Google Play / Outside Play (sideload)
PLAY-17Contacts permission (new Play rule)AdvicePlay only. READ_CONTACTS is requested: advice; high risk when targetSdk ≥ 37 (the new minimum-scope rule applies to apps targeting Android 17, enforced from 2027-01-27).Google Play
SIDE-02Old targetSdk: Play Protect warning on installHigh riskOutside Play. targetSdk more than two API levels below the latest Android release on the check date (the latest level is kept in the rule data).Outside Play (sideload)
SIDE-03Permissions blocked for sideloaded apps by enhanced fraud protectionHigh riskOutside Play. RECEIVE_SMS, READ_SMS, a notification listener or an accessibility service. In the select markets where Google Play Protect’s enhanced fraud protection is active (Google does not publish a full list), installs of such apps from browsers, messaging apps or file managers are blocked.Outside Play (sideload)
SIDE-04Accessibility service marked as an accessibility toolHigh riskOutside Play. An accessibility service whose config sets isAccessibilityTool="true". Only a hint: whether the app really is a tool for people with disabilities needs a human check. Unknown when the config XML cannot be read.Outside Play (sideload)
SIDE-06High-risk combination of capabilitiesHigh riskOutside Play. Three or more of: SYSTEM_ALERT_WINDOW, an accessibility service, SMS permissions, a device admin receiver, a notification listener.Outside Play (sideload)
SIDE-07No launcher entryAdviceOutside Play. No activity or activity-alias with MAIN + LAUNCHER (or LEANBACK_LAUNCHER), and no keyboard, wallpaper, accessibility, dream, TV input, home-screen or other system-style component.Outside Play (sideload)
SIDE-08Split APK shipped as if it were a complete appWill be rejectedOutside Play, APK only. Reject (cannot install alone): the file is a split (<manifest split>, isFeatureSplit), which fails with INSTALL_FAILED_INVALID_APK "Full install must include a base package"; or a base APK whose <manifest> sets android:isSplitRequired="true" or android:requiredSplitTypes, which fails with INSTALL_FAILED_MISSING_SPLIT. High risk: a base APK flagged only with <application android:isSplitRequired> or the meta-data com.android.vending.splits.required. The installer does not read those, so it may install but is incomplete without its splits (code or resources from the splits can be missing at runtime).Outside Play (sideload)
SIDE-09Non-standard ZIP structureHigh riskAPK only. Duplicate entries, central directory / local header mismatches, unsafe paths, the encryption flag or an unknown compression method → high risk; extra bytes after the archive → advice.Google Play / Outside Play (sideload)
SIDE-10Android developer verification: what to registerAdviceOutside Play, APK only. Always lists the package name and signing certificate SHA-256 to register. High risk when the signer is the debug certificate or a public AOSP test key, which cannot prove ownership.Outside Play (sideload)
SIGN-02Signed with a publicly known keyWill be rejectedA signer certificate matches, by SHA-256, a key whose private half is public: the AOSP test certificates (testkey, platform, shared, media, …) or the React Native template’s debug.keystore (also in Expo’s bare template). Reject on Play; high risk outside Play.Google Play / Outside Play (sideload)
SIGN-04Weak signing key or certificate digestHigh riskRSA key under 2048 bits, a DSA key, or an MD5-based certificate signature → high risk; a SHA-1-based certificate signature → advice.Google Play / Outside Play (sideload)
SIGN-05Signing certificate expires before 22 October 2033Will be rejectedPlay only. A signer certificate’s notAfter is before 2033-10-22. APK: reject (the rule applies to the app signing key). AAB: advice only (the AAB carries your upload key; Google signs the app with the app signing key, and the 2033 rule is stated for that key).Google Play
SIGN-08ZIP alignment and resources.arsc storageWill be rejectedAPK only. Reject only when targetSdk ≥ 30 and resources.arsc is compressed or not 4-byte aligned (cannot install). Other uncompressed entries not 4-byte aligned → advice.Google Play / Outside Play (sideload)
PRIV-07Cleartext traffic or user-installed CAs trustedAdviceusesCleartextTraffic="true"; or not declared with targetSdk < 28 (cleartext then allowed by default); or the network security config permits cleartext or trusts user CAs outside <debug-overrides>. Unknown when the config cannot be read and nothing else is found.Google Play / Outside Play (sideload)
PROT-01App protection (packer / hardening) identifiedAdviceIdentification only: a commercial app-protection runtime by its library file name, or (weak signal) one very small classes.dex next to large assets. Protecting code is legitimate; this only explains the trade-offs.Google Play / Outside Play (sideload)

You choose a scenario before the check runs: Google Play, outside Play (sideloading or other stores), or both. Play-only rules such as the permission declarations are skipped when you only distribute outside Play, and install-time rules such as SIDE-01 apply everywhere.

You can also pick the date the rules are evaluated against. It defaults to today. Choosing a later date shows which requirements will start to bite, for example the 16 KB rule after 2027-02-01.

How your file stays private

The file is never uploaded. That is a property of how the page is built, not only a promise:

  • The page hands the browser’s File handle to a Web Worker. The worker reads slices of the file and decompresses entries with the browser’s built-in DecompressionStream. It contains no network code at all.
  • Only the parts that matter are read: the ZIP central directory, AndroidManifest.xml, the resource table (resources.arsc, or resources.pb in an AAB), the launcher icon, the accessibility-service and network-security-config XML when the manifest points to them, the first bytes of each .so and of the React Native bundle, small version files, and the signing data. A 200 MB APK is analyzed by reading a few megabytes.
  • After the report is shown, the whole file is hashed with SHA-256 in 4 MB slices, still inside the worker. The hash is shown on the page and included in your own exports. Next to it is a link that searches the hash on VirusTotal: a plain link, so nothing is requested until you click it, and even then only the hash is in the address. The file itself is never uploaded anywhere.
  • The analytics event sent after an analysis carries only coarse, fixed values: file kind, a size bucket, a duration bucket, success or an error code, and the number of failed checks. It never contains the file name, the package name, a hash or any file content. The full list is on the privacy page.
  • The tool page shows no ads.

How to verify it yourself

You do not have to take our word for it.

  1. Open your browser’s developer tools and switch to the Network tab before you choose a file. Run an analysis and look at every request that appears. None of them carries your file. Apart from this site, the only hosts you should see are Google Fonts and Google Analytics.
  2. Or load this page, then disconnect from the network (turn off Wi-Fi, or tick Offline in the Network tab), and run the analysis. It completes, because nothing needs to leave your machine.

How to read the results

Each check ends in one of five states:

  • Will be rejected: if the rule applies to your scenario, Google Play will block the release, or Android will refuse to install the package.
  • High risk: likely to trigger a policy declaration review, a Play Protect warning, or a requirement that becomes mandatory on a known date.
  • Advice: a best practice or an early warning.
  • Unknown: the tool could not decide. Typically a value is a resource reference it cannot resolve yet, or the part of the file the rule depends on failed to parse. Unknown is not a pass. Check those items by hand.
  • Passed: the tool looked and found nothing.

Every failed check lists its evidence, for example lib/arm64-v8a/libfoo.so: PT_LOAD p_align=0x1000, so you can confirm the finding with your own tools before changing anything.

A clean report is not an approval. Google Play reviews policy declarations, store listings, Data safety answers and runtime behavior that no file inspection can see. The results do not represent Google’s review decision. For source-level checks inside Android Studio, Google also offers Play Policy Insights.

Fixing the most common problems

16 KB page size (PLAY-02, PLAY-03)

Apps that target Android 15 or higher must support 16 KB memory pages on 64-bit devices. Google’s developer documentation states that from 2027-02-01, updates that do not comply cannot be published. Until then the tool reports these checks as high risk, not as rejections. Source: Support 16 KB page sizes.

  • ELF alignment (PLAY-02). Build native code with NDK r28 or later, which aligns to 16 KB by default. With NDK r27 or earlier, add the linker flag -Wl,-z,max-page-size=16384. For prebuilt .so files from an SDK vendor, ask the vendor for a 16 KB compatible version.
  • ZIP alignment (PLAY-03). Use Android Gradle Plugin 8.5.1 or later, which aligns uncompressed libraries correctly. If you cannot upgrade, set useLegacyPackaging = true so the libraries are compressed instead (installs get larger). You can confirm the result with zipalign -c -P 16 -v 4 app.apk.

targetSdk 36 (PLAY-01)

Since 2026-08-31, new apps and app updates for phones and tablets must target API level 36 (Android 16). You can request an extension in Play Console that runs until 2026-11-01. Wear OS and Android Automotive OS apps must target 35, and TV and XR apps 34; the tool reads uses-feature in the manifest to pick the right threshold. Source: Target API level requirements.

Raising targetSdk changes runtime behavior, so walk through the Android 16 behavior changes and test before you ship. The opposite case, SIDE-01, matters even outside Play: Android 14 refuses to install apps that target below API 23, and Android 15 and later refuse below API 24 (Android 15 behavior changes).

Debug certificate (SIGN-01)

A certificate whose subject is CN=Android Debug,O=Android,C=US is the key Android Studio generates for local builds. Google Play rejects it, and its private key sits on every developer machine, so anyone could sign an “update” that replaces yours. Create a dedicated release key (RSA 2048 bits or more), back it up, and sign release builds with it. On Play, enroll in Play App Signing so Google holds the app signing key and you keep an upload key. Sources: Sign your app, Play App Signing.

Only a v1 signature (SIGN-03)

The v1 (JAR) scheme signs individual ZIP entries and leaves the rest of the archive unprotected. Apps that target API 30 or higher must be signed with APK Signature Scheme v2 or later, or they will not install. The Android Gradle Plugin enables v2 and v3 by default, so a v1-only APK usually comes from a custom signing step. Sign with apksigner and keep v2/v3 enabled; once minSdk is 24 or higher you can drop v1. Always run zipalign before apksigner, never after. Sources: APK signing, apksigner, zipalign.

Permission findings (PLAY-08, 09, 10, 12, 13, 16)

These are not automatic rejections of the permission itself. They mean Google Play only allows the permission for specific core uses and asks you to fill in a declaration. If your app does not need it, remove it, including from libraries that merge it into your manifest. Otherwise use the narrower alternative: the SMS Retriever API instead of SMS permissions, <queries> instead of QUERY_ALL_PACKAGES, the Storage Access Framework or MediaStore instead of all files access, the system Photo Picker instead of READ_MEDIA_IMAGES. Note that from 2027-01-27 phone account verification is no longer an allowed use of READ_CALL_LOG (Policy deadlines). Each finding in the report links to its policy page: SMS and Call Log, package visibility, all files access, REQUEST_INSTALL_PACKAGES, background location, photo and video permissions.

AAB files and how to cross-check them with bundletool

An Android App Bundle stores its manifest and resource table as protobuf rather than binary XML. The tool decodes the base module’s manifest/AndroidManifest.xml, resources.pb and BundleConfig.pb, so an AAB gets the same manifest checks as an APK. References such as @string/app_name and @mipmap/ic_launcher are resolved to their default value and shown next to the raw resource ID. The report also lists the bundle’s modules (base, feature modules and asset packs, with their delivery mode) and the BundleConfig.pb settings that matter for 16 KB support: whether native libraries are kept uncompressed and at which page alignment.

The launcher icon is shown when it is a PNG or WebP bitmap; the highest-density one is picked. An adaptive icon is vector XML, which the tool does not render; it says so and shows the foreground bitmap when there is one.

To check the tool against Google’s own reader, run bundletool locally:

java -jar bundletool.jar dump manifest --bundle=app.aab
java -jar bundletool.jar dump resources --bundle=app.aab --values
java -jar bundletool.jar dump config --bundle=app.aab

The package, versionCode, versionName, min/target SDK, permissions, debuggable, label and icon should match the report. bundletool prints references by name (@string/app_name); the resource dump maps that name to the ID shown in the report and its values.

What it does not do

  • No malware verdict. It does not scan for viruses and does not say whether an app is safe to install.
  • No DEX decompilation. It does not turn classes.dex into Java or Kotlin. For that, use a local decompiler such as JADX (see the guides below).
  • No AAB conversion. It cannot turn an AAB into an installable APK in the browser; use bundletool for that. It reads the bundle as it is: there are no generated split APKs to check, so the ZIP alignment check (PLAY-03) and the v1-only signature check (SIGN-03) apply to APKs only.
  • Detection by names, not by code. Frameworks, SDKs and app protection are identified from file names, the manifest and small version files. A renamed library or an SDK without a manifest component is not found, and a version is shown only when the package states it. Fingerprints from DEX code, and the checks that need it (self-update, dynamic code loading, R8, Play Integrity, Data safety hints), come in a later version.
  • Packers are identified, never handled. Packing and app hardening are legitimate protection. PROT-01 names what it found and explains the false-positive and Play App Signing risks. The tool never unpacks, modifies, re-signs or repackages anything, and it gives no advice on hiding behavior from reviewers or scanners.
  • No full signature verification. Certificates are read and checked, but v1/v2/v3 signatures are not cryptographically verified yet; use apksigner verify -v for that.
  • No review decision. Results do not represent Google’s review decision, and a clean report does not guarantee approval.

FAQ

Is the file really not uploaded? Yes. Analysis runs in a Web Worker in your tab. You can confirm it with the Network tab or by going offline, as described in How to verify it yourself.

Which file types are supported? .apk and .aab up to 1 GiB. Split APK sets (.apks, .xapk) are not supported in the first version.

Why do I get “Unknown”? A value the check depends on could not be read, for example a targetSdkVersion written as a resource reference, or a damaged signing block. Treat Unknown as “check this yourself”, not as a pass.

Does a clean report mean Google Play will approve my app? No. Play also reviews declarations, store listing, Data safety and runtime behavior. The tool only covers what can be read from the file.

How current are the rules? Each rule records when it was last checked against its official source and is reviewed monthly. A rule not checked for 90 days is marked as needing review in the report.