Google has released a test version of their new JACK compiler for Android developers with Android Studio 2.1.
My question is, how do we enable obfuscation for the APK with JACK? The article below says that JACK performs obfuscation natively and eliminates the need for Proguard:
Compiling with
Jack
Whereas the following article says that JACK makes use of Proguard configuration files (i.e. the .pro file) for performing obfuscation:
Experimental New Android Tool Chain - Jack and Jill.
It also says that
During this process Jack also handles any requested code minification (shrinking and/or obfuscation).
What exactly does this mean? Do we have to use the minifyEnabled option and define a .pro file containing the Proguard options?
In Summary:
How exactly do we go about enabling obfuscation with JACK? Can we
bypass the use of Proguard, or does Proguard play a de-facto role in
the obfuscation process, even if we compile with JACK?
Does JACK currently support obfuscation or not, and is it available
in a stable (i.e. non-beta/canary) version of Android Studio?
Note:
I have already referred the following posts:
How to enable Jack (Java Android Compiler Kit) in android studio.
Error:Jack is required to support java 8 language features.
Further References:
An Introduction to Jack and Jill on X86.
The dark side of Jack and Jill.
Java 8 Language Features.
Update:
The answer by Matt Insko is helpful, but I would like more detail, and a more precise, canonical answer.
J.A.C.K. obfuscation does not appear to be supported in the latest released Gradle Plugin (v2.1.0).
If you enable JACK when using the latest v2.1.0 plugin, it will tell you Jack requires Build Tools 24.0.0 or later requiring you to use the preview tools.
Using android gradle v2.2.0-alpha1, Build Tools-v24rc4, Platform Tools-v24rc3, and Sdk Tools-v25.1.7rc1 I was able to get obfuscation to be performed by JACK.
When enabled inside defaultConfig it complained Minifying the variant used for tests is not supported when using Jack., because minifyEnabled true was configured in the debug build.
So, I created a custom build type and enabled it there:
buildTypes {
...
custom {
minifyEnabled true
proguardFiles 'proguard-android-JACK.txt-2.2.0-alpha1'
jackOptions {
enabled true
}
}
There was a problem when using proguardFiles getDefaultProguardFile('proguard-android.txt'). It errorred with: com.android.jack.api.v01.ConfigurationException: Error while parsing ..., . So, I just removed the lines it complained about and then just manually specified my modified configuration file.
You can have a look here: https://source.android.com/source/jack.html
From the official documentation:
(Jack) Handles shrinking, obfuscation, repackaging and multidex. Using a
separate package such as ProGuard is no longer necessary.
Please notice especially the section "Shrinking and Obfuscation" where it's mentioned that:
Jack has shrinking and obfuscation support and uses proguard
configuration files to enable shrinking and obfuscation features.
And also the supported and ignored options are presented too.
Related
I have a complicated build setup for an android app which basically consists of a normal android app fused together with a Xamarin/Mono project in order to include an important C# library (like this: https://github.com/royd/KotlinAppWithXamarinDependency)
Everything is working fine except if I enable minification in my app/build.gradle via minifyEnabled true the app instantly crashes on startup because the Mono-runtime can't find native assemblies that are definitely contained in the apk.
This is the message I get in Logcat:
A/monodroid: No assemblies found in '(null)' or '<unavailable>'. Assuming this is part of Fast Deployment. Exiting...
With minifyEnabled false everything is working fine so I tried disabling all config options in my proguard-rules.pro:
-dontobfuscate
-dontoptimize
-dontshrink
And I also added the following lines to my app/build.gradle
packagingOptions {
doNotStrip "*/armeabi/*.so"
doNotStrip "*/armeabi-v7a/*.so"
doNotStrip "*/x86/*.so"
}
Unfortunately all this doesn't help.
I also decompiled a working and a broken apk with dex2jar to compare the bytecode. It seems to be exactly the same except for some enum-optimizations that shouldn't matter.
According to the error message in Logcat the error seems to be thrown from the native library libmonodroid.so.
So my question: What does minifyenabled flag do when all these config options are disabled?
Edit:
I have found out that minification works as intended when I use version 4.0.1 of Android Gradle Plugin (from July 2020). Upgrading the version to 4.1.0 (August 2020) breaks my app. Now the question is what changed between these two versions?
When you set the minifyenabled as true. The r8 will choose the configuration files but not only the proguard-rules.pro and the app/build.gradle to shrink, obfuscate, and optimize your app.
There are some others files such as AAR libraries: <library-dir>/proguard.txt and
JAR libraries: <library-dir>/META-INF/proguard/ and so on. So this error may be caused by the native library losing when you set the set the minifyenabled as true.
If you need more information, please check the official document:https://developer.android.com/studio/build/shrink-code#enable
In addition, you can check the 'proguard-android-optimize.txt' and when you add the -dontoptimize to proguard-rules.pro may cause a conflict.
I found out, that in the Android Gradle Plugin versions 3.6.0 to 4.1.0 they switched to a more performant tool for building apks called zipflinger.
This tool can be disabled by adding this line to my gradle.properties:
android.useNewApkCreator=false
When building the apk zipflinger stores the external .NET assemblies as DEFLATED zip entries instead of STORED and thats why monodroid cant read them.
References:
https://github.com/xamarin/xamarin-android/issues/6838#issuecomment-1110816027
https://copyfuture.com/blogs-details/20210119115509664T
I'm working on an Android SDK that is about to be split into separate modules, with some code being shared between others, namely:
shared classes
SDK with feature #1
SDK with feature #2
There is a need of obfuscating the output AARs. With one single module it's not an issue, but I can't find how to configure the whole project correctly with Proguard.
How does the Proguard obfuscation work in case when I want to publish a new version of all these libraries? Will all the modules be obfuscated separately? How can I make sure that all the modules will be obfuscated at once and the release version of the libraries will correctly refer to all the artifacts that are located in the shared module?
Not sure I understand the issue.
But if you want to release 2 SDKs now instead of 1 (before split), I don't think the setup should differ very much.
Just make sure you have proguard file in these SDKs and you are using it in the build script specific to that SDK (module). Then just run something like :sdk:assembleRelease and you are done.
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'library.pro'
}
It is described in detail in this issue:
Obfuscating the .aar files
I understand that shared module is not published, so there you just need to define specific proguard rules that will be used by other modules, like this:
release {
minifyEnabled true
consumerProguardFiles 'onboarding-proguard-rules.pro'
}
So today I decided to try my hand at making at making a dynamic feature module. I have R8 enabled with both minifyEnabled and shrinkResources set to true. Trying to compile gives me the following error.
Resource shrinker cannot be used for multi-apk applications
Affected Modules: app
Has anyone else seen this? There are similar questions around stack but nothing directly related to DFMs.
I would love to keep this flag enabled to avoid library bloat
Gradle Plugin: 4.0.0
Gradle Wrapper: 6.1.1
This feature is implemented starting Android Gradle Plugin 4.2.0 and can be enabled by setting android.experimental.enableNewResourceShrinker=true flag in gradle properties.
Details are available here.
I have been trying to use the latest JACK and JILL build system to for my android project. I know that JACK process includes the proguard processing.
But after that i couldn't locate the mappings.txt file for back-tracking stack-trace of bugs provided on google play developer console.
Please help me LOCATE mappings.txt.
Another related question is if the shrinkingResources still works while JACK because shrinkingResources requires minifyEnabled true but JACK requires minifyEnabled false.
Project Config--
compileSdkVersion 24
buildToolsVersion "24.0.0"
classpath 'com.android.tools.build:gradle:2.1.2'
UPDATE--
Answer posted by T. Neidhart is NOT a working solution.
To enable obfuscation/shrinking with JACK you need to set minifyEnabled to true. It was unsupported in earlier versions, but now JACK has its own obfuscation and shrinking implementation (not using ProGuard at all) that can process some of the original ProGuard rules (for a complete list of supported options refer to Jack obfuscation and shrinking).
Once the configuration is properly setup, the mapping.txt file will be located in the same place as before: build/outputs/mapping/<buildtype>/mapping.txt
There is nowhere to find that mappings file as JACK internally process proguard and there are some issues pointed on android tools site while enabling JACK.
So for now not using JACK is the best option if you care tracing back exceptions in your apps.
I am getting the following error when I compile my app:
[2014-05-07 21:48:42 - Dex Loader] Unable to execute dex: Cannot merge new index 65536 into a non-jumbo instruction!
I am at the point that if I declare a new method anywhere in my package, I get this error. If I don't, the app compiles.
I would like to know what exactly (and accurately) does this error mean. My app is big, but I don't think its that big! So:
Does the error mean I have too many methods? public? static? package? members?
Is it related to the methods/members of my root package, or also to the included JAR libraries?
Is there a way to get more debug information about this?
I already know about that "jumbo" enabling flag addressed in the similar questions here in SO, however, I think jumbo mode is not available on the API level I'm targeting (ICS).
Your error is for the amount of strings (methods, members, etc) in a single dex file.
You need to compile you app using jumbo in dex with:
dex.force.jumbo=true
in project.properties
This increment the limit for strings in a dex files. And your project will probably compile.
Also with jumbo set, the is another limit of 64K only for methods in an single dex. If you get this limit in the future , you will need to remove some dependencies.
UPDATE: for build with Gradle:
In Gradle you can enable jumboMode also in the build.gradle file with:
dexOptions {
jumboMode = true
}
Check:
Android Build: Dex Jumbo Mode in Gradle
Also with Gradle you can avoid the 64K limit for methods using multidex build, tutorial here:
https://developer.android.com/tools/building/multidex.html
For gradle build, just add the dexOptions into build.gradle to enable jumbo mode:
android {
dexOptions {
jumboMode = true
}
}
Remember to run "gradle clean" before your new building.
It's related to the number of methods of libraries included in the project. For example if you have tracking in your app, just Google Analytics is ~7000 methods.
In one of my projects using Lombok (2MB of JAR) gave me these problem. Solved getting rid of this library.
It looks like the problem occurs because all the class files from your project and JAR files are packed together before DEXing. This may not be completely true but any way of controlling this in our project has proven to be quite difficult. Even removing stuff that initially caused this problem, cleaning and rebuilding didn't fix the issue for us in a consistent way.
So we took this opportunity to switch our project to Android Studio and managed to solve the problem by turning on ProGuard for debug builds as well. More precisely we only use the shrink phase of the ProGuard's processing chain.
Gradle makes it very easy to turn on ProGuard for debug builds:
buildTypes {
debug {
runProguard true
proguardFile 'proguard-project-debug.txt'
}
}
And here is the debug ProGuard config we use:
-keep class com.your.code.**
# Use -keep to explicitly keep any other classes shrinking would remove
-dontoptimize
-dontobfuscate
-ignorewarnings
This does increase the build time of the project but the good side is that the debugger still works.
The only faster alternative I can think of is that any JAR files are manually stripped of the unused class files. But this is not only difficult to do it is also inconvenient when you want to use a slightly larger part of a library at a later time.
I hope this helps other developers struggling with this issue. And perhaps in the future Google can improve the compiler that does this pruning by default. Our APK DEX file went from 8MB to 2.9MB.
Newer gradle (1.0.0+) versions
In newer Versions of Android studio (1.0+) the bundled Gradle got updated. There were some changes on how the build mechanism works so your project Gradle file can now take advantage of the minifyEnabled and shrinkResources parameters. Current version is 1.1.0.
Keeping up with changes on a fast moving platform like Android takes effort but it is often rewarded with new features, tools and faster build times. So updating Android Studio and (carefully) updating your projects is worth the time you invest.
buildTypes {
debug {
proguardFile 'proguard-project-debug.txt'
minifyEnabled true
shrinkResources true
}
}
Some interesting observations. Same error may appear if you have multi-flavor project. It's confusing. Turned out that I attempted run app with generic command: gradlew installDebug. When I've changed command line to look like this problem is gone. Don't forget to replace Flavor part with your actual one.
gradlew installFlavorDebug