App Not Installed as Package Appears to Be Invalid: Fix Your APK
On this page
Short answer: “App not installed as package appears to be invalid” is one sentence that Android’s package installer shows for a whole family of failures. In my tests on Android 14 and Android 16 emulators, the causes that actually produced it were an unsigned APK, an APK with only a v1 signature, an APK changed after it was signed, and a single split APK installed on its own. A compressed resources.arsc and a truncated download fail too, but with different wording. Run adb install to get the real INSTALL_* code, then fix the build. Never patch the device or turn off signature checks.
This site’s APK & AAB analyzer catches most of these causes before you hand the file to anyone. It reads the signing block, the ZIP layout and the manifest in your browser, and nothing is uploaded. All output below comes from APKs I built and signed myself.
Who this is for: Android developers and testers who install their own builds from a file.
What you will learn:
- Which installer failures turn into “package appears to be invalid”, and which do not
- How to read the real
INSTALL_PARSE_FAILED_*code - What the analyzer’s SIGN-03, SIGN-08, SIDE-08 and SIDE-09 rules check, and what they cannot see
- The fix for each cause, using only the official build tools
Only install and inspect apps you build or are authorized to test, on devices you control.
Where the message comes from
The phone’s installer does not show the platform’s error code. It turns the code into a public status and picks a sentence for that status. In AOSP, PackageManager.installStatusToPublicStatus maps twenty codes to STATUS_FAILURE_INVALID. Among them are INSTALL_PARSE_FAILED_NO_CERTIFICATES, INSTALL_PARSE_FAILED_NOT_APK, INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, INSTALL_FAILED_INVALID_APK, INSTALL_FAILED_TEST_ONLY and even INSTALL_FAILED_VERSION_DOWNGRADE. The installer app’s strings.xml then shows install_failed_invalid_apk: “App not installed as package appears to be invalid.”
I installed each test APK through the Files app on an Android 14 emulator set to Chinese. For the unsigned, v1-only and tampered APKs, the installer showed 应用未安装:软件包似乎无效。, the Chinese translation of that same string, and logcat recorded only InstallFailed: Installation status code: 4. Status 4 is STATUS_FAILURE_INVALID. The specific reason never reaches the screen or the log, so you have to ask for it.
Two failures in this guide look different on the phone:
- A compressed
resources.arscfails with code -124, which maps to the generic status. The dialog only said “App not installed.” (未安装应用。). - A truncated file never got as far as installing. The installer said “There was a problem parsing the package.” (解析软件包时出现问题。).
Step 1: get the real code with adb
Connect a device with USB debugging enabled, or start an emulator, and install the same file with adb:
adb install app-release.apk
These are the results for my test package dev.example.invaliddemo (minSdk 24, targetSdk 35). The Android 14 (API 34) and Android 16 (API 36) emulators printed the same codes. Temporary paths are shortened here:
$ adb install unsigned.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl…tmp/base.apk: Attempt to get length of null array]
$ adb install v1only.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Scanning Failed.: No signature found in package of version 2 or newer for package dev.example.invaliddemo]
$ adb install modified.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from …/base.apk: META-INF/RELEASE.SF indicates …/base.apk is signed using APK Signature Scheme v2, but no such signature was found. Signature stripped?]
$ adb install tampered.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from …/base.apk using APK Signature Scheme v3: SHA-256 digest of contents did not verify]
$ adb install arsc-compressed.apk
Failure [-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]
$ adb install truncated.apk
Failure [INSTALL_PARSE_FAILED_NOT_APK: Failed to parse …/base.apk: Failed to load asset path …/base.apk]
$ adb install base-fr.apk
Failure [INSTALL_FAILED_INVALID_APK: Full install must include a base package]
$ adb install app.aab
adb: filename doesn't end .apk or .apex: app.aab
$ adb install testonly.apk
Failure [INSTALL_FAILED_TEST_ONLY: Failed to install test-only apk. Did you forget to add -t?]
(testonly.apk was only run on the Android 16 emulator.) The code tells you where to look: NO_CERTIFICATES is signing, NOT_APK the file itself, -124 resources.arsc, and INVALID_APK with “base package” splits.
Step 2: check the file in the analyzer
Open the APK & AAB analyzer, choose Outside Play (sideload) or Both, and drop the APK. For a release you plan to upload, the Play compliance checker runs the same rules with Google Play preselected. These are the results it gave for my files, with the evidence lines exactly as the report prints them:
| File | Rule and severity | Evidence |
|---|---|---|
unsigned.apk |
SIGN-03, reject | no v1, v2, v3 or v3.1 signature found |
v1only.apk |
SIGN-03, reject | v1 signature only (no APK Signing Block with v2/v3), targetSdkVersion=35 |
modified.apk |
SIGN-03, reject | the same v1-only evidence; the ZIP tool dropped the signing block |
arsc-compressed.apk |
SIGN-08, reject | resources.arsc is compressed, targetSdkVersion=35 |
base-fr.apk |
SIDE-08, reject | <manifest split="config.fr"> (this file is a split, not the base APK) |
truncated.apk |
no report | “The file looks like a ZIP but its internal structure is damaged.” |
tampered.apk |
nothing | the analyzer does not verify signatures cryptographically |
app.aab |
none of the above | read as an app bundle; APK-only rules are skipped |
Note the last two rows: the analyzer reads certificates and schemes but does not recompute signature digests yet, so use apksigner verify for that.
Cause 1: no signature, or only v1
Android refuses to install an unsigned APK. Since Android 11, an app that targets API 30 or higher also needs APK Signature Scheme v2 or newer: “Users can’t install or update apps that are only signed with APK Signature Scheme v1 on devices that run Android 11.”
SIGN-03 encodes this. Its condition: “APK only. No v2/v3 signature: reject only when targetSdk ≥ 30 (cannot install), high risk below 30; no signature at all is reported separately.” For an unsigned file, the finding carries the note “The APK is not signed at all; Android will not install it.”
Fix it by signing with apksigner, which turns on v2 and v3 by default, or with Android Studio’s release signing config. Then check:
$ apksigner verify -v v1only.apk
DOES NOT VERIFY
ERROR: Target SDK version 35 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme
A correctly signed build prints Verifies and Verified using v2 scheme (APK Signature Scheme v2): true. A leftover jarsigner step in a build script is the usual culprit.
Cause 2: the APK changed after it was signed
The apksigner documentation is direct: “If you sign your APK using apksigner and make further changes to the APK, the APK’s signature is invalidated.” I tried two kinds of change:
- Rewriting the ZIP. Adding a file with
ziprewrote the archive and dropped the APK Signing Block. Only the v1 files underMETA-INF/remained, and they still say v2 was used, hence “Signature stripped?”. The analyzer shows this as SIGN-03 with v1-only evidence. It also raised SIGN-08 at advice level, because the added file was stored without 4-byte alignment:1 uncompressed entry not 4-byte aligned, e.g. extra.txt at 2957. If a build you know was signed with v2/v3 shows up as v1-only, something rewrote it after signing. - Changing bytes in place. I flipped one bit inside
resources.arsc. The layout and the signing block were untouched, so the analyzer reported nothing. The device rejected it (“SHA-256 digest of contents did not verify”), and so didapksigner verify -v:APK integrity check failed. CHUNKED_SHA256 digest mismatch.
The fix is ordering. Run zipalign before signing, never after, and make signing the last step that touches the file. Any post-processing, such as adding a channel file, stripping resources or running an app-protection tool, belongs before apksigner. Then sign again with your own key and run apksigner verify -v.
Packing and hardening tools are legitimate, and many of them re-sign the output. If a protected build fails with NO_CERTIFICATES, follow the vendor’s documented signing step and sign the result with your release key, then verify it. The analyzer’s PROT-01 (advice) names a protection runtime when it finds one and explains the trade-offs: heuristic scanners can flag packers, and self-checking protections can break when Play App Signing re-signs the app. If a Play build is involved, prefer a product that documents Play App Signing support.
Cause 3: compressed or misaligned resources.arsc
From the Android 11 behavior changes: “Apps that target Android 11 (API level 30) or higher can’t be installed if they contain a compressed resources.arsc file or if this file is not aligned on a 4-byte boundary.”
SIGN-08’s condition: “APK 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.”
I produced this by unzipping and re-zipping the APK with zip -9, as a hand-made “repack” step would. unzip -v shows the difference:
$ unzip -v good.apk | grep arsc
688 Stored 688 0% 01-01-1980 00:00 c58b3cbb resources.arsc
$ unzip -v arsc-compressed.apk | grep arsc
688 Defl:X 189 73% 01-01-1980 00:00 c58b3cbb resources.arsc
Be aware that zipalign -c passed this file (630 resources.arsc (OK - compressed)), because it only checks entries that are stored. Look at the method column, or use the analyzer.
Fix: don’t re-zip APKs by hand. Rebuild with AGP, or keep resources.arsc stored, run zipalign and then sign. The current zipalign page marks -p as deprecated in favour of -P 16, so the order is:
zipalign -P 16 -f -v 4 unaligned.apk aligned.apk
apksigner sign --ks release.jks --out app-release.apk aligned.apk
zipalign -c -P 16 -v 4 app-release.apk
The 4 is what gives resources.arsc its 4-byte alignment; -P 16 only page-aligns uncompressed .so files.
Cause 4: an AAB, or one piece of a split APK set
An .aab is a publishing format, not an installable package, and adb refuses it before it reaches the device. The analyzer reads it as an app bundle and skips APK-only rules such as SIGN-03 and SIGN-08.
Split APKs are the subtler case. bundletool build-apks without options produced base-master.apk and base-fr.apk for my bundle. Installed alone, the language split failed with INSTALL_FAILED_INVALID_APK: Full install must include a base package. SIDE-08 flags it, and its condition starts: “Outside Play, APK only. Reject (cannot install alone): the file is a split (
A base APK that “requires” splits is less clear-cut, because where the flag sits matters. A base APK that I marked with <application android:isSplitRequired="true"> installed alone with Success on both emulators. The reason is in AOSP: ApkLiteParseUtils reads isSplitRequired and requiredSplitTypes only from the <manifest> element, and PackageInstallerSession rejects a full install with INSTALL_FAILED_MISSING_SPLIT only when that manifest-level flag is set and no matching split is staged. On the Android 16 emulator, the same attribute moved to <manifest> failed with INSTALL_FAILED_MISSING_SPLIT: Missing split for …. android:requiredSplitTypes="language" failed the same way (aapt2 also writes isSplitRequired="true" on <manifest> when it sees that attribute, and ApkLite treats any required split type as “split required” anyway). SIDE-08 now reports the <application> flag, and bundletool’s com.android.vending.splits.required meta-data (read by Play, not by the installer), as high risk rather than reject: “may install but is incomplete without its splits (code or resources from the splits can be missing at runtime)”.
Fix: for direct distribution, build one universal APK, which bundletool describes as “a single APK that includes all of your app’s code and resources”:
java -jar bundletool.jar build-apks --bundle=app.aab --output=universal.apks \
--mode=universal --ks=release.jks --ks-key-alias=release
Unzip universal.apks and ship universal.apk, which installed with Success. For testing, install the whole set with bundletool install-apks --apks=app.apks, or every split at once with adb install-multiple base-master.apk base-fr.apk. Both installed my split set.
Cause 5: a damaged download
A truncated or corrupted file is not a build problem, but it produces the same complaints. My 2,000-byte cut of a valid APK gave INSTALL_PARSE_FAILED_NOT_APK through adb and “There was a problem parsing the package” on the phone. The analyzer stops with “The file looks like a ZIP but its internal structure is damaged.” Publish the SHA-256 of each release (the analyzer shows it for any file it can read; shasum -a 256 app.apk works too) so testers can compare before reporting a bug.
SIDE-09 (high risk, both scenarios) covers the related “non-standard ZIP” case: “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.” I did not build a sample for it; a finding there means a non-standard tool touched the file.
Two causes outside this list
- Test-only builds. APKs that Android Studio builds for its Run button carry
android:testOnly="true".adb installneeds-tfor them, and the installer mapsINSTALL_FAILED_TEST_ONLYto the “invalid” status. The analyzer’s PLAY-06 reportstestOnlywhen you choose the Google Play or Both scenario. Share a build from the release variant instead. - Downgrades map to the same status in AOSP. If the code is
INSTALL_FAILED_VERSION_DOWNGRADE, raiseversionCode. See the package-conflict guide for a real run.
What REA 6.4.0 adds
REA, the open-source project by morluto, has no packaging or policy checks. On the device side, its install-adb-package contract says the device’s “Success/Failure verdict is preserved with its reason”. In my run with adb 37.0.1, though, installing unsigned.apk returned only unreadable_output (“Analysis returned an unreadable result”). A successful install returned the APK’s sha256 and size as Evidence. Use plain adb install for the failure code. rea inspect-artifact states that its ZIP inventory “lists central-directory entries only”, so the APK Signing Block is out of scope, and it failed on the truncated file with artifact_operation_failed. rea inspect-android-package needs a JADX MCP JAR, and its result says signature_verification: "not_performed".
FAQ
Is there a setting that lets the phone install it anyway? No. Signature, parsing and split checks are part of the platform. The only fix is a correctly built and signed APK.
The same APK installs on one phone and fails on another.
Compare the code on both. The v1-only and resources.arsc checks for apps targeting API 30+ arrived with Android 11, so an Android 10 phone may accept a file that an Android 11+ phone rejects. If you suspect the files differ, compare their SHA-256.
Will re-signing with a new key fix it? It fixes the invalid-package error. If an older build signed with your original key is installed, the phone will then report a conflict instead. Sign with the original key.
Does the analyzer upload my APK? No. It runs in a Web Worker in your browser. The optional VirusTotal link sends only the hash, and only when you click it.
Next steps
- Check a build before you share it: APK & AAB analyzer, or the Play compliance checker for uploads
- Same package, different key: “App not installed as package conflicts with an existing package”
- targetSdk, ABI and minSdk failures: “App isn’t compatible with your phone”
- Convert an AAB and inspect every entry: AAB to APK and APK unpack
- Reference: apksigner, zipalign, bundletool, Android 11 behavior changes, REA’s DISCLAIMER.md