I am using Android Studio version v2.1.2 and Proguard doesn't work when I try to sign the release build, the build fails dramatically.
According to this link from developer docs Jack does obfuscation automatically.
Handles shrinking, obfuscation, repackaging and multidex Using a
separate package such as ProGuard is no longer necessary.
I had to disable minifyEnabled flag and remove the line where we load proguard file; to get it working, after doing this; I inspected the apk file generated by doing the above and I cannot tell whether Jack really obfuscated and reduced redundant code as the release apk size is same as the debug apk size.
I need to understand how to make obfuscation work with the newer compiler as the documentation doesn't really help.
I am looking forward to understand the following questions.
Does Jack work without Proguard file?
Is there a way to specify Proguard file?
The Jack compiler has its own Shrinker and Obfuscator that re-uses existing Proguard rules (see supported directives).
The configuration should be the same as before, so you need to add the following to your buildType configuration:
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
proguardFile 'your-proguard-file.txt'
Related
I have read the article. The author think every Android app should use code shrinking.
I use the following code to shrink and obfuscate code, proguard-rules.pro is original and blank, and proguard-android-optimize.txt is original. it's default made by Android Studio.
You know that some project can work well in Android Studio but failed after publish to Google Play, you can see the article.
When an app run in Android Studio, I think ProGuard doesn't work and it doesn't shrink and obfuscate code, so the app works well in Android Studio.
When I generate .aab file for publish in Android Studio, the ProGuard will shrink and obfuscate code, but it maybe cause runtime error due to incorrectly shrink and obfuscate operation.
How can I test if ProGuard works correctly before I publish an app to Google Play ?
buildTypes {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
}
}
Add content:
To Ryan M: Thanks!
It seems that I can test whether ProGuard works correctly in Android Studio by the article.
You can see Code A and Image A.
Is that right?
Code A
debugMini {
initWith debug
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
matchingFallbacks = ['debug']
}
Image A
Install and run the minified release version of your app (see here or here for info on installing AAB files) that you upload to Google Play, not the debug version.
If you're just hitting "Run" in Studio, you're installing the debug version that doesn't (by default) have Proguard or other minification run on it. If you instead use the minified release version before uploading it to Google Play, you'll get the same behavior you will after uploading: Google Play isn't running any "extra" Proguard tasks on it after you upload.
You can also use the Alpha/Beta testing tracks in Play to test the full Play experience without publishing to a wider audience or fiddling with bundletool.
There are several ways to confirm you code is being properly minimized. One is to check the youappmodule/build/outputs/mapping/release/mapping.txt file. This will include lines like
com.example.somepackage.SomeClass -> a.b.c.d:
If you see that, you know which classes are being properly obfuscated. You can also find out which classes have been removed by making sure there is no such entry for that class.
Another good way is to inspect the output APK in Android Studio. In Android Studio 4.1 you can do this by going to Build > Analyze APK and then selecting your APK that should have had Proguard run with it. You can then inspect the classes.dex file and check its contents. You can see which classes have been obfuscated and removed by directly traversing the file structure.
I think the easiest way to test it is to build your app in the release version and install it on your device.
This is the simplest way.
In my app's example, the debug apk is 20Mbs (from 13Mbs, after upgrading the Gradle version and Gradle Plugin version), and the release apk is just 5Mb. Why is that?
In the build.gradle file, the buildTypes part has remained unchanged, so there hasn't been any optimizations / shrinking from the R8 compiler or from ProGuard.
android {
...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
RELEASE:
DEBUG:
You can see the big difference in size in the lib folder, among others.
There are more optimizations happen during the release builds besides ProGuard and R8. According to the documentation https://developer.android.com/studio/build/shrink-code.html
When you build you 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 following compile-time tasks:
Code shrinking (or tree-shaking): detects and safely removes unused classes, fields, methods, and attributes from your app and its library dependencies (making it a valuable tool for working around the 64k reference limit). For example, if you use only a few APIs of a library dependency, shrinking can identify library code that your app is not using and remove only that code from your app. To learn more, go to the section about how to shrink your code.
Resource shrinking: removes unused resources from your packaged app, including unused resources in your app’s library dependencies. It works in conjunction with code shrinking such that once unused code has been removed, any resources no longer referenced can be safely removed as well. To learn more, go to the section about how to shrink your resources.
Obfuscation: shortens the name of classes and members, which results in reduced DEX file sizes. To learn more, go to the section about how to obfuscate your code.
Optimization: inspects and rewrites your code to further reduce the size of your app’s DEX files. For example, if R8 detects that the else {} branch for a given if/else statement is never taken, R8 removes the code for the else {} branch. To learn more, go to the section about code optimization.
I am working an a existing Android app which includes the Dropbox SDK. The SDK includes a ton of new classes which makes it necessary to use minifyEnabled true in buildsettings to avoid multidex.
While this is no problem in my release config it has a major downside when debugging the app: Most of the breakpoint do not work any more.
Even if a breakpoint works and I would like to use the "step into" feature to step through the code it happens that this is not possible. Instead of stepping to the code, the call stack shows obfuscated instead of the real code:
a.c:111,f (com.my.app.a)
xb:106,f (com.my.app.a)
onCreate:62, MyApp (com.my.app.TheClass)
...
So, I cannot set minifyEnabled false. Is there anything else I can do to still use my breakpoints?
If you only want to use ProGuard (minifyEnabled true) in order to prevent the app from requiring multidex, you can disable obfuscation and only use the shrinking feature of ProGuard (assuming that you dont use optimization e.g. when using proguard-android.txt as default config).
This should not create obfuscated stacktraces and allow you to debug the application.
Edit:
In order to disable obfuscation, just add
-dontobfuscate
to your configuration file.
When prepare to release the Android app, we would use Proguard to obfuscate the code which may break the app.
So once some error occurs, we modify that and build-release-test again and again, is there a simple way to do that?
Also, is it possible to see the obfuscated code directly in Android Stuido?
Retracing
Retracing is what makes the obfuscated stack trace human-readable by replacing obfuscated names to the ones used in original source. In order to be able to retrace, make sure to save mapping.txt for every build you are about to test or send to someone. Mapping is unique for every build process.
Mapping can be found in
appModule/build/outputs/mapping/release/mapping.txt
For retracing, there is a convenient tool named proguardgui, found in
$ANDROID_HOME/tools/proguard/bin/proguardgui.sh
(*.sh for UNIX systems, for other platforms expect different extension).
Choose "ReTrace", add a mapping.txt (make sure to use mapping.txt that was generated for that apk build) and paste the obfuscated stack trace into window. Press "ReTrace" on bottom right corner and you should get that stack trace with deobfuscated names.
Here's a screenshot with sample input I found on the Internet
Decompiling
Also, is it possible to see the obfuscated code directly in Android Stuido?
No, but you might see the code by converting dex to jar and decompiling it.
dex2jar myapp.apk
jd-gui myapp-dex2jar.jar
dex2jar github page.
jd-gui from github page.
Practices I use to follow
What works for me is whenever I add a library I add a proguard config for a library (usually provided by library developer).
There's also a project called android-proguard-snippets, thought they are mostly outdated, so make sure to check from library developer first.
For easy management, I use to split the proguard config for every library in a separate file. Below is a snippet from one of my build.gradle buildTypes for release
proguardFile getDefaultProguardFile('proguard-android.txt')
proguardFile 'proguard-dart.pro'
proguardFile 'proguard-parceler.pro'
proguardFile 'proguard-retrolambda.pro'
proguardFile 'proguard-rules.pro'
proguardFile 'proguard-rx-java.pro'
proguardFile 'proguard-support-design.pro'
proguardFile 'proguard-support-v7-appcompat.pro'
For objects used in Firebase serialization, add #Keep annotation.
For fields used by Gson, add #SerializedName annotations or use #Keep on an object.
Whenever I use reflection (or Animators, which are technically the same) I make sure to add proguard rule to keep the code accessed by reflection just after I write such code. In the end there will be probably nothing to fix.
All,
I'm trying to use proguard to obfuscate .APK file and it seems not working. As Proguard mainly works for Java bytecode, I use dex2jar to convert the apk file to jar file, use Proguard to obfuscate it, and then repackage the output jar into apk. The resulting apk seems problematic. I got a lot of error like Could not read file: Expected chunk of type 0x80003, read 0x6d783f3c. Is there anyway that I can obfuscate the Android bytecode directly on .apk instead of source code? Please help.
Thanks!
You need to use proguard with the proper configuration for android.
There is also a predefined setting for your gradle build file (when using android studio)
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
Source: http://developer.android.com/tools/help/proguard.html