mikepenz / AboutLibraries

AboutLibraries automatically collects all dependencies and licenses of any gradle project (Kotlin MultiPlatform), and provides easy to integrate UI components for Android and Compose-jb environments
http://mikepenz.github.io/AboutLibraries/
Apache License 2.0
3.67k stars 423 forks source link

Minify + Shrink resources removes String resources #331

Closed AllanWang closed 7 years ago

AllanWang commented 7 years ago

Obviously this is the case, and it can be fixed by keeping the R class, but I was wondering if there is hopefully a better alternative somehow. -keepresources looked promising but it seems to be a dexguard feature rather than a proguard feature.

In comparison, keeping all the R classes adds around 60kb to a < 3mb app, which is somewhat significant.

rubengees commented 7 years ago

I had success with this:

-keepclasseswithmembers class **.R$* {
    public static final int define_*;
}

This only keeps the definitions used by AboutLibraries for autodetection but no other Strings.

mikepenz commented 7 years ago

@rubengees but wouldn't this also remove the strings of the libs themself? So do you add them manually to your project in addition?

rubengees commented 7 years ago

Hmm, no it works out of the box in my case. Maybe proguard intelligently recognizes the usage by the library? I do not use shrinkResources, but only proguard itself though.

AllanWang commented 7 years ago

Shrink resources is the issue, not proguard. I'm going to try what you have plus public static final int library_*; and see if that works

mikepenz commented 7 years ago

It can't as those are loaded during the runtime. So this means your definition still keeps the resources.

@AllanWang I do not think there is anything I can do about this, or the lib can do about it.

rubengees commented 7 years ago

Just tried it with shrinkResources enabled on my project, that works.

AllanWang commented 7 years ago

@rubengees is your project open sourced?

AllanWang commented 7 years ago

Also since this keeps the whole R class, I'm not sure if this will be better than the original rules

rubengees commented 7 years ago

Yes, here here are the proguard rules: https://github.com/proxer/ProxerAndroid/blob/master/app/proguard-rules.pro

Also since this keeps the whole R class, I'm not sure if this will be better than the original rules

I am not a proguard expert so this may be true. It did help me avoid the 65k field reference limit though, which popped up due to another lib (I only had the rule to keep entire R from the README before).

@mikepenz

It can't as those are loaded during the runtime.

As far as I know, proguard is able to recognize patterns of Strings when using reflection and keeps those in the resources. If that is the case, I do not know, why the define_ statements does not get keeped...

rubengees commented 7 years ago

@AllanWang

From the proguard documentation:

-keepclasseswithmembers [,modifier,...] class_specification
Specifies classes and class members to be preserved, on the condition that all of the
specified class members are present. For example, you may want to keep all
applications that have a main method, without having to list them explicitly.

I think that means that entire R does not get keeped, but only the fields we use or specify with this rule.

AllanWang commented 7 years ago

@rubengees I think it means that it does, since the only constraint is that a class contains a define string and it's preserving the entire class rather than just some members. I'm still waiting for travis to build so I can decompile it later. Plus I think the reason it works with define is because the rest of the class is kept, otherwise all your library_ strings will be gone too.

(Not a proguard expert either, so what you're saying is ideally what I want to happen)

mikepenz commented 7 years ago

The only thing which can be maybe done in the future is to split up the core, and move all libraries to a different module. So you can either use the module with all the resources, or you manually add the resources you want

rubengees commented 7 years ago

I just decompiled my app and the R file is really small. I think it works the way we want to (I could be mistaken of course).

mikepenz commented 7 years ago

@rubengees just drag&drop the apk onto Android Studio 3.0, it has a really cool visualisation, and also shows the contained resources

AllanWang commented 7 years ago

@mikepenz The issue still stands with all the external libraries with their strings,

Using the rules defined above definitely cleans it a fair bit though, since it seems to remove all the appcompat resources.

My R class with from 6k variables to 3k, and About library went from 3709 to ~300.

For the app, the size

mikepenz commented 7 years ago

well I can't do anything about external libraries.

The only reason the R class has to be kept is for the auto-detection. You can enable proguard, don't add the rule, and just manually set which libraries needs to show up

AllanWang commented 7 years ago

Our cases are for proguard + shrink + no auto detection. Because without this rule those strings will be gone anyways. I don't think any changes need to be done on your end since it's fine the way it is, but perhaps the proguard lines can be added to the readme for those who want to shrink their resources as much as possible and are willing to input libraries manually.

Thanks rubengees!

-keepclasseswithmembers class **.R$* {
    public static final int define_*;
}
rubengees commented 7 years ago

@AllanWang My pleasure :) @mikepenz I could send a PR if you like.

mikepenz commented 7 years ago

@rubengees already writing the README update :)

mikepenz commented 7 years ago

https://github.com/mikepenz/AboutLibraries/blob/develop/README.md#proguard

Thank you @rubengees & @AllanWang