As i need to reduce the size of APK file, I have followed Apk Expansion guide to divide APK in chunks.
The Downloader library defines ways to download the expansion file, but i need to know the way to exclude resource files and aar files from the apk.
I found following, but these are neither removing any resource-drawable files nor any arr files, and the size of apk remains same.
For testing purpose, i have added drawables of around 4 MB and couple of arr files of size 3 MB. I am creating apk from Build->Build APK option. I don't know if following will effect only on signed APK.
sourceSets {
main {
resources {
exclude '**/drawable/*'
}
}
}
android {
packagingOptions {
exclude 'lib/armeabi/a.so'
}
}
If there are specific resources you wish to keep or discard, create an XML file in your project with a <resources> tag and specify each resource to keep in the tools:keep attribute and each resource to discard in the tools:discard attribute. Both attributes accept a comma-separated list of resource names.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="#layout/l_used*_c,#layout/l_used_a,#layout/l_used_b*"
tools:discard="#layout/unused2" />
Save this file in your project resources, for example, at res/drawable/keep.xml. The build does not package this file into your APK. This way you can customize which resources to keep.
Expansion files may not contain any executable code. This is partly a Google Play policy, but also for security. Because they are written to a directory accessible to both your app and Play, and possibly to an SD card, if you put code their it would open your app to security exploits.
Because of this, you don't want to put AAR files in expansion files, as these normally have code. And many resources might not be appropriate, as these get compiled with your app and so have resource ids etc. Instead you should split out large elements that are not part of the explicit compile. Good candidates are things like:
Open GL textures
large sound files for sound effects
large level data or maps for games
large images
All of these could potentially be in the assets directory of your app and are prime candidates for expansion files.
If you have none of the above, if you are going over 100Mb in size it is likely that you are not Proguarding your code correctly, and including a lot of code your app doesn't use. If this is the case, then learning to use Proguard correctly is probably a bigger improvement than switching to expansion files. SO users may be able to advise you more if you can say where the size in your APK is going? How much on images? How much on executable code? Are you using Android Studio and java, native code, or a technology like Unity? All of these have slightly different approaches to APK size minimization.
There are 2 things that you can do.
Firstly, you can use Lint. Lint will help to highlight and remove all the resources that you are not using in your code including the drawables.
Second you can use Proguard. Using Proguard you can choose which version of APK you want to shrink including the debug(or main, as in your example) version. Just insert the following code.
android {
buildTypes {
debug {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
} }
Related
I have some library modules in my application and there are a lot of resources that are unused. But they did not remove in release build.
minifyEnabled has been set true in release buildType and also shrinkResources has set true in app module.
Note: Proguard worked correctly and remove all of the unused source codes.(including library module source codes).
P.S: I know that we can't use shrinkResources option in library modules and this shrinking is app module responsibility.
UPDATE1 : I read this thread's answers. Although I didn't use getIdentifier(), it hasn't effect.
UPDATE2: According to below quote, I checked R class in output apk and I found references(id) to unused resources. Why are they there?
Proguard works on the Java side. Unfortunately, it doesn’t work on the resources side. As a consequence, if an image my_image in res/drawable is not used, Proguard only strips it’s reference in the R class but keeps the associated image in place.
source
I checked shrinkResources option and it works somehow.
shrinkResources did not remove unused resources rather it clears file contents. For unused xml I saw an empty xml like this in the output apk:
<?xml version="1.0" encoding="utf-8"?>
<x />
I don't know the reason behind clearing content instead of deleting the file.
This approach is not optimal but is acceptable. An empty xml like the above one occupies 47 bytes.
I replaced some png images in my project and the app bundle did not build successfully as the png files were too large each 2-3mb. I then changed the images with some jpegs which were a few hundred kb in size per file. After that when I built the app the size of the app went from 9mb to 27 mb. I analyzed the apk and most of the size is due to some lib files
I deleted the build folder to remove any old files but it did not help.I excluded all .so files but the apk is not installing without them. I tried making a bundle but that is also the same size.
What should I do to revert back to the old apk size.
Read Add multi-density vector graphics
Android Studio includes a tool called Vector Asset Studio that helps
you add material icons and import Scalable Vector Graphic (SVG) and
Adobe Photoshop Document (PSD) files into your project as vector
drawable resources. Using vector drawables instead of bitmaps reduces
the size of your APK because the same file can be resized for
different screen densities without loss of image quality.
You should use SVG images instead of JPG/PNG.
To make your app as small as possible, you should enable shrinking in your release build to remove unused code and resources. When enabling shrinking, you also benefit from obfuscation, which shortens the names of your app’s classes and members, and optimization, which applies more aggressive strategies to further reduce the size of your app.
Read Shrink, obfuscate, and optimize your app
android {
buildTypes {
release {
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Enables resource shrinking, which is performed by the
// Android Gradle plugin.
shrinkResources true
// Includes the default ProGuard rules files that are packaged with
// the Android Gradle plugin. To learn more, go to the section about
// R8 configuration files.
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
I think images are not the issues from the dex files you have created I think you have included big libraries or many libraries?
Try to set minifyEnabled true to shrink resources in gradle file.
Use NDK abiFilters in your app module’s build.gradle like this:
android {
defaultConfig {
//...
ndk {
abiFilters "armeabi-v7a", "x86", "armeabi"
}
}
}
You can also exclude the specific *.so files that you don't want:
packagingOptions {
exclude 'lib/arm64-v8a/lib.so'
exclude 'lib/mips/lib.so'
}
I've got problem with very simple application. APK size is now 3 MB, but it contains a lot of useless for me files (I think that source of this files is Support Library). In my application I don't use any images, but all drawable directories contains a lot of icons, buttons, etc. Is it possible to delete this images by any rule in gradle or other method? I use Android Studio.
Already I added to build.gradle information about languages to include in APK. I had in Hello World 80 languages before it.
Screen of files:
The Gradle build system for Android supports "resource shrinking": the automatic removal of resources that are unused, at build time, in the packaged app. In addition to removing resources in your project that are not actually needed at runtime, this also removes resources from libraries you are depending on if they are not actually needed by your application.
To enable this add the line shrinkResources true in your gradle file.
android {
...
buildTypes {
release {
shrinkResources true
}
}
}
Check the official documentation here,
http://tools.android.com/tech-docs/new-build-system/resource-shrinking
I have one apk file but its file size is 22.4 MB. It's huge, so I need to reduce or compress the apk file in android. What is the right way to reduce and compress the apk file size?
You can compress an APK file (rar, zip), but it has to be decompressed in order to work.
If the apk file to large to distribute you can:
Use expansion files: http://developer.android.com/google/play/expansion-files.html
Create multiple versions of your apk: http://developer.android.com/google/play/publishing/multiple-apks.html (e.g. no hdpi files for ldpi devices)
Use ProGuard
ProGuard is a free Java class file shrinker, optimizer, obfuscator,
and preverifier. It detects and removes unused classes, fields,
methods, and attributes. It optimizes bytecode and removes unused
instructions. It renames the remaining classes, fields, and methods
using short meaningless names. Finally, it preverifies the processed
code for Java 6 or higher, or for Java Micro Edition.
If you use Eclipse, A default configuration file will automatically be added to your Project. But this default configuration only covers general cases, so you most likely have to edit it for your own needs.
Remove unused resources: https://code.google.com/p/android-unused-resources/
Optimize your images by using tools like 9patch and png optimizers
Remove everything that is only used for debugging purposes (debug classes, or even Log() methods). Also try removing unnecessary .so files
You can ZipAlign the signed apk to compress it.
Usage:
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
Example:
D:\android-sdk\android-sdk\tools>zipalign -f -v 4 "C:\Users\Joisar\Desktop\project_name\appname_signed.apk" "C:\Users\Joisar\Desktop\project_name\appname__zipaligned.apk"
Note:
Kindly checkout the apk whether it is zipaligned or not by following command, if it's not zipaligned, then do it.
zipalign -c -v 4 "C:\Users\Joisar\Desktop\project_name\appname_signed.apk"
Find the problem
You can Analyse APK from Android Studio. This shows you the various files in their directories and their sizes, both absolute and relative to the whole APK:
Check for Unused Resources
This is the easiest: shows you, among others, the unused resources:
Just remove them from your project.
Use Vector Images
Vector Drawables provide one sharp image for all resolutions, greatly reducing the size for your graphics. As usually, you can use these for icons etc, but not for Photos. Non-vectorized images can be reduced with trimage.
proguard minify
Add the following to app/build.gradle to enable proguard to reduce unused classes from your project:
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Use .svg format icon set.
Compress PNGs.
Use only specific libraries of Google Play Services.
Use Proguard
build.gradle
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Shrink Resources
build.gradle
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
...
}
}
}
I've migrated the AdMobs banner ads to Google Play Services in my Android Studio project. The resulting APK mushroomed from 0.7 MB to over 1.6 MB. Fortunately ProGuard knocked it down to just over 1 MB. I poked around the APK and noticed that 280 kB of "g+" images have been added to
res/
drawable-hdpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi
I have no plans to ever use Google+ in this app. It's a utility app and there's no need to deal with social media. 280kB may sound like peanuts compared to multi-Megabyte apps, but being a relatively simple utility, users want it to be as small as possible. It just feels dirty releasing a new version that blows up from ~700 kB to over 1000 kB with no tangible feature improvements for the user.
Ideally I'd like to exclude those icons for just one project, but I could live with a global solution for now.
If you are using Gradle you can use the shrinkResources option in combination with ProGuard to exclude resources. This deletes both your resources, as well as resources that your depndencies are using.
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
As of April 2015 there still seems to be a bug because of which some resources (including Google Play icons) would not get removed. You can work around this by creating a keep.xml file and specifying which resources should be removed. Remember to test your APK after that because removing resources that are actually needed might crash your app!
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:discard="#drawable/common_signin_*,#drawable/ic_plusone_*,#drawable/powered_by_google_*"/>
Removing these images reduces the size of the APK by about 300kB.
I had this error:
" ...\Application\build\intermediates\exploded-aar\com.google.android.gms\play-services-base\7.3.0\res\drawable-xxhdpi\common_signin_btn_icon_disabled_focus_light.9.png ERROR: Unable to open PNG file "
Android studio was unable to open the common_signin_btn_icon_disabled_focus_light.9.png file.
To solve this I moved the project folder directory up a level or two to reduce path length. Everything worked perfectly after that.
I used "D:\the_project_folder". Worked for me. No more compile errors.
thanks to this link:
https://github.com/googlesamples/android-XYZTouristAttractions/issues/2
Cheers!
So far the two best options are to add tiny bitmaps or aliases to the project named the same as the g+ icons. These supersede the icons in the GPS library. The icons are in each of the drawable-* directories with the following filenames:
res/
drawable-hdpi/
drawable-mdpi/
drawable-xhdpi/
drawable-xxhdpi/
common_signin_btn_icon_disabled_dark.9.png
common_signin_btn_icon_disabled_focus_dark.9.png
common_signin_btn_icon_disabled_focus_light.9.png
common_signin_btn_icon_disabled_light.9.png
common_signin_btn_icon_focus_dark.9.png
common_signin_btn_icon_focus_light.9.png
common_signin_btn_icon_normal_dark.9.png
common_signin_btn_icon_normal_light.9.png
common_signin_btn_icon_pressed_dark.9.png
common_signin_btn_icon_pressed_light.9.png
common_signin_btn_text_disabled_dark.9.png
common_signin_btn_text_disabled_focus_dark.9.png
common_signin_btn_text_disabled_focus_light.9.png
common_signin_btn_text_disabled_light.9.png
common_signin_btn_text_focus_dark.9.png
common_signin_btn_text_focus_light.9.png
common_signin_btn_text_normal_dark.9.png
common_signin_btn_text_normal_light.9.png
common_signin_btn_text_pressed_dark.9.png
common_signin_btn_text_pressed_light.9.png
ic_plusone_medium_off_client.png
ic_plusone_small_off_client.png
ic_plusone_standard_off_client.png
ic_plusone_tall_off_client.png
I created a tiny 9-patch bitmap copied and named as each of those files in the drawable dirs. You can barely see it here --->
The alternative is to create aliases. One bitmap alias per file so you end up with the same number of files. For example:
res/
drawable/
blank.png
drawable-xxhdpi/
common_signin_btn_icon_disabled_dark.9.xml
...
Each of the alias XMLs references the tiny one:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/blank" />
The size difference is negligible between the tiny bitmap and the alias. Yes it's a hack, but until Google/ProGuard automatically removes unused bitmaps, this may be the only way to recover the wasted space. Thanks to CommonsWare for the assist.
As a simpler alternative, just delete the .png files in drawable-xxhdpi, drawable-xhdpi and drawable-hdpi, leaving the ones in drawable-mdpi. Of course, check that the filename also exists in drawable-mdpi, first.
Leaving one valid resolution is safer IMHO and the drawable-mdpi files take up less than 30KB which may be acceptable for many people.