Have you developed an application in Android Studio and now you want to get it ready APK file for installation on a device or publication in Google Play? This process seems simple only at first glance. In practice, novice developers are faced with build errors, problems with signing, or misunderstanding which version of the APK to choose: debug for testing or release for distribution.
In this article we will analyze all the stages - from preparing the project to generating the final APK, including nuances with application signature, file size optimization and elimination of common errors. You will learn how to:
- ๐ง Collect
debug.apkin 2 clicks for quick testing - ๐ Generate signature key and protect it from loss
- ๐ฆ Compress APK using Android App Bundle (AAB)
- โ ๏ธ Fix type errors
Failed to read keyorMissing keystore
All instructions are valid for Android Studio Giraffe (2022.3.1) and newer, but the basic principles also work in older versions. If you use Flutter, React Native or other frameworks, the APK building process will be similar, but with slight differences in the settings.
1. Preparing the project before building the APK
Before generating the APK, make sure that the project is ready to build. Skipping this step often leads to errors like Build failed or Manifest merger failed.
Open your project in Android Studio and follow these steps:
- ๐ Check
build.gradle (Module: app):- Make sure that
minSdkVersionandtargetSdkVersionmeet the requirements of your application. - Example of correct configuration:
android {defaultConfig {
minSdkVersion 24
targetSdkVersion 34
versionCode 1
versionName "1.0"
}
}
- Make sure that
- ๐ Run linter (
Analyze โ Inspect Code) to find critical errors in the code. - ๐ฑ Connect a physical device or run emulator for preliminary testing.
โ ๏ธ Attention: If permissions are specified inAndroidManifest.xmlthat are not declared in the code, the build will fail mistake. For example,<uses-permission>) that are not declared in the code, the build will fail. For example,CAMERAorREAD_CONTACTSrequire an explicit request in runtime for Android 6.0+.
Also check that there is no duplicate resource files (for example, two res no duplicate resource files (for example, two ic_launcher.png with the same name, but in different folders drawable). This is a common cause of build errors.
โ๏ธ Check before building APK
2. Building the debug version of the APK (for testing)
Debug version of APK is an uncompressed and unsigned file that can only be installed on devices with USB debugging enabled (USB DebuggingIt is suitable for:
- ๐งช Testing functionality on a real device
- ๐ Finding bugs using Android Profiler
- ๐ Quick deployment of changes without signature
To assemble debug.apk, do:
- In the top menu, select
Build โ Build Bundle(s) / APK(s) โ Build APK. - Wait for the build to complete (a notification will appear at the bottom
APK(s) generated successfully). - Click
locatein the notification - the folder will openapp/build/outputs/apk/debug/where the file is locatedapp-debug.apk.
The finished APK can be immediately transferred to the device via USB or via ADB:
adb install app/build/outputs/apk/debug/app-debug.apk
โ ๏ธ Attention: The Debug version contains debugging information, which increases its size by 30-50% compared to the release. Do not distribute it outside the development team - this violates the rules. Google Play.
If the APK is not installed, check the section in the device settings Security โ Unknown sources and allow installation from your browser or file manager.
3. Generating a release version of an APK (for publication)
Release version of APK is an optimized and signed file that can be uploaded to Google Play, sent to testers or distributed via a website. Unlike debug, it is:
- ๐ Signed by yours key (keystore)
- ๐๏ธ Compressed and optimized (debug symbols removed)
- ๐ Ready for publication in stores
The release-APK generation process consists of two stages: creating a signature key (if it does not exist yet) and assembly with signature.
Step 1: Creating a signature key (keystore)
If you do not have a key yet, do:
- In Android Studio go to
Build โ Generate Signed Bundle or APK โ APK. - Click
Create new...and fill in the fields:- Key store path โ path to the file (for example,
C:\keys\my_app.keystore) - Password โ password for keystore (remember it!)
- Alias โ key name (for example,
release_key) - Password (for alias) โ password for the key (can be the same as the keystore password)
- Validity (years) โ validity period (recommended 25+ years)
- Key store path โ path to the file (for example,
Keep the keystore file in a safe place! Losing the key means that you will not be able to update the application on Google Play - you will have to publish it under a new package.
Step 2: Build a signed APK
After creating the key:
- In the same window, select the created keystore, enter passwords.
- Specify
Build Type: releaseandFlavor: main(if you do not use custom flavors). - Click
Finishand wait for the build to complete. - Use a keystore backup (if available).
- Create a new keystore and publish the application as new (with another
package name). - ๐๏ธ Removes unused code (tree shaking)
- ๐ค Shortens class and method names (obfuscation)
- โก Optimizes bytecode
- ๐ผ๏ธ Compress images using TinyPNG or WebP-format.
- ๐ฆ Use
android:extractNativeLibs="false"inAndroidManifest.xmlif your application does not contain native libraries. - ๐๏ธ Remove unnecessary dependencies in
build.gradle(check with./gradlew :app:dependencies).
The finished file will be in the folder app/release/ with the name app-release.apk.
What to do if you forgot your keystore password?
Unfortunately, it is impossible to recover your keystore password. data-i="151">Use a backup copy of the keystore (if there is one).
Google Play does not allow updating applications with a new key!
| APK type | Signature | Optimization | Size | Purpose |
|---|---|---|---|---|
debug.apk |
Automatic (Android Studio) | No | Large (+30โ50%) | Testing |
release.apk |
Manual (your keystore) | Yes (ProGuard/R8) | Minimal | Publishing |
app-bundle.aab |
Manual | Yes (dynamic delivery) | Even less | Google Play |
4. APK optimization: ProGuard and size reduction
The Release version of APK by default is optimized through R8 (ProGuard's successor), which:
To configure R8, open proguard-rules.pro in the module folder and add rules. For example, to save annotations Retrofit:
-keepattributes Annotation-keepclassmembers class * {
@retrofit2.http.* <methods>;
}
To further reduce the size:
โ ๏ธ Attention: If after enabling R8 the application stops working, check the build logs for type warningsNote: the configuration refers to the unknown class. This means that R8 has removed the required class - add it to the saving rules (-keep).
Using Android App Bundle (AAB) instead of APK can reduce the size of the downloaded file by 15-30% due to dynamic delivery of resources. Google Play recommends AAB as the main publishing format.
5. Typical errors when building APKs and their solutions
Even experienced developers encounter build errors. Here are the most common ones and how to fix them:
| Error | Cause | Solution |
|---|---|---|
Failed to read key from keystore |
Wrong password or path to keystore | Check passwords in build.gradle or generate the keystore again |
Manifest merger failed |
Permission or attribute conflict in AndroidManifest.xml |
Use tools:replace or tools:node="merge" |
Duplicate class found |
Duplicate dependencies in build.gradle |
Add implementation('com.example:lib:1.0') { exclude group: 'com.conflict' } |
Execution failed for task ':app:processReleaseResources' |
Damaged resources or invalid paths | Clean the project (Build โ Clean Project) and rebuild |
If the error persists, try:
- Update Android Studio and Gradle to the latest versions.
- Clear cache:
File โ Invalidate Caches / Restart. - Check the build logs in the window
Build Output(at the bottom Android Studio).
For errors related to Java or Kotlinit is useful to run the build with the flag --stacktrace:
./gradlew assembleRelease --stacktrace
This will show the full call stack and make diagnosis easier.
6. Alternative ways to obtain the APK
In addition to the standard build in Android Studio, there are other methods for generating APK:
- ๐ง Via the command line:
Use Gradle commands in the terminal:
# Build debug-APK./gradlew assembleDebug
Building release-APK (keystore required)
./gradlew assembleRelease - ๐ฆ From Android App Bundle (AAB):
If you have a
.aabfile, generate the APK using bundletool:java -jar bundletool.jar build-apks --bundle=app.aab --output=app.apksjava -jar bundletool.jar install-apks --apks=app.apks - ๐ From the installed application:
You can extract the APK from the connected device via ADB:
adb shell pm list packages -f | grep 'your package'adb pull /data/app/your.pack-1/base.apkโ ๏ธ Attention: The extracted APK may be damaged or may not contain all the resources. This method is only suitable for analysis, but not for distribution.
To automate the assembly, you can use CI/CDservices like GitHub Actions or Bitrise. They allow you to generate an APK with each commit to the repository.
If you need to quickly share an APK with testers, use services like AppCenter or Firebase App Distribution. They automate the distribution and collection of reviews.
7. Checking the APK before publishing
Before uploading the APK to Google Play or distributing through other channels, check:
- ๐ Testing on different devices:
Make sure that the application works on Android 5.0โ14.0, different architectures (
armeabi-v7a,arm64-v8a,x86) and screens. - ๐ก๏ธ Security check:
Use Google Play App Signing for additional key protection. Upload the APK to Play Console and wait for the check for malicious code.
- ๐ Compliance with Google Play requirements:
- APK must weigh no more than 150 MB (otherwise you need Android App Bundle).
targetSdkVersionmust be at least 31 (for new applications).- The application must support 64-bit architectures (since 2019).
To analyze APK, use the following tools:
- APK Analyzer (built into Android Studio): shows the file structure and resource sizes.
- aapt (Android Asset Packaging Tool):
aapt dump badging your_file.apkWill display information about the version, permissions and components.
โ ๏ธ Attention: If your application uses native libraries (for example, through NDK), make sure that the APK includes all necessary .sofiles for supported architectures. Their absence will lead to a crash on some devices.
FAQ: Frequently asked questions about APK assembly
Can I install a release-APK without a signature?
No. The release version must be signed by your keystore. Without a signature, it cannot be installed on any device, except through ADB with the flag -r (but this is a temporary solution for debugging).
How to reduce the size of APK for Google Play?
Use Android App Bundle (.aab) instead of APK - it automatically generates optimized APKs for each device. Also:
- Remove unnecessary resources (for example, translations into unused languages).
- Compress images into WebP-format.
- Enable
shrinkResources trueiminifyEnabled truevbuild.gradle.
What to do if Google Play refuses publication due to targetSdkVersion?
From August 2023, new applications must have targetSdkVersion 33 or higher. Update this line in build.gradle and test the application for compatibility with the latest changes in Android (for example, new permissions for notifications).
Is it possible to decompile the APK and get the source code?
Technically yes, using tools like JADX or Apktool. However:
- The code will be obfuscated (names of classes and methods are replaced with random ones).
- It is almost impossible to restore the original logic.
- Distribution of decompiled code violates license agreements.
How to automate the APK build on every commit?
Set up CI/CDpipeline. Example for GitHub Actions:
name: Build APKon: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
- run: ./gradlew assembleRelease
- uses: actions/upload-artifact@v3
with:
name: app-release.apk
path: app/build/outputs/apk/release/app-release.apk
This will collect the release-APK with each push to the repository.