Getting Started with ProGuard

In this Android tutorial, you’ll learn how to strip down your app size by making use of ProGuard – an app shrinking and obfuscation tool. By Kolin Stürt.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Adding BubblePicker Code

In the res/layout/activity_main.xml file, replace the second TextView (descriptionTextView) with the following:

<com.igalata.bubblepicker.rendering.BubblePicker
  android:id="@+id/picker"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:backgroundColor="@android:color/white" />

This adds the BubblePicker to the main layout. In the MainActivity.kt file, add the following to the setupBubblePicker() method:

picker.bubbleSize = 50
picker.centerImmediately = true
picker.adapter = object : BubblePickerAdapter {

  val colors = resources.obtainTypedArray(R.array.colors)
  val titles = listOf("1", "2", "3", "4", "5", "6")

  val multiplier = 2
  val modulus = 8
  val addition = 1

  override val totalCount = titles.size // 1

  override fun getItem(position: Int): PickerItem { // 2
    return PickerItem().apply {
      title = titles[position]

      val start = colors.getColor((position * multiplier) % modulus,0)
      val end = colors.getColor((position * multiplier) % modulus + addition,0)
      gradient = BubbleGradient(start, end, BubbleGradient.VERTICAL)

      textColor = ContextCompat.getColor(this@MainActivity, android.R.color.white)
    }
  }

}

picker.listener = object : BubblePickerListener { // 3

  override fun onBubbleSelected(item: PickerItem) {

  }

  override fun onBubbleDeselected(item: PickerItem) {

  }

}

Note: This tutorial assumes you’re familiar with handling imports. If you don’t have on-the-fly imports set up, import by pressing option + return on a Mac or Alt + Enter on a PC while your cursor is over the item that needs to be imported.

Note: This tutorial assumes you’re familiar with handling imports. If you don’t have on-the-fly imports set up, import by pressing option + return on a Mac or Alt + Enter on a PC while your cursor is over the item that needs to be imported.

Here’s what’s going on in the updated method:

  1. You are overriding totalCount to tell the BubblePicker how many bubbles there will be.
  2. You’re overriding getItem() to return a customized PickerItem.
  3. You set up the BubblePickerListener to handle selecting a bubble.

Finish off the implementation by adding this to the end of onResume:

picker.onResume()

Add this to the end of onPause:

picker.onPause()

Build and run the app. Uh oh — the app crashes with a NullPointerException! Note that several methods in your stack trace are obfuscated – the names are changed and minified. This is one of the key features of ProGuard.
Crash error message
Sad face
Check the output log to narrow down what the problem is. You can see in the Run tab that it has something to do with “GL” and “onDrawFrame” in the BubblePicker library.

Note: It’s always good practice to add sufficient logging in your catch statements, nullability checks and error states. With ProGuard, this is crucial – in the event of a problem, it will help lead you or other developers to the root of the issue, especially when the method names in stack traces are obfuscated.

Note: It’s always good practice to add sufficient logging in your catch statements, nullability checks and error states. With ProGuard, this is crucial – in the event of a problem, it will help lead you or other developers to the root of the issue, especially when the method names in stack traces are obfuscated.

Debugging with ProGuard Output Files

When ProGuard finishes running, it produces 4 output files. They are:

  • usage.txt – Lists code that ProGuard removed.
  • dump.txt – Describes the structure of the class files in your APK.
  • seeds.txt – Lists the classes and members that were not obfuscated. Good to verify that you have obfuscated your important files.
  • mapping.txt – The file that maps the obfuscated names back to the original.

You can use the mapping file to find the culprit of the crash.

Run the APK Analyzer again, then select the classes.dex file. Your crash points to obfuscated code looking something like org.a.d.l.a. The single characters you see may vary from this example but you can follow the directory path of the characters:
Proguarded directories
At first, it’s not clear what the directories are. Click the Load Proguard mappings… button to map the obfuscated names back to the original.
Load Proguard mappings button
Select the mapping.txt file in the debug folder and click OK.

Toggle the Deobfuscate names button to the left of the Change ProGuard mappings… button to switch between obfuscated and deobfuscated code. You can trace the problem down to the jbox2d library.
Unobfuscated code
You need to preserve jbox2d so that ProGuard doesn’t muck with it.

There are a few more things you should know about the mappings file:

  • Every time you make a release build, the mapping.txt file is rewritten. That means you must save each copy with each release of your app. That way, when you receive an obfuscated stack trace for a particular app release, it will be useful.
  • You can upload your mapping.txt file to Google Play to deobfuscate your crash stack traces.
  • If you’re using Fabric, a deployment and crash reporting tool from Google, instructions for uploading your mapping.txt file are here.

Adding Keep Rules

Keep rules tell ProGuard not to obfuscate certain parts of your code. Some options are:

  • keep – Preserve entire class and class members.
  • keepclassmembers – Preserve the class members.
  • keepclasseswithmembers – Preserve all classes that have a specified member.

ProGuard rules are written in a specific template format. It’s best practice to use explicit keep rules, rather than keeping the entire class. Instead of preserving the entire BubblePicker library, you only need to keep org.jbox2d and its sub-packages. The format is the same as the dontwarn rules.

Add the following to the proguard-rules.pro file right after the dontwarn rules you added:

-keep class org.jbox2d.** { *; }

Inside the curly braces, you told ProGuard to match any method name.

Build and run the app. When your app loads up, you should see the bubbles floating around on the screen.

App with bubbles

Note: If you’re sharing your code, write keep rules as you write your code and be sure to publish them on your site or GitHub README page so other developers can easily use your code without any problems.

Note: If you’re sharing your code, write keep rules as you write your code and be sure to publish them on your site or GitHub README page so other developers can easily use your code without any problems.

Now you’ll set up some real sloth data.