I already made a Flutter app. The release apk is about 14MB. I searched methods to minify this and found this ons: https://flutter.io/android-release/#enabling-proguard
But my question is, how can I get to know all my used additional libraries for step 1? Are there any commands to know them or is it just all the dependencies that I added to the pubspec.yaml ?
How do I need to implement them in this file /android/app/proguard-rules.pro?
First, we will enable shrinking and obfuscation in the build file. Find build.gradle file which sits inside /android/app/ folder and add lines in bold
android {
...
buildTypes {
release {
signingConfig signingConfigs.debug
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Next we will create a configuration which will preserve entire Flutter wrapper code. Create /android/app/proguard-rules.pro file and insert inside:
#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
Note: Use signingConfigs.release instead signingConfigs.debug to build a apk or appbundle
I will leave this answer here as an addition for any poor soul that has to deal with this issue and encounters this thread.
As of December 2021 with the latest Android Sdk, Studio and Flutter versions, if you try to douseProguard true it will not work because it's obsolete.
Sadly, Gradle will not tell you this, instead, you will get an error like this:
A problem occurred evaluating project ':app'.
> No signature of method: build_7cqkbrda1q788z3b02yxbvrx9.android() is applicable for argument types: (build_7cqkbrda1q788z3b02yxbvrx9$_run_closure2) values: [build_7cqkbrda1q788z3b02yxbvrx9$_run_closure2#41108b15]
Which as you can see it is complete gibberish and not useful. The secret is to just not use useProguard at all. By default Flutter is setup to use R8 which handles minification now on Android.
Here is a so post about this for reference: Gradle : DSL element 'useProguard' is obsolete and will be removed soon
If you are using firebase, see Flutter build crashes using ProGuard with Firebase Auth
Next, you need to consider the dependencies in pubspec.yaml You can immediately ignore any pure Dart packages - you are just looking for plugins. Of these plugins, you are just interested in ones that make use of existing libraries. You will likely have added these to gradle. Those are the ones you need to protect from name shortening.
The simplest approach may just be to try it and see what package names pop up in the NoClassDefFoundError and keep iteratively adding them.
As Remi says, your gain will be minimal, so is it really worth the hassle. You should see some improvements in APK sizes over the coming releases.
Related
I am developing one android library for that i want enable the progurad.
First thing i did is:
I have enabled the minification for my library
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
After this, I have generated the AAR file with minification. And then i used the AAR file to my testing app to check whether my library classes were available. But classes were not there, Because the pro guard removed all my classes from library as it was not used.
Second thing i did is:
-keep public interface com.example.client.** { *; }
I have added the above thing to my proguard-rules.pro. Now i can able to see all my classes with proguard applying the same class, function, variable names. (In mapping file i could see the same name getting applied)
I don't know the exact way to apply the proguard to generate the obfuscated AAR.
Is there any guideline to generate AAR with the minification/
Or in my case what is fix to generate AAR with the class available?
I am struggling for a long time... Could someone please try to help me!!!
From this reference:
https://github.com/codepath/android_guides/wiki/Building-your-own-Android-library
I have the following gradle file:
android {
compileSdkVersion 25
buildToolsVersion "26.0.2"
buildTypes {
release {
minifyEnabled true
consumerProguardFiles 'consumer-proguard-rules.pro'
}
}
}
And the following proguard file:
-dontobfuscate
-optimizations !code/allocation/variable
-keep public class * {
public protected *;
}
However all of my classes in the aar are missing when I run the 'assembleRelease' task to build my release aar file.
Any ideas?
You should set minifyEnabled to false (the default value) :
consumerProguardFiles is not used for immediate minification (i.e. when building the library itself). It it used when the consumer of the library (e.g. an application) is build.
Minifying the library before consumption is not recommended, because you can not know what parts will actually be used before the final build. Libraries usually don't do it. e.g. LeakCanary, ACRA, Butter Knife
in general, a library must keep the all the methods and method names, required to operate it; eg:
-verbose
# -libraryjars ../app/libs
# -dontpreverify
# -dontobfuscate
# -dontshrink
# -dontoptimize
# keep class BuildConfig
-keep public class **.BuildConfig { *; }
# keep class members of R
-keepclassmembers class **.R$* {public static <fields>;}
the answer to the question should probably be:
# keep all public and protected method names,
# which could be used by Java reflection.
-keepclassmembernames class * {
public protected <methods>;
}
there are most likely some more rules required, while the -verbose flag tells one what to write into there. when building the library against other code (as suggested above), one nevertheless needs to add more or less the same rules for the library. there are also quite some, not open source, libraries with obfuscated class names.
a library's build.gradle might look about like this:
android {
defaultConfig {
consumerProguardFiles 'proguard-consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false // don't proguard the library itself.
}
}
}
the default proguard-consumer-rules.pro explains it:
The Android Gradle plugin allows to define ProGuard rules which get embedded in the AAR.
These ProGuard rules are automatically applied when a consumer app sets minifyEnabled to true.
The custom rule file must be defined using the 'consumerProguardFiles' property in your build.gradle file.
When a library is not being processed itself, it still can bring it's ProGuard rules - in order to be consumed, when building the whole project.
I am not getting what you actually want to do, but I can suggest you one thing that is just don't do assembleRelease instead import in your another project, clean project and build then use the generated aar from the /build/outputs/aar/ directory. And must check you are not using reference of obfuscated class anywhere.
I am following this tutorial and there is one section that says:
If you use Picasso as your image engine, add rules as Picasso's README says. And add extra rule:
-dontwarn com.bumptech.glide.**
am confused on how to add -dontwarn com.bumptech.glide.**?
I tried compile '-dontwarn com.bumptech.glide.** and compile 'com.bumptech.glide.** but both attempts failed.
Please can anyone guide me through it?
I am sorry for the beginner question
this rule is related to proguard
so you should add it to proguard-rules.pro file
you can read more here https://developer.android.com/studio/build/shrink-code.html
proguard change the references and the structure (obfuscating names specially ) of your code, for shrinking and security reasons, but that's not good for 3th party libraries.
Application projects obfuscate the entire code base, including any referenced libraries, so they need proper configuration for the application code and for the library code.
glide in your case
So the rules tell proguard to keep the code as it is (Keep command).
Sample code from gradle
minifyEnabled true
shrinkResources false
debuggable false
proguardFiles getDefaultProguardFile(
'proguard-android.txt'),'proguard-rules.pro'
so as you see the rules are written in two files, proguard-android is the default file that can be found in your SDK folder.
the proguard-rules is in you app folder.
by minifyEnabled true you enable proguard.
so your main issues is you don't know how to add the rules.
Here are ProGuard Rules for most of the famous android libraries here
but it always better to check library page, just google it for example glide + proGuard
here is sample code from one of my projects for glide , write it inside proguard-rules.pro
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.GeneratedAppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
I am using Guava in a Android project. I am hitting the 65k method limit which fails the gradle build. I found that this could be resolved by using proguard. I run Proguard on release build and it works fine. I do not want to run proguard on debug build as it makes debugging hard. I was wondering if there is a way to resolve this? One option I am considering is to build a local guava.jar and defining that as a dependency instead of pulling it from maven central. Is there a better way to do this?
Latest Android build tools support MultiDex option. This allows to build apps with over 65k methods. Just follow the official guide.
Also you can enable automatic resource shrinking alongside with ProGuard:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
}
}
}
According to the official doc of Guava, you can use the following:
-injars path/to/myapplication.jar
-injars lib/guava-r07.jar
-libraryjars lib/jsr305.jar
-outjars myapplication-dist.jar
-dontoptimize
-dontobfuscate
-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
This will keep your methods with the same name without obfuscating. Meaning that you can still debug properly with all the appropriate names written as is.
Every project I've previously worked on where Proguard was specified it was eventually abandoned as enabling it caused so many problems it was unusable and an enormous drain on resources. But my current project really does require obfuscation to make reverse-engineering more difficult. As I'm using Android Studio and Gradle I enabled it in the build config:
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
I then build a release build and see 292 warnings and build failure. Most are as follows and relate to libraries (Retrofit, Joda Time, Butterknife etc)
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.lang.model.element.TypeElement
OK, so I assume it is optimising away portions of the libraries. So I tried adding lines like this to the proguard-rules.pro file (specified in the Gradle file and auto-created by Android Studio):
-keep class butterknife.internal.** { *; }
No difference. OK, so I'll try disabling ALL shrinking and optimising to hopefully only benefit from obfuscation (even if admittedly a little less obfuscation benefit). I added these line to the Proguard config file:
-dontshrink
-dontoptimize
I recompile, and absolutely nothing changes, I'm still left with 292 fairly meaningless compilation warnings. Now I'm really confused.
How can I make 100% certain Proguard is actually reading my Proguard config file? Or is it using it but I've set an incorrect option?
What can I add to the Proguard file to reduce its work to JUST obfuscation so I have a Proguard-enabled build config that works as a starting point (without breaking my app) and does not optimise away any code.
I would appreciate any help to assist in reducing my hatred of Proguard.
put the following in your proguard config so that it wont mung up your butterknife library.
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepclasseswithmembernames class * {
#butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
#butterknife.* <methods>;
}
here is a github discussion link about the same issue, https://github.com/JakeWharton/butterknife/pull/117#issuecomment-51292624