A Conservative Guide to ProGuard for Android

Android’s documentation for ProGuard describes it like so:-

“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…. Having ProGuard run is completely optional, but highly recommended.”

But this documentation for ProGuard is minimal in its recommendations, and ProGuard advice on Stack Overflow is inconsistent. Some developers find that ProGuard can introduce bugs when delivering push notifications, making in-app purchases, and using third-party libraries. This post is a conservative guide to ProGuard that minimizes the chance of these bugs by stressing safety over aggressive optimizations. When developing Burner for Android, this approach still led to ProGuard reducing the size of its. apk file by almost 25%, from ~1.7 MB to ~1.3 MB.

Basic configuration

First, open your project’s project.properties file and find the line specifying proguard.config. Append to it a colon as a delimiter, followed by proguard-appname.txt, substituting your own application name for appname. In its entirety the line should look like:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-appname.txt

So for Burner, it looks like:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-burner.txt

If no such line for proguard.config exists in your project.properties file, add one.

If you navigate to the directory {sdk.dir}/tools/proguard/, you’ll find that in addition to proguard-android.txt there is another file named proguard-android-optimize.txt. By using the former, your code will be shrunk and obfuscated. By using the latter, your code will also be optimized. But as Donald Knuth famously said, premature optimization is the root of all evil. The preamble to proguard-android-optimize.txt warns us so:

“Adding optimization introduces certain risks, since for example not all optimizations performed by ProGuard works on all versions of Dalvik. The following flags turn off various optimizations known to have issues, but the list may not be complete or up to date.”

We’re erring on the side of safety and referring to proguard-android.txt instead of proguard-android-optimize.txt. If your application is running slowly, it may be best to explore other space-time tradeoffs in your code before switching to proguard-android-optimize.txt. If using proguard-android-optimize.txtintroduces a bug on an esoteric or new version of Dalvik, that bug may be impossible or costly to fix.

Next, create that file proguard-appname.txt in your project. It should be a sibling of the project.properties file. Again, for Burner, this filename is proguard-burner.txt.

From the collective wisdom of Stack Overflow, I always begin this file with the following entries:

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.billing.IInAppBillingService
-keep public class * extends android.view.View {
    public (android.content.Context);
    public (android.content.Context, android.util.AttributeSet);
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
}

This excludes shrinking and obfuscating parts of classes that extend select classes from the Android API. The line including BroadcastReceiver is especially important if your application reacts to notifications, while the line including IInAppBillingService is especially important if your application offers in-app purchases. Again, some of these exclusionary rules could probably be removed, but we’re erring on the side of safety.

Third-party libraries

Many problems with ProGuard stem from the inclusion of third-party libraries in your project. For example, the following line of code from the greenDAO ORM throws a NoSuchFieldException because ProGuard obfuscates the field name TABLENAME:

this.tablename = (String) daoClass.getField("TABLENAME").get(null);

The first step in avoiding such errors is to consult the documentation of each third-party library and follow any instructions for deployment with ProGuard. For example, the Urban Airship documentation instructs adding the following lines to your configuration:

# Suppress warnings if you are NOT using IAP:
-dontwarn com.urbanairship.iap.**
# Required if you are using Autopilot
-keep public class * extends com.urbanairship.Autopilot

# Required if you ARE using IAP:
#-keep class com.android.vending.billing.**

# Required if you are using the airshipconfig.properties file
-keepclasseswithmembers public class * extends com.urbanairship.Options {
public *;
}

If the documentation mentions nothing about ProGuard, but the library is open source, then there is no point to obfuscating its code from a security standpoint anyway. Find the source code for the library, or temporarily rename the JAR file so that it has a .zip extension and extract its contents. Then find the ancestor packages for its code. For example, the ancestor package for all greenDAO ORM code is de.greenrobot.dao, which includes subpackages async, identityscope, internal, query, and test. With the following two lines in our ProGuard configuration, we exclude shrinking and obfuscating any code in package de.greenrobot.dao or a subpackage like de.greenrobot.dao.async:

-libraryjars libs

-keep class de.greenrobot.dao.** { *; }
-keep interface de.greenrobot.dao.** { *; }

