Minify android app but do not obfuscate it - android

When I do not minify my app I reach the maximum method count and building the dex file fails. This can be avoided by enabling minify in build.gradle. The downside, however, is that now the code gets obfuscated. This is OK for the Release build but it is problematic for a Debug build.
Is there a way to tell gradle to minify a Debug build but not obfuscate it?

minifyEnabled true
is just a shortcut for:
postprocessing {
removeUnusedCode true
obfuscate true
optimizeCode true
}
So, if you want to minify without obfuscating, replace minifyEnabled true with:
postprocessing {
removeUnusedCode true
obfuscate false // <--
optimizeCode true
}
Additionally, the compiler will complain if you have shrinkResources true. The equivalent postprocessing field is removeUnusedResources true, i.e:
postprocessing {
removeUnusedCode true
removeUnusedResources true // <--
obfuscate false
optimizeCode true
}
Contrary to other answers, useProguard false does not disable obfuscation; it changes the obfuscation engine from ProGuard to R8.

Yes, you can use ProGuard to minify debug builds.
The key is to use -dontobfuscate option in ProGuard configuration for debug build.
Use this setting in build.gradle:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro',
'proguard-rules-debug.pro'
}
}
Write your release ProGuard configuration to proguard-rules.pro.
Use the same configuration for release and debug. This way you ensure that no necessary code is stripped away. And debug minification doesn't break the build.
Add extra ProGuard config file proguard-rules-debug.pro for debug build. It should contain rules used only for debug. In this case add only:
-dontobfuscate

Tomik's answer is technically correct, but it doesn't support using Instant Run for your builds. As pointed out in the official guide on code-shrinking:
Enable code shrinking with Instant Run If code shrinking is important
to you while incrementally building your app, try the experimental
code shrinker that's built into the Android plugin for Gradle. This
shrinker supports Instant Run, unlike ProGuard.
You can configure the Android plugin shrinker using the same
configuration files as ProGuard. However, the Android plugin shrinker
does not obfuscate or optimize your codeā€”it only removes unused code.
So you should use it for your debug builds only, and enable ProGuard
for your release builds so your release APK's code is obfuscated and
optimized.
So the proper solution would be to setup your debug build like this:
android {
buildTypes {
debug {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
This way the code in your debug build doesn't get optimized nor obfuscated, but will get shrunk. This also applies when using Instant Run.

A simple solution is to add minifyEnabled true and useProguard false inside the build configuration. But code shrinking is not recommended for debug builds from official docs Be aware that code shrinking slows down the build time, so you should avoid using it on your debug build if possible.
Reference https://developer.android.com/studio/build/shrink-code.html

Related

Why is minifyEnabled is false in release builds by default?

In build.gradle (app) file we have this by default,
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
According to https://developer.android.com/studio/build/shrink-code,
minifyEnabled true make the code more secure (making it hard to reverse engineer) and also shrink the size in release build, which we use for publishing the app.
I know that using minifyEnabled true makes compile time longer, but usually debug builds are used for development and testing, which is not affected anyways.
What I'm looking for is that, what are the disadvantages (such as performance impacts) cause by using minifyEnabled true at runtime. I'm not worried about the build time of a release build.
Google Play Console also recommending us to enable it therefore I'm wondering why is minifyEnabled is disabled by default.
By adding minifyEnabled true in your release build you can obfuscate code but it is set to false by default in release builds because if set true it shall require proguard rules to be written to tell the compiler which classes are to be ignored while obfuscating the code. If minifyEnabled is set to true by default and the developer forgets to add proguard rules, it can lead to runtime crashes.
However, setting minifyEnabled to true and shrinkResources to true can reduce your apk size.
As NIKHIL AGGARWAL said, setting minifyEnabled to true can lead to runtime crashes.
You should research each used library so that include their ProGuard rules into your project. Also sometimes after Gradle or libraries upgrade you should again check ProGuard rules and accordingly update them in your project.
You should add data classes of your network model to ProGuard.
You should check your release build on several devices/emulators with different Android versions to understand where it can crash. Debugging in release build is difficult and with obfuscation it becomes a nightmare.
However after you set minifyEnabled = true and avoid crashes you will decrease apk size and impede to cracking attempts.

proguard-android-optimize.txt vs proguard-android.txt in Android build.gradle

I was reading the docs about shrinking, obfuscating and optimising for a release build using build.gradle for an Android app. In one section of the docs, proguard-android.txt is used as the defauly ProGuard file:
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
and in another section, proguard-android-optimize.txt is used:
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
There doesn't seem to be an explanation of what the difference between these are, and I can't find any information. Can someone explain what the differences are and when you would use proguard-android-optimize.txt vs proguard-android.txt?
Thanks :)
Take a look at the Android source code over here.
Optimizations: If you don't want to optimize, use the
proguard-android.txt configuration file instead of this one, which
turns off the optimization flags. 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. (The "arithmetic" optimization can be
used if you are only targeting Android 2.0 or later.) Make sure you
test thoroughly if you go this route.
Also, this answer is a pretty good read as well.

How can I build an .aar library with shrunk classes in Android Studio?

I want to build an .aar library and proguard classes, but my library proguard file doesn't work, and I can see clear classes.
Here is my proguard file:
android {
buildTypes {
release {
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules-my-lib.pro'
}
}
}
and app/build.gradle:
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
While you can probably shrink and obfuscate the library itself, the usual practice is to leave minifyEnabled as false and provide the proguard configuration to the application, using consumerProguardFiles instead of proguardFiles.
This means that the minification is applied only once, on the whole application, using the merged configuration from the app's proguardFiles and the libraries consumerProguardFiles. This is usually more efficient because parts of the libraries not actually used by the application can be removed.
Create a Android Studio Project and convert it to library Follow this link. Build and Execute the command Generate APK, .aar file will be created in release/debug folder.
Write the proguard rules as similar to APK, it will apply to .aar file also.
I hope this helps

What's the difference between "minifyEnabled" and "useProguard" in the Android Plugin for Gradle?

I see that the Android Plugin for Gradle has a minifyEnabled property as well as a useProguard property, as follows:
android {
buildTypes {
debug {
minifyEnabled true
useProguard false
}
release {
minifyEnabled true
useProguard true
}
}
}
What's the difference between these two properties? Or, rather, what's the meaning of each?
Quoting from tools.android.com:
Built-in shrinker
Version 2.0 of Android Plugin for Gradle ships with an experimental
built-in code shrinker, which can be used instead of ProGuard. The
built-in shrinker supports fast incremental runs and is meant to speed
up iteration cycles. It can be enabled using the following code
snippet:
android {
buildTypes {
debug {
minifyEnabled true
useProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
}
The built-in shrinker can only remove dead code, it does not obfuscate or optimize. It can be configured using the same files as
ProGuard, but will ignore all flags related to obfuscation or
optimization.
Unlike ProGuard, we support using the built-in shrinker together with
Instant Run: depending on the project, it may significantly decrease
the initial build and install time. Any methods that become reachable
after a code change will appear as newly added to the program and
prevent an Instant Run hotswap.
You don't need useProguard true anymore.
Code shrinking with R8 is enabled by default when you set the minifyEnabled property to true.
When you build your project using Android Gradle plugin 3.4.0 or higher, the plugin no longer uses ProGuard to perform compile-time code optimization. Instead, the plugin works with the R8 compiler to handle the tasks according to the official document.
If you want to use ProGuard instead of R8. Add this line in the gradle.properties file
android.enableR8=false
I set minifyEnabled true for my release buildType and it removed an entire enum which it thougt to be unused code i guess. This made my app crash due to a NoSuchFieldException. Took me 4 hours to find the reason for this crash. 0/10 can not recommend minifyEnabled.
Just enable minifyEnabled will have code both optimized and obfuscated.
This is because useProguard true is default so no need to set it explicitly.
See also:
Obfuscation in Android Studio

proguard gradle debug build but not the tests

I enabled proguard for the debug build using:
android {
buildTypes {
debug {
runProguard true
proguardFile 'proguard-debug.txt'
}
release {
runProguard true
proguardFile 'proguard-project.txt'
zipAlign true
}
}
}
The problem I'm experiencing when I do this is that the gradle build wants to proguard the tests during the proguardDebugTest task as well. I can't seem to modify to get access to this particular task. Is there a way I can proguard the debug apk but not the test apk?
runProguard is old. It was replaced with minifyEnabled
With minifyEnabled (and other changes in new versions of gradle) you will may encounter issues where the proguard config works for your debug apk but not for the instrumentation tests. The apk created for instrumentation tests will use its own proguard file, so changing your existing proguard file will have no effect.
In this case, you need to specify the proguard file to use on the instrumentation tests. It can be quite permissive because it's not affecting your debug and release builds at all.
// inside android block
debug {
shrinkResources true // removes unused graphics etc
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
testProguardFile('test-proguard-rules.pro')
}
Introduce a new build type "derived" from debug specific to the test app that disables ProGuard again like
android {
buildTypes {
debugTest.initWith(debug)
debugTest {
minifyEnabled false
}
}
}
and use that build type for the test app by assigning its name to the testBuildType property
android {
testBuildType 'debugTest'
}
Put
gradle.projectsEvaluated {
proguardDebugTest.enabled = false
}
it in your build script.
There are two things to know here:
The general Gradle feature to enable / disable tasks.
The Android Gradle plugin specific deferred creation of tasks in afterEvaluate, so you need to also defer disabling of the task to afterEvaluate.
EDIT:
One small note: It disables the task but fails the build. This is because the :preDexDebugTest task wont run with proguard on. The best solution i've found so far is to have debug specific proguard config. More details here. Create a separate proguard config file, include the regular proguard file like so:
-include proguard.cfg
and add test config. For me it was:
-dontwarn org.mockito.**
-dontwarn sun.reflect.**
-dontwarn android.test.**

Categories

Resources