Last reviewed: 31 August 2026 · HappyMynds · 5 min read

When DroidXP is enough, and when you still need apktool / aapt / lint

AdSense reviewers and engineers smell the same lie: a website that claims to replace the Android SDK. We do not. Here is the job table we use at the desk.

What this page is for

You have a file called app-release.apk (or a folder of splits) and a question that sounds like “is this the build?” The browser can answer some of those questions in two minutes. Android SDK tools answer the rest. Mixing the two without a job table is how tickets become “DroidXP said the package is empty, so the APK is broken” — which is usually false.

This is the table we use at the desk. It is also how we want a reviewer to read the site: Home and About name HappyMynds; the Android hub starts with the analyzer; this page says where we stop.

Job → tool

Confirm the file is a ZIP with DEX and a manifest, and hash it. APK Analyzer. Enough when QA sent “the build” and you want to know if it is empty, a debug APK, or a renamed AAB. Screenshot the SHA-256 next to the CI artifact name.

Read package / versionCode / permissions as Play would. aapt dump badging (or aapt2 dump badging). Our analyzer’s printable-string hints are clues. Side-by-side: heuristic block blank, aapt prints package: name='com.example.notes' versionCode='24003'. That is the usual screenshot for this guide. See versionCode vs versionName vs applicationId.

Edit or read decoded AndroidManifest.xml and resources. apktool. The Manifest Validator is for text you already have (source, merged manifest from CI, or apktool output). It uses the browser DOMParser. It does not decode binary AXML.

Readable permission names from a paste. Permissions Decoder. Policy still lives in Play Console. See permissions that cause review.

exported on API 31+. Lint or a text search after apktool. We do not fail that in the validator yet. Exported after Android 12.

Copy leftovers in resources.arsc. String extractor for a skim; apktool for IDs and locales. A UTF-16 scan is not a string resource table.

Sign or verify signatures. apksigner on your machine. Signer guide prints commands only. Whole-file SHA-256 is not a certificate fingerprint. Play hashes.

Splits / AAB. bundletool + analyzer per slice. What the browser can see.

Deep links. Syntax in the tester; resolution on a device. ADB guide.

Upload identity, policy, Data safety. Play Console. Nothing on this site substitutes.

Desk sequence we actually run

  1. Drop the file on the analyzer. If JSZip lists BundleConfig.pb or base/manifest/, stop: that is a bundle, not an APK. Use bundletool.
  2. Note DEX count, lib/**/*.so, and SHA-256. If QA expected native code and lib/ is empty, you may have base.apk without the ABI split — not “the app has no JNI.”
  3. Run aapt dump badging your.apk. Copy package:, sdkVersion, targetSdkVersion, and uses-permission: into the ticket. If aapt fails, the file is not a valid APK regardless of what the ZIP listing showed.
  4. If you need XML: apktool d your.apk -o out, then paste out/AndroidManifest.xml into the Manifest Validator for well-formedness. Search that text for intent-filter and exported yourself.
  5. Paste permission names into the decoder. Remove leftovers in Gradle, do not “explain them away” in the ticket.
  6. Verify signing locally: apksigner verify --verbose --print-certs your.apk. Compare the cert digest to Play Console → App signing, not to the analyzer’s whole-file hash.

Worked contrast — blank heuristic vs aapt

Drop a release APK on the analyzer. “Possible package” empty. Someone concludes the APK is unsigned or corrupt. Run aapt: package and versions print. The binary manifest simply did not expose ASCII package=. That failure mode is documented on the analyzer page; this guide exists so we do not have to repeat it in every ticket.

Expected aapt shape (redacted):

package: name='com.example.notes' versionCode='24003' versionName='2.4.0'
sdkVersion:'24'
targetSdkVersion:'35'
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.POST_NOTIFICATIONS'

If versionCode in aapt does not match the git tag you thought you shipped, stop before Play. Reused integers fail the upload; the analyzer hash differing from CI is the faster check. See the versionCode article for flavor suffixes that look like “wrong listing.”

Mistakes this table is meant to prevent

  • Treating a green Manifest Validator report as “exported is fine.” The validator does not walk every component for the API 31+ attribute.
  • Pasting binary AXML into the decoder or validator. Both want text.
  • Comparing a local universal APK hash to a Play-split, re-signed install and filing a tamper ticket against your own pipeline.
  • Sideloading base.apk alone, seeing no .so files, and disabling a JNI feature in the next commit.
  • Using the version checker as a device probe. It is a local API 16–36 table.

Commands worth keeping in the runbook

aapt dump badging app-release.apk
aapt dump permissions app-release.apk
aapt dump xmltree app-release.apk AndroidManifest.xml
apktool d app-release.apk -o apktool-out
apksigner verify --verbose --print-certs app-release.apk
bundletool build-apks --bundle app.aab --output app.apks --mode=universal

build-tools versions differ; if aapt is missing, use the copy under $ANDROID_HOME/build-tools/<ver>/. apktool needs Java. None of that runs in this tab.

How we want a reviewer to read this site

The keep-index Android tools are local checks with stated limits. Commodity formatters stay public and noindex. This page is the contract: we do not replace apktool, aapt, lint, or Play Console. If a tool page ever sounds like it does, the tool page is wrong — file it on Contact.