In addition to the JAR file for greenDAO ORM, your libs folder may contain JAR files for third-party libraries like Joda Time and the Android Asynchronous Http Client. Your project may also depend on Android library projects like ActionBarSherlock and ViewPagerIndicator. Applying the approach above to each of these libraries, proguard-android.txt looks like:

-libraryjars libs

# The official support library.
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }

# Library JARs.
-keep class de.greenrobot.dao.** { *; }
-keep interface de.greenrobot.dao.** { *; }
-keep class org.joda.** { *; }
-keep interface org.joda.** { *; }
-keep class com.loopj.android.http.** { *; }
-keep interface com.loopj.android.http.** { *; }

# Library projects.
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
-keep class com.viewpagerindicator.** { *; }
-keep interface com.viewpagerindicator.** { *; }

This immediately follows the block of entries shown under Basic configuration. Change its content according to what libraries your project depends on.

Output

ProGuard runs when you build your application in release mode. After it has run, you should find a proguard directory in your project directory. The Android’s documentation for ProGuard contains complete information on the files it contains, but two are especially important:

  • seeds.txt contains classes and members excluded from obfuscation. Here you should find those belonging to the library packages that you explicitly excluded; if missing, then they were obfuscated and bugs may appear.
  • mapping.txt maps between the original and obfuscated class, method, and field names. If you are using a crash-reporting tool like Crittercism to automatically collect the stacktraces from crashes, then you will need this file to translate their obfuscated names back to their original names. Many crash-reporting tools will automatically perform this translation given this file; for example, see the Crittercism documentation. Because mapping.txt is so important to debugging, commit it to Git, add it to Dropbox, or copy it to a location that grants it longevity.

Further optimization:-

While this is a conservative guide to ProGuard, you can use it as a starting point for aggressive optimization with fewer exclusionary rules. Refer to its official documentation for more information.

A to Z in Android Developement

A to Z in Android Developement

How to Train your `droid`?

Hello droid!

If you are looking for a technical training kind of an article, you have come to the wrong place then :). I am writing this to share a few “things” about Android that I have experienced / heard, so that we can all have some fun time while our gradle builds are running or while we are sipping a cup of tea or maybe in the middle of a boring meeting.

WARNING!

Kindly read at your own risk. Don’t miss the Damage-control links!

Let’s begin! Shall we?

Afor Activity. Activity in android is one of the main components. Almost every application contains at least one Activity.

“Best way to prevent your Activity from getting restarted on orientation change is to set android`:configChanges` and just forgetting about it.”

Bfor Broadcast. Android is a chatty place, it’s components like to talk to one another and they can do so via broadcasts.

“Broadcast Receiver’s onReceive() is your stage. Go wild here and perform all the long running tasks.”

Cfor ContentProvider. ContentProvider provides us with an abstract layer and a way to share data among different applications.

“Creating a ContentProvider for your application is a MUSTfor you. You don’t seem to have a life anyway.”

Dfor Doze Mode. Android Devices can explode if they don’t doze off for a while. Android also takes a nap when you don’t play with it.

No-body cares about your Alarms, your Wake-locks, your sync jobs or even your app. Why should you?”

Efor Elevation. It is to show that a certain sheet of paper lies above the other paper. For instance, FABs lie above your screen and are elevated.

“Best way to have elevation in your apps is to just use setElevation() function and a get a super-ugly flat UI on pre-lollipop devices. Deal With It!”

Ffor Firebase. Firebase provides us with tools to create great apps. In 2016, the company was acquired by Google and that’s why I/O 2016 was filled by almost all Firebase stuff.

“Start by Realtime Database to cache all your data. Upgrade to FCM or your phone might not wake up once it dozes off. Firebase all the things!”

Gfor Gradle. Used to automate and manage the build process and produce your apk and aar‘s for you. Intention is to make your build process smooth.

“I love Gradle! It makes our life full of power-naps and TT.”

Hfor Handler. Handler is tied to a thread and is used to handle messages. It can be instantiated using the main Looper instance Looper.getMainLooper(). It is usually used to execute certain tasks on UI thread via messages coming from a background thread.

Animation not running? Keyboard not showing up? width/ height is 0? Do the magical handler.postDelayed() and you are good! Yeah go ahead and pat your back.

Well Done Source

Ifor Intent. Intent is the intention to perform a certain action. It can be Explicit (Direct — Authoritatively announce to perform an action like an extrovert) or Implicit (Indirect — First give a signal regarding your intention and perform an action when invited like an introvert).

