The adb install command pushes an APK file from your computer to an Android device and triggers the package installer, all without manually copying the file or navigating the phone's file manager. It supports standard APKs, split APKs, and several flags that control upgrade behavior, permissions, and installation targets.
With ADB set up and the device connected (or wirelessly paired), the minimum command to install an APK is:
adb install path/to/app.apk
On Windows, use backslashes or quote the path if it contains spaces:
adb install "C:\Users\YourName\Downloads\app-release.apk"
On macOS or Linux:
adb install ~/Downloads/app-release.apk
ADB streams the APK to the device's temporary storage, triggers the package manager, and reports the result. A successful install ends with:
Performing Streamed Install
Success
If you see INSTALL_FAILED_* instead, the section on error codes below explains the most common ones.
Before running adb install, the device must have Install unknown apps permission granted for ADB-sourced installs, or the older Unknown sources toggle must be on. On Android 8 and later, this is per-app: go to Settings > Apps > Special app access > Install unknown apps, find "Android Debug Bridge" or "Shell," and enable it. On Android 7 and earlier, a single toggle in Settings > Security > Unknown sources covers all sources.
The adb install command accepts several flags that change its behavior:
-r (replace / upgrade): Reinstall an app that is already installed, preserving its data. Without this flag, installing over an existing app fails with INSTALL_FAILED_ALREADY_EXISTS.
adb install -r app.apk
-d (downgrade): Allow installing an older version than the currently installed one. Normally the package manager rejects downgrades to prevent rollback attacks. This flag overrides the check. Use with caution — downgrading can leave a database schema in an inconsistent state if the app ran migrations on upgrade.
adb install -r -d older-version.apk
-g (grant all permissions): Automatically grant all runtime permissions declared in the APK's manifest at install time, without prompting the user. Useful for automated testing where you want the app to have full permissions immediately.
adb install -g app.apk
-t (allow test APKs): Required when installing APKs built with android:testOnly="true" in the manifest. Debug builds from Android Studio sometimes include this flag, causing install failures without -t.
adb install -t app-debug.apk
--user <USER_ID>: Install the app for a specific user profile on a multi-user device. User 0 is the primary/owner account. Additional users have IDs starting at 10 or 100 depending on the Android version.
adb install --user 0 app.apk
Modern apps distributed through the Play Store use App Bundles, which produce split APKs: a base APK plus additional APKs for specific screen densities, CPU architectures (ABI splits), and language resources. When you download an app from a source that provides the full split APK set, you need adb install-multiple rather than adb install.
adb install-multiple base.apk split_config.arm64_v8a.apk split_config.en.apk split_config.xxhdpi.apk
List all the APK files that belong to the install set on the same command line. The order matters only for the base APK, which must come first. ADB streams all of them to the device and the package manager installs them as a single atomic operation.
To determine which split APKs you need for your specific device, you can check the device's ABI and density:
adb shell getprop ro.product.cpu.abilist # e.g., arm64-v8a,armeabi-v7a
adb shell wm density # e.g., Physical density: 420
Select the split APK that matches the primary ABI (arm64-v8a, x86_64, etc.) and the closest density bucket (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi).
An alternative to adb install is to push the APK to the device first, then install it from within the ADB shell using the pm (package manager) command. This method is useful when the APK is already on the device's storage (for example, downloaded via the device's browser):
adb push app.apk /data/local/tmp/app.apk
adb shell pm install /data/local/tmp/app.apk
Clean up afterward:
adb shell rm /data/local/tmp/app.apk
The pm install command accepts the same flags as adb install (-r, -d, -g, etc.). This approach is slightly less convenient but useful when scripting multi-step operations that already involve ADB shell commands.
INSTALL_FAILED_ALREADY_EXISTS: The package is already installed. Add -r to replace it. If you want a clean install (wiping data), first run adb uninstall com.package.name, then install.
INSTALL_FAILED_UPDATE_INCOMPATIBLE: The APK's signing certificate does not match the certificate of the version already installed. This occurs when you try to install a debug build over a production build (or vice versa). Uninstall the existing version first: adb uninstall com.package.name.
INSTALL_FAILED_VERSION_DOWNGRADE: The version code of the new APK is lower than the installed version. Add -d to force the downgrade, or uninstall first.
INSTALL_FAILED_TEST_ONLY: The APK was built with android:testOnly="true". Add -t to allow it.
INSTALL_FAILED_INSUFFICIENT_STORAGE: Not enough free space on the device. Free storage and retry. This can also trigger on devices with very full /data partitions even when the user-visible storage shows free space, because app storage and media storage use different quotas on some Android versions.
INSTALL_PARSE_FAILED_NO_CERTIFICATES: The APK has not been signed, or its signature is invalid. Production APKs must be signed. Debug builds signed by Android Studio's debug keystore should not produce this error; if they do, rebuild and re-export the APK.
INSTALL_FAILED_USER_RESTRICTED: Device policy (MDM/enterprise policy, or parental controls) is blocking sideloading. This cannot be overridden by ADB flags; the policy must be changed through device management.
After a successful install, confirm the app is present with:
adb shell pm list packages | grep com.your.package
Replace com.your.package with the actual package name. A matching line confirms the package is registered. To launch the app immediately from ADB without tapping its icon:
adb shell monkey -p com.your.package -c android.intent.category.LAUNCHER 1
This sends a synthetic launcher intent to start the app's main activity. Useful for automated testing or for confirming the app launches without errors after installation.