The ProGuard tool shrinks, optimizes, and
obfuscates your code by removing unused code and
renaming classes, fields, and methods with semantically obscure names. The result is a smaller
sized .apk
file that is more difficult to reverse engineer. Because ProGuard makes your
application harder to reverse engineer, it is important that you use it
when your application utilizes features that are sensitive to security like when you are
Licensing Your Applications.
ProGuard is integrated into the Android build system, so you do not have to invoke it manually. ProGuard runs only when you build your application in release mode, so you do not have to deal with obfuscated code when you build your application in debug mode. Having ProGuard run is completely optional, but highly recommended.
This document describes how to enable and configure ProGuard as well as use the
retrace
tool to decode obfuscated stack traces.
Enabling ProGuard (Gradle Builds)
When you create a project in Android Studio or with the Gradle build system, the
minifyEnabled
property in the build.gradle
file enables and disables
ProGuard for release builds. The minifyEnabled
property is part of the
buildTypes
release
block that controls the settings applied to
release builds. Set the minifyEnabled
property to true
to enable
ProGuard, as shown in this example.
android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
The getDefaultProguardFile('proguard-android.txt')
method obtains the default
ProGuard settings from the Android SDK tools/proguard/
folder. The
proguard-android-optimize.txt
file is also available in this Android SDK
folder with the same rules but with optimizations enabled. ProGuard optimizations perform
analysis at the bytecode level, inside and across methods to help make your app smaller and run
faster. Android Studio adds the proguard-rules.pro
file at the root of the module,
so you can also easily add custom ProGuard rules specific to the current module.
You can also add ProGuard files to the getDefaultProguardFile
directive for all release builds or as part of the productFlavor
settings in the
build.gradle
file to customize the settings applied to build variants. This example
adds the proguard-rules-new.pro
to the proguardFiles
directive and the other-rules.pro
file to the flavor2
product flavor.
android { ... buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'proguard-rules-new.pro' } } productFlavors { flavor1 { } flavor2 { proguardFile 'other-rules.pro' } } }
Enabling ProGuard (Ant Builds)
When you create an Android project, a proguard.cfg
file is automatically
generated in the root directory of the project. This file defines how ProGuard optimizes and
obfuscates your code, so it is very important that you understand how to customize it for your
needs. The default configuration file only covers general cases, so you most likely have to edit
it for your own needs. See the following section about Configuring
ProGuard for information on customizing the ProGuard configuration file.
To enable ProGuard so that it runs as part of an Ant or Eclipse build, set the
proguard.config
property in the <project_root>/project.properties
file. The path can be an absolute path or a path relative to the project's root.
If you left the proguard.cfg
file in its default location (the project's root
directory), you can specify its location like this:
proguard.config=proguard.cfg
You can also move the the file to anywhere you want, and specify the absolute path to it:
proguard.config=/path/to/proguard.cfg
When you build your application in release mode, either by running ant release
or
by using the Export Wizard in Eclipse, the build system automatically checks to see if
the proguard.config
property is set. If it is, ProGuard automatically processes
the application's bytecode before packaging everything into an .apk
file. Building in debug mode
does not invoke ProGuard, because it makes debugging more cumbersome.
ProGuard outputs the following files after it runs:
dump.txt
- Describes the internal structure of all the class files in the
.apk
file mapping.txt
- Lists the mapping between the original and obfuscated class, method, and field names. This file is important when you receive a bug report from a release build, because it translates the obfuscated stack trace back to the original class, method, and member names. See Decoding Obfuscated Stack Traces for more information.
seeds.txt
- Lists the classes and members that are not obfuscated
usage.txt
- Lists the code that was stripped from the
.apk
<project_root>/bin/proguard
if you are using Ant.<project_root>/proguard
if you are using Eclipse.- a class that is referenced only in the
AndroidManifest.xml
file - a method called from JNI
- dynamically referenced fields and methods
These files are located in the following directories:
Caution: Every time you run a build in release mode, these files are overwritten with the latest files generated by ProGuard. Save a copy of them each time you release your application in order to de-obfuscate bug reports from your release builds. For more information on why saving these files is important, see Debugging considerations for published applications.
Configuring ProGuard
For some situations, the default configurations in the ProGuard configuration file will suffice. However, many situations are hard for ProGuard to analyze correctly and it might remove code that it thinks is not used, but your application actually needs. Some examples include:
The default ProGuard configuration file tries to cover general cases, but you might
encounter exceptions such as ClassNotFoundException
, which happens when ProGuard
strips away an entire class that your application calls.
You can fix errors when ProGuard strips away your code by adding a -keep
line in
the ProGuard configuration file. For example:
-keep public class <MyClass>
There are many options and considerations when using the -keep
option, so it is
highly recommended that you read the
ProGuard
Manual for more information about customizing your configuration file. The
Overview of Keep options and Examples sections are particularly helpful.
The Troubleshooting
section of the ProGuard Manual outlines other common problems you might encounter
when your code gets stripped away.
Decoding Obfuscated Stack Traces
When your obfuscated code outputs a stack trace, the method names are obfuscated, which makes
debugging hard, if not impossible. Fortunately, whenever ProGuard runs, it outputs a
mapping.txt
file, which shows you the original class, method, and field names
mapped to their obfuscated names.
The retrace.bat
script on Windows or the retrace.sh
script on Linux
or Mac OS X can convert an obfuscated stack trace to a readable one. It is located
in the <sdk_root>/tools/proguard/
directory. The syntax for executing the
retrace
tool is:
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
For example:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
If you do not specify a value for <stacktrace_file>, the retrace
tool reads
from standard input.
Debugging considerations for published applications
Save the mapping.txt
file for every release that you publish to your users.
By retaining a copy of the mapping.txt
file for each release build,
you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace.
A project's mapping.txt
file is overwritten every time you do a release build, so you must be
careful about saving the versions that you need. For Eclipse, this file is stored in
<project_root>/bin/proguard/
. For Android Studio, this file is stored in
the app build/outs/
folder.
For example, say you publish an application and continue developing new features of
the application for a new version. You then do a release build using ProGuard soon after. The
build overwrites the previous mapping.txt
file. A user submits a bug report
containing a stack trace from the application that is currently published. You no longer have a way
of debugging the user's stack trace, because the mapping.txt
file associated with the version
on the user's device is gone. There are other situations where your mapping.txt
file can be overwritten, so
ensure that you save a copy for every release that you anticipate you have to debug.
How you save the mapping.txt
files is your decision. For example, you can rename
the files to include a version or build number, or you can version control them along with your
source code.