“Feeling too Lazy to implement a feature? Throw an Intent and just let other apps handle it!”

Jfor Java. It’s an awesome programming language which is meant to WORA — Write Once, Run Anywhere . Java was developed by James Gosling of Sun Microsystems (acquired by Oracle). Android applications can be written using Java.

“Damn! WORA — Write Once Regret Always”

Kfor Kotlin. Kotlin is a statically typed, JVM based programming language. It is highly interoperable with JAVA and is a very attractive alternate to Java Developers who are sick of it’s verbosity (not me, I have an IDE).

“I once wrote an Application in Kotlin. Code | Convert Java File to Kotlin File.”

I would have definitely given it a try if it was named Korean though.

L-> {Lambda Expressions}. Less formal and more readable expressions.

“I like verbose.”

Mfor MVP. It stands for Model-View-Presenter. It is an architectural pattern to separate the logic from the presentation layer. More and more people are adopting this pattern for Android Development these days.

“Let’s make our lives a living hell and drown in the ocean of unlimited classes and interfaces.”

Source

Ofor OkJesse. Jesse Wilson, developer at Square told in one of the Fragmented Podcasts about the reason behind naming the libraries as OkHttp, OkIO. It’s because OK is a moment to rejoice for all of us :

“We, Developers live to get a 200 OK from the API. Always”

Pfor PendingIntent. It is an Intent that you give to another application to run. Pending Intent runs with our permissions in somebody else’s environment. Example: Alarms.

“Lazy to complete a task? Pass it to another application as a pending intent instead.”

Qfor Query. Your app has a database. You want to fetch some records. Guess what you need for that? No! you need to have some data in the database first and then you can query!

Select * from PJs WHERE name like ‘Q%’ ;

0 results found.

Rfor Rxify. Rxify is the term given by me to the use of Reactive programming and it’s operators. I believe that reactive programming can achieve difficult and error-prone tasks easily at the flick of a wrist.

“I love MAGIC! But with great POWER comes MissingBackpressureException”

Sfor Service. Service is one of the main components of Android. They do not have a UI of their own and are supposed to perform some tasks which do not involve much user interaction.

“Service runs in background, Go Ahead and do all your ugly stuff here and die in the hands of ANR.”

Tfor TDD. TDD stands for Test Driven Development. It’s the practice which says that we should first write all the test cases for anything we develop which all initially fail. We should then code to make them all pass.

“Let’s aim for 100% test coverage and make the client pay for it.”

Ufor URI. URI stands for Uniform Resource Identifier. It is like an address which points to some “thing” of significance.

“Even after ~ 4 years of Android Development I do not fully understand the concept of URI myself. You can safely skip this section.”

Vfor View. Basic component of any User Interface in Android. On the screen it takes up a rectangular area.

“Custom Views are so cool, let’s always draw our views ourselves.”

Wfor Wharton, Jake Wharton. He is the GeekGod of Android who works at Square. He has given us “things” like ButterKnife, Dagger, Retrofit, Timber, Hugo etc.

Applications respond to Chuck Wharton even in the case of ANR.”

Xfor xml. Extensible Markup Language is designed to be both machine and human (haha.. ya right!) readable. Using xml we can define a set of rules.

“Let’s use the cool new ConstraintLayout. It can be created using the Layout Editor, no need to work with stupid xmls anymore. … 4 hours later…. *creates a LinearLayout using xml*.”

Yfor Yoda, you are. After you have mastered at least the things mentioned above, you can safely call yourself a pro.

“After this rigorous training you have become the Master of Android Things.”

Master of Things Source

Zfor zzz. All work and no “Zzz” makes droid a dull “thing”.

“While you were reading this article, your device probably dozed off and your dear app won’t be able to do any damn thing about it!”

TL;DR

You missed all the good stuff. No issues, go back to stare at your “Gradle Build Running” dialog then 😛

This post was partially inspired by @anddev_badvice on Twitter and title from “How to Train your Dragon” movie which is pretty awesome!

I am myself a droid who is still learning. If you think I made a mistake anywhere, or you seek an explanation to the silly stuff in this post, leave a response. Click the heart if you want your fellow droids to chill a little too.

Credits:-https://medium.com/@ragdroid