---
title: Configuring ProGuard, an Easy Step-by-Step Tutorial | Guardsquare
description: ProGuard is a great way to reduce your code base significantly and see code changes instantly. See how this developer did it with DuckDuckGo.
image: https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/Configuring-ProGuard-an-easy-step-by-step-tutorial-2.png
---

[![guardsquare-logo](https://insights.guardsquare.com/hs-fs/hubfs/Logos/logo-white.png?length=536&name=logo-white.png "guardsquare-logo") ](https://23593082.hs-sites.com/)

- pricing

[Request Pricing](https://www.guardsquare.com/request-pricing?hsCtaTracking=646b0379-d596-4b1a-8526-2ccbdbb0f81b%7Ce8809087-a83f-4476-8b22-34b9572013fd)

[Login](https://customers.guardsquare.com/login?utm_referrer=https%3A%2F%2Fwww.guardsquare.com%2F)

En

- [中文](https://www.guardsquare.com/zh-hans)
- [한국어](https://www.guardsquare.com/ko)
- [Português](https://www.guardsquare.com/pt-br)
- [Español](https://www.guardsquare.com/es)

<https://twitter.com/intent/tweet?original_referer=https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial&url=https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial&source=tweetbutton> <http://www.linkedin.com/shareArticle?mini=true&url=https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial> <http://www.facebook.com/share.php?u=https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial> [mailto:?subject=Check%20out%20https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial](mailto:?subject=Check%20out%20https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial)

May 11, 2021

# Configuring ProGuard, an Easy Step-by-Step Tutorial

Written by: Laurent Ferier - DexGuard Team Lead

![](https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/Configuring-ProGuard-an-easy-step-by-step-tutorial-2.png)

I was recently asked to apply ProGuard on [DuckDuckGo](https://play.google.com/store/apps/details?id=com.duckduckgo.mobile.android), an open-source, privacy-enabled browser for Android. This lets me experiment with ProGuard on a big-enough application whose internals I wasn’t too familiar with - which was great. The application should also be big enough to be a challenge. And last, it should use reflection, because issues I would encounter with ProGuard are always about reflection. 

The main advantage of ProGuard is that it reduces the application size and optimizes performance. Configuring ProGuard can be initially daunting, but once you’ve mastered the underlying concepts and tools, it’s a straightforward affair. 

I’ll focus on two specific tools :

1. `-addconfigurationdebugging,`a runtime tool used to determine the rules you’ll require in your ProGuard configuration. 
2.   The new [ProGuard Playground](https://playground.proguard.com/) online tool, which lets you see the impact of a set of keep rules on the target application. This replaces long build and analyze cycles with immediate visualization.

In this post, I’ll show you how to apply ProGuard to an application step-by-step so you can apply it to your own projects. Let’s dive in!

## Step 1: Enable ProGuard in the Android project

Before any ProGuard setup, I need to make sure that everything is running correctly. I download the application sources, set up configuration files according to my development environment, and build the application. The resulting apk size is 13.5MB, and executing the application shows that it’s working correctly on-device. I’ll use this APK to help me configure ProGuard. 

To enable ProGuard, I first need to update the build.gradle configuration file. The [user’s guide](https://23593082.hs-sites.com/manual/quickstart) proposes the following configuration:

1. Disable R8 in `gradle.properties` file

```
android.enableR8=false
android.enableR8.libraries=false
```

2. I substitute the module with the latest ProGuard version (currently 7.0.1) in root `build.gradle:`

```
buildscript {
    ...
    configurations.all {
        resolutionStrategy {
            dependencySubstitution {
                substitute module('net.sf.proguard:proguard-gradle') 
                      with module('com.guardsquare:proguard-gradle:7.0.1')
            }
        }
    }
```

3. I then enable minification (shrinking) and set up the ProGuard configuration files:`minifyEnabled true`indicates that the code should be shrunk, whereas`shrinkResources true`tells me to remove all unused resources. The`proguard-project.txt` file shall hold my specific ProGuard configuration: 

```
android {
    ...
    buildTypes {
        release {
            minifyEnabled   true
            shrinkResources true
            proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
            proguardFile 'proguard-project.txt'
        }
    }
}
```

4. To make life easier during configuration, I enable verbose output by adding`-verbose`to my`proguard-project.txt`configuration file.

But when I try to build the application, it throws a`can’t find referenced class`error. Let’s look at how to solve that next.

### Dealing with `can’t find referenced class` ProGuard warnings

My first attempt at building the application resulted in many warning messages like this one: 

`Warning: okhttp3.internal.platform.BouncyCastlePlatform: can't find referenced class org.bouncycastle.jsse.BCSSLSocket`

The ProGuard documentation (see [https://www.guardsquare.com/manual/troubleshooting](https://23593082.hs-sites.com/manual/troubleshooting/troubleshooting)) provides the reason for this: 

*"A class in one of your program jars or library jars is referring to a class or interface that is missing from the input. The warning lists both the referencing class(es) and the missing referenced class(es)."*

It then documents the reasons why classes can be missing: 

1. If the missing class is referenced from your own code, you may have forgotten to specify an essential library.
2. If the missing class is referenced from a pre-compiled third-party library, and your original code runs fine without it, then the missing dependency doesn't seem to hurt. 
3. If you don't feel like filtering out the problematic classes, you can try your luck with the`-ignorewarnings`option, or even the`-dontwarn`option. 

The ProGuard user manual explains why the third solution is commonly necessary in the standard Android build process (see [https://www.guardsquare.com/manual/troubleshooting](https://23593082.hs-sites.com/en/products/proguard/manual/troubleshooting)). I could just ignore such warnings, by adding`-ignorewarnings`in proguard-rules.pro, but this is not recommended because future warnings will also be caught by this rule. So it is better to add precise`-dontwarn` rules in the ProGuard configuration instead.

Let’s look at the preceding warning message:

`Warning: okhttp3.internal.platform.BouncyCastlePlatform: can't find referenced class org.bouncycastle.jsse.BCSSLSocket`

It indicates that class`org.bouncycastle.jsse.BCSSLSocket` cannot be found which is used by`okhttp3.` By default, OkHttp uses the default platform security provider. Other security providers, such as`bouncycastle, Conscrypt` and`OpenJSSE`can be optionally used by OkHttp. ProGuard doesn't have this knowledge and will warn about this, so I have to explicitly tell it that these missing classes are fine (see the ProGuard user's manual about the`-dontwarn`option).

```
-dontwarn org.bouncycastle.**
-dontwarn org.conscrypt.**
-dontwarn org.openjsse.javax.net.ssl.**
-dontwarn org.openjsse.net.ssl.**
```

A similar problem occurs with`Flow`: `Warning: org.reactivestreams.FlowAdapters: can't find referenced class java.util.concurrent.Flow`

`Flow`was added in API 30, and `FlowAdapters`is a bridge between Reactive Streams API and the Java 9 API. Since the `compileSdkVersion`is 29, this class is not available and we need to inform ProGuard about this:

```
-dontwarn java.util.concurrent.**
```

I also add the following line in the configuration file because the application does not rely on such packages:

```
-dontwarn java.awt.geom.**
-dontwarn kotlin.time.**
```

When optimizing, ProGuard analyses the complete application, which is why it can detect such missing dependencies, which are in fact not used. 

The APK is now built successfully, but will it work on the first try? 

## Step 2: Run the ProGuard-processed application

My first try at running the application results in a`java.lang.IllegalStateException:`

```
exception when setting module id
java.lang.IllegalStateException: Unable to get current module info in ModuleManager created with non-module Context
```

and also a`java.lang.AssertionErrordue`to a`java.lang.NoSuchFieldException:`

```
java.lang.AssertionError: Missing field in com.duckduckgo.app.trackerdetection.c.a
[…]
caused by: java.lang.NoSuchFieldException: BLOCK
```

I expected such issues because ProGuard is altering the package, and in some cases, when code is accessed through reflection, ProGuard cannot always determine which code is actually used in those cases and might remove important code. I have to configure`-keep`directives to keep this code in the resulting APK. 

Similarly, ProGuard also renames fields, methods, classes, and packages. When these are accessed through reflection, there are cases where ProGuard cannot determine that they cannot be renamed. Consider for instance that the string used to access a field by reflection is dynamically built. We have then to manually indicate this to ProGuard using`-keep`configuration rules to preserve such items (see also [ProGuard configuration made easy](https://www.guardsquare.com/blog/proguard-configuration-made-easy)). 

### Letting ProGuard help me

Helpfully, ProGuard provides great tools to help me configure the required `-keep`rules : 

- The option`-addconfigurationdebugging`
- [The ProGuard Playground](https://playground.proguard.com/)

#### Option `-addconfigurationdebugging`

The option`-addconfigurationdebugging` (see [https://www.guardsquare.com/manual/configuration/usage](https://23593082.hs-sites.com/manual/configuration/usage)) specifies to instrument the processed code with debugging statements that print out suggestions for missing ProGuard configuration rules. This is very useful to get practical hints at run-time, for cases where the processed code crashed because it still lacked some configuration for reflection.

Setting up this option is straightforward. I merely add the following lines to my configuration file. 

```
# Now, it's time to let ProGuard help methods
# I will not leave this option in the release application
#   see https://www.guardsquare.com/en/blog/proguard-configuration-made-easy
-addconfigurationdebugging
```

I then rebuild the application, install it, and set it up to retrieve the logcat output using the following commands:

```
adb logcat -c
adb logcat > application.log
```

I only have to run the application on the device and it works like magic! Whenever a reference is made to a missing class, method, or field during execution, a dump is created with this kind of information: 

```
ProGuard: The class 'androidx.lifecycle.ClassesInfoCache' is calling Class.getDeclaredMethods
ProGuard: on class 'com.duckduckgo.app.global.DuckDuckGoApplication' to retrieve its methods.
ProGuard: You might consider preserving all methods with their original names,
ProGuard: with a setting like:
ProGuard:  
ProGuard: -keepclassmembers class com.duckduckgo.app.global.DuckDuckGoApplication {
ProGuard:     <methods>;
ProGuard: }
```

Testing the application with`-addconfigurationdebugging`enabled provides a list of`-keep`and`-keepclassmembers`rules which can be added in the configuration file. Of course, since initially the classes are not kept, the application does not behave like the original one and might crash on multiple occasions. We’ll need to iterate updating our keep rules several times to complete our runtime testing and configuration file

I apply this technique on the DuckDuckGo application which gives me the following list of`-keep`rules: 

Note that the rules proposed by`-addconfigurationdebugging`should not be added blindly in the configuration file because they need to be aggregated, and sometimes might not be correct. The ProGuard Playground is a great tool to help us with this. 

#### ProGuard Playground

[The ProGuard Playground](https://playground.proguard.com/) is a new tool that provides an easy way to visualize the impact of ProGuard rules on your application. It lets you interactively tweak the keep rules without having to rebuild the application. Without the Playground, this process would be performed by long build and analyze cycles, but the ProGuard playground lets you immediately see the impact of a configuration change on the embedded classes, methods, and fields in the target APK.

When I apply the`-keep`rules gathered during the first iteration, the ProGuard Playground shows that some of the`api`packages have an active`-keep`rule for the fields and methods, but some don’t. This seems inconsistent to me: it looks like all fields and methods should be kept for classes in any`api`package, and all constructors and fields should be kept for`model`packages. I replace all these rules with the following ones: 

Using the ProGuard playground, I maintain the quality of these new rules by removing specific`-keep`rules one at a time and making sure that the same set of classes, methods, and fields are kept.

### Further work toward a fully configured application

I build and run the application with this new ProGuard configuration, testing all application functionalities to make sure that debug suggestions have covered all code paths. ProGuard still suggests more`-keep`rules to add. 

#### Issue with constructors

The following configuration options keep appearing:

```
ProGuard: The class 'com.squareup.moshi.ClassFactory' is calling Class.getDeclaredConstructor
ProGuard: on class 'com.duckduckgo.app.autocomplete.api.AutoCompleteServiceRawResult' to retrieve
ProGuard: the constructor with signature (), but the latter could not be found.
ProGuard: It may have been obfuscated or shrunk.
ProGuard: You should consider preserving the constructor, with a setting like:
ProGuard:  
ProGuard: -keepclassmembers class com.duckduckgo.app.autocomplete.api.AutoCompleteServiceRawResult {
ProGuard:     public <init>();
ProGuard: }
ProGuard: 
```

Since I don’t know the DuckDuckGo application well enough, this error is not clear to me. But the ProGuard playground will efficiently show me the reason for this message. 

Again, using the original APK in the playground, I encode the corresponding keep rule,

```
-keepclassmembers class com.duckduckgo.app.autocomplete.api.AutoCompleteServiceRawResult {
     public <init>();
}
```

and find out that the`init()` method requires a string parameter - but the keep directive does not specify any. I update the `-keep` rule by considering any number of parameters: 

```
-keepclassmembers class com.duckduckgo.app.autocomplete.api.AutoCompleteServiceRawResult {
     public <init>(...);
}
```

The Proguard Playground shows that it will fix this issue. To make sure I keep all class constructors, I apply this solution for all constructors in both the`api` and`model`packages by updating the following rules: 

#### LifeCycle adapters

ProGuard also suggests keeping XXX_LifeCycle adapters:

```
02-10 14:20:04.733 28890 28890 W ProGuard: The class 'androidx.lifecycle.Lifecycling' is calling Class.forName to retrieve
02-10 14:20:04.733 28890 28890 W ProGuard: the class 'com.duckduckgo.app.global.DuckDuckGoApplication_LifecycleAdapter', but the latter could not be found.
02-10 14:20:04.733 28890 28890 W ProGuard: It may have been obfuscated or shrunk.
02-10 14:20:04.733 28890 28890 W ProGuard: You should consider preserving the class with its original name,
02-10 14:20:04.733 28890 28890 W ProGuard: with a setting like:
02-10 14:20:04.733 28890 28890 W ProGuard:  
02-10 14:20:04.733 28890 28890 W ProGuard: -keep class com.duckduckgo.app.global.DuckDuckGoApplication_LifecycleAdapter
02-10 14:20:04.733 28890 28890 W ProGuard:  
```

But adding the proposed keep rule does not help to avoid this, and this is where ProGuard Playground comes to the rescue. When I check the impact of such rules on the system, I’m surprised to see that these rules have no impact: nothing gets flagged as kept, but the class`DuckDuckGoApplication_LifecycleAdapter`is also nowhere to be found.

I understand this is part of the`androidx.lifecycle`, which checks for the existence of such classes and handles their absence. Since no such class is used in the application, this warning can be ignored.

#### New keep rules

During this iteration, ProGuard also indicates that I should add the following`-keep`rule:

```
-keepclassmembers class com.duckduckgo.app.browser.PulseAnimation { <methods>; }
```

#### Testing classes

Lastly, ProGuard also proposes the following keep rule: 

```
-keep class kotlinx.coroutines.test.internal.TestMainDispatcherFactory
```

But since I am not currently executing any unit test, it’s no wonder the class cannot be found. I don’t need to add such a rule in the configuration file. 

The resulting application is running correctly, and no more relevant warnings are emitted by`-addconfigurationdebugging.`

## Step 3: Getting production-ready

#### Remove `-addconfigurationdebugging.`

As mentioned in the User’s guide, and since I’ve finished setting up my configuration file, I remove the`-addconfigurationdebugging` flag from it. This flag should be used for configuration purposes only - it is no longer useful and would add obfuscation information to the processed code while also increasing the application size and slowing it down.

### The (final) configuration

The resulting ProGuard configuration is as follows:

### Results

The following table summarizes some metrics about the resulting application: 

|   | Initial | Optimized | Reduction Ratio |
| --- | --- | --- | --- |
| APK Size | 13 MB | 8.8 MB | 67% |
| - Resources | 4.5 MB | 4.4 MB | 97% |
| - Code | 5.7 MB | 1.8 MB | 31% |
| - Native libraries | ~1 MB | ~1 MB | 100% |
| Download size | 11.6 MB | 7.5 MB | 64% |
| Classes count | 13302 | 6690 | 50% |
| Methods count | 87162 | 30175 | 34% |

 

It’s clear that the size of resources (such as pictures, strings, etc.) is not reduced by the process, and still has a big impact on the overall package size. Note that you can use DexGuard instead to remove unused resources (see [https://www.guardsquare.com/dexguard](https://23593082.hs-sites.com/dexguard)). The size of native libraries is not impacted by the operation either. But ProGuard managed to drastically reduce the code size by a factor of 3, and the package size and download size have been reduced by one-third. Good job! :-)  

## Lessons learned

This post provides a practical example of applying Proguard to a real-life application. Most of the configuration needed during this process is related to creating a coherent set of `-keep` rules. To summarize:

- The configuration option`-addconfigurationdebugging`provides specific`-keep`rules related to the application, but this set of rules is still rough and needs to be adjusted.
- [The ProGuard Playground](https://playground.proguard.com/) is a great tool to interactively see the impact of the`-keep`rules on the target application without having to go through a long build process.
- ProGuard was able to shrink the code size by a factor of 3, which resulted in a one-third smaller package.

Tag(s): [Android](https://23593082.hs-sites.com/amilia-test/tag/android) , [Technical](https://23593082.hs-sites.com/amilia-test/tag/technical) , [Protection](https://23593082.hs-sites.com/amilia-test/tag/protection) , [ProGuard & R8](https://23593082.hs-sites.com/amilia-test/tag/proguard-r8)

## [Laurent Ferier - DexGuard Team Lead](https://23593082.hs-sites.com/amilia-test/author/laurent-ferier-dexguard-team-lead)

Connect with the author

## Discover how Guardsquare provides industry-leading protection for mobile apps.

## Other posts you might be interested in

[

** 11 min read  | August 22, 2023

## Webinar Recap: Accessibility Features and Overlays on Android

Android Protection Security Research 

](https://23593082.hs-sites.com/amilia-test/blog/app-permissions-abuse) [

** 7 min read  | August 15, 2023

## What is RASP and Why It Matters to Mobile App Developers

Android iOS Protection DexGuard iXGuard 

](https://23593082.hs-sites.com/amilia-test/blog/rasp-dynamic-analysis)

## Subscribe to our newsletter

Stay in the know with monthly updates right to your inbox.

![HubSpot CMS](https://cdn2.hubspot.net/hubfs/302335/hubspot-cms-logo-gray.svg "HubSpot CMS")

[General Terms](https://23593082.hs-sites.com/terms-of-use) | [Privacy Policy](https://23593082.hs-sites.com/privacy-policy) | [Cookie Policy](https://23593082.hs-sites.com/cookie-policy)

Tervuursevest 362 bus 1, 3000 Leuven, Belgium | VAT: BE0550675829 |

© 2016-2026 Guardsquare nv. All rights reserved.

<https://www.facebook.com/guardsquare> <https://twitter.com/Guardsquare> <https://www.linkedin.com/company/guardsquare/> <https://www.youtube.com/channel/UCP9s5F1ksT1E-7vSF2CDyhw> <https://github.com/Guardsquare>

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Laurent Ferier - DexGuard Team Lead",
    "url" : "https://23593082.hs-sites.com/amilia-test/author/laurent-ferier-dexguard-team-lead"
  },
  "dateModified" : "2023-09-19T17:51:03.662Z",
  "datePublished" : "2021-05-11T04:00:00.000Z",
  "headline" : "Configuring ProGuard, an Easy Step-by-Step Tutorial | Guardsquare",
  "image" : [ "https://23593082.hs-sites.com/hubfs/Imported_Blog_Media/Configuring-ProGuard-an-easy-step-by-step-tutorial-2.png" ],
  "mainEntityOfPage" : {
    "@id" : "https://23593082.hs-sites.com/amilia-test/blog/configuring-proguard-an-easy-step-by-step-tutorial",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject"
    }
  }
}
```