Reduce the size of an APK file

Asked

Viewed 5,295 times

9

It is possible to reduce the size of an APK file by changing the way it is compressed?

It is known that an APK file is just a ZIP file, signed and aligned. However, I performed some tests, and if the contents of an APK file is extracted, and then compressed again to a new ZIP file, its size decreases further.

But, if I rename that ZIP file back to APK, Google Play complains that the file is neither signed, nor aligned.

How to solve this?

*I know other techniques to reduce APK files, such as using Proguard to obfuscate and optimize the file, remove Ssets and duplicate resources, among others. The fact is if it is even possible to decrease the final size of the APK by changing its compression?

2 answers

7


Yes, it is possible to reduce the size of an APK file by just changing its compression.

It is possible to use any ZIP utility such as Winzip, Winrar, or 7-Zip. I used 7-Zip.

To execute these commands, I created a script. BAT, but here I will explain step-by-step the lines of the script (my APK file is C:\Android\Teste.apk).

First I make sure that the temporary folder used in the process is empty, in my case C:\Android\TempAPK:

if exist C:\Android\TempAPK (
del /S /Q C:\Android\TempAPK
rd /S /Q C:\Android\TempAPK
)
md C:\Android\TempAPK

Then, I extract the contents of the APK to this temporary folder:

"C:\Program Files\7-Zip\7z.exe" x C:\Android\Teste.apk -oC:\Android\TempAPK

Then delete the folder META-INF, together with its contents (I did not use the command deltree, because I couldn’t find it in Windows 8):

del C:\Android\TempAPK\META-INF /S /Q
rd C:\Android\TempAPK\META-INF

Then compress the files again to a file called Teste.zip using the method Deflate (that is OBLIGATORY), and with compression settings to the maximum:

cd C:\Android
"C:\Program Files\7-Zip\7z.exe" a -tzip C:\Android\Teste.zip .\TempAPK\* -mm=Deflate -mpass=15 -mfb=258

Now you need to sign this ZIP using the tool jarsigner, which comes with the JDK (in my case, it’s JDK 1.7.0_10):

cd "C:\Program Files\Java\jdk1.7.0_10\bin"
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore C:\Android\keystore\keystore.bin -storepass <SENHA DA KEYSTORE> -keypass <SENHA DA KEY> C:\Android\Teste.zip <ALIAS DA KEY>

Now just align the ZIP file using the tool zipalign, creating the final APK, and clearing all temporary files (note the SDK path):

cd C:\Android\sdk\build-tools\android-4.4W
del C:\Android\Teste.apk
zipalign 4 C:\Android\Teste.zip C:\Android\Teste.apk

del /S /Q C:\Android\TempAPK
rd /S /Q C:\Android\TempAPK
del C:\Android\Teste.zip

This reduced the size of my APK from 330kB to 274kB.

More about subscription, on the Google website:

Signing Your Applications

Building and Running from the Command Line

  • 1

    Carlos, this information is very good! As I usually build manually, I will try to port to Linux and put here if allowed. + 1

  • @Wakim for sure! I haven’t tried the script on Linux yet! It’ll be great!!! D

  • 2

    I managed to do the "port", can I post as a response? I had a 200kB gain in the process to generate a production apk. In a next build I will use this solution.

  • @Wakim Please, Wakim!!! Here will serve as a guide for the people who use Windows and Linux! o/

5

With the inspiration and excerpts of the Rafael, below follows my adaptation to the Linux platform.

Requirements:

  1. 7zip, to install: sudo apt-get install p7zip-full.
  2. unzip.
  3. jarsigner, located at JDK.
  4. zipalign, located in the folder build-tools/versao_do_buildtools/zipalign from the Android SDK.

The script is:

#!/bin/sh

# Interrompe o script ao primeiro erro
set -e

# Nome do keystore que ira usar no jarsigner
keystore_name=nome_do_keystore 

# Guardo o nome do usuario corrente
me=$(whoami)

# Variavel que guarda a localizacao do keystore, usado no jarsigner
keystore_location=/home/$me/.android/$keystore_name.jks

# Caminho para o diretorio onde esta o apk
apk_directory=caminho_para_o_seu_apk

# Caminho do apk com o nome
apk_location=$apk_directory/nome_do_seu_apk.apk

# Caminho para o apk final, pronto para producao
apk_location_aligned=$apk_directory/nome_do_seu_apk-release.apk

# Alias name usado na keystore
alias_name=seu_alias_name

echo 'Fazendo a descompressão do apk'

unzip "$apk_location" -d "$apk_directory/apk-uncompressed"

echo 'Apagando o META-INF'

rm -r -f "$apk_directory/apk-uncompressed/META-INF"

echo 'Apagando APK antigo'
rm -f "$apk_location"

echo 'Comprimindo novamente com maior eficiencia'
7z a -tzip "$apk_location" "$apk_directory/*" -mm=Deflate -mpass=15 -mfb=258

echo 'Apagando pasta temporaria'
rm -r -f "$apk_directory/apk-uncompressed"

echo 'iniciando jarsigner'
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore "$keystore_location" "$apk_location" "$alias_name"
echo 'jarsigner finalizado'

echo 'iniciando zipalign'
# Corrigir local para o zipalign conforme o necessario
/home/$me/android-studio/sdk/build-tools/20.0.0/zipalign -v 4 "$apk_location" "$apk_location_aligned"
echo 'zipalign finalizado'

It is necessary to make some adaptations according to the variables I left, some directories may vary according to the organization of the person and the Linux distribution (I used Ubuntu).

I performed this process on my apk, reduced the size of 986,5 kB for 787,0 kB, a gain of 199.5kb. Of course the reduction will vary from apk to apk, depending on the number of resources it uses (xml, png’s) and the libraries you use.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.