Proguard : ignore library proguard errors - android

I am optimizing my proguard configuration and I am still keeping some class names that are not compulsory.
After intensive reflection I finally find why.
My class implements Parcelable and I use some libraries which use this proguard configuration:
# Needed for Parcelable/SafeParcelable Creators to not get stripped
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
which seems to be keep the names of the class and the CREATOR field.
I think that just the CREATOR field is really required as it is possible to read in the official proguard-android-optimize.txt proguard file:
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
As I am not the owner of the library, I cannot change it. Is there a way to override their proguard configuration file ? (which may be included with the consumerProguardFiles gradle keyword)
Thanks for the answers.

I finally came to a solution concerning proguard-android-optimize.txt.
In AndroidStudio, you have access to proguard-android-optimize.txt (⌘↑O on mac, or control + shift + N for windows/linux). Just copy the file content, and paste it to your project without the rules you want to remove. Finally use it as your own proguardFiles.
replace
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
with
proguardFiles 'proguard-android-optimize.txt', 'proguard-rules.pro'
Be aware that it is at your own risk and that you won't have the optimization from the latest embedded proguard files.
Concerning the consumerProguardFiles you have no choice to do pull request to them if you can, or ask for an evolve if you can contact the library author.

Related

using R8 to hide private and internal methods from android library

i have written android library. but when i integrate aar into client app. i can actually see private/internal/public methods of "public" classes.
what i expect is: it should show only "public" methods of "public" classes.
i am using R8, for release build i have following settings in library gradle file.
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
}
proguard-rules.pro file contents:
-keep class com.comp.sdk.UserManager {
public *;
}
here UserManager is 'object' in kotlin.
after building aar file. distributing to client app. client app can still see
private/public/internal methods for UserManager object.
my question is how can i write r8 rules for showing only public methods/variables of User object in kotlin?

Relase aar doesn't contain any code android?

I am using android studio bumble bee
I created a module library which has a single class
class Lib2 {
fun print(){
println("From lib2")
}
}
The proguard as
-keepclasseswithmembers class com.example.lib2.Lib2{
public <methods>;
public <fields>;
}
I create the release aar with minifyEnabled true
However when I integrate the aar with my app module I am not getting Lib2. What is wrong here?
From documentation:
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.
In English it means "Don't obfuscate classes that have the following methods and fields structure".
For example, keeping all classes which have constructors with single Context parameter:
-keepclasseswithmembers class * {
public <init>(android.content.Context);
}
Since, from my understanding, you simply want to keep the whole class, you can use:
-keep public class com.example.lib2.Lib2
In my opinion, it's better to use #Keep annnotation directly in the class, because:
The proguard rules is decoupled from source and as the time flies we forget that the rule is there. by using #Keep you know immediately what classes are being kept from obfuscation and it's much more readable.
This annotation is packed with your AAR so when you publish it, consumer apps won't obfuscate it as well. With proguard rules you must add another rules file to pack with your AAR that "tells" the consumer app to not obfuscate this class.
Much more simple:
#Keep
class Lib2 {
fun print(){
println("From lib2")
}
}

R8 changes "protected" methods of abstract class to "public" without -allowaccessmodification flag

I have an issue with R8. In MyLib I have public abstract MyLibsClass in which I have protected methods. MyChildClass extends from MyLibsClass in MyApp and after R8's magic all protected methods (including protected abstract) in MyLibsClass are changed into public ones, and of course in MyChildClass I'm getting "attempting to assign weaker access privileges ('protected'); was 'public') issue as trying to override protected abstract methods.
Additional info
gradle-6.0.1
MyLib's build.gradle
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
}
proguard-rules.pro
-keep class com.example.mylib.*{
public protected *; }
-keep class com.example.mylib.*$*{
public protected *; }
Anyone had this kind of issue or know a way to fix this?
So based on discussion here ,
DON'T USE DEFAULT PROGUARD SETTINGS FOR LIBRARIES
as allowAccessModification is enabled in default proguard settings, which is located in Android SDK (\Android\Sdk\tools\proguard\proguard-android-optimize.txt) and my mistake was using this for my libraries.
Citation from proguard manual
you probably shouldn't use this option when processing code that is to
be used as a library, since classes and class members that weren't
designed to be public in the API may become public.
So if anyone has the same issue I will suggest to create your own base config file for proguard and copy past whole default configs without "allowAccessModification" into it.
Also if someone interested more, you can track this issue. Hopefully will get separate config file for libraries in near feature.
I faced the same problem, and thanks to #Hayk Nahapetyan's answer, I could resolve it.
Here is my solution with a little more detail.
In the library module's build.gradle, remove the default file from the buildTypes's release closure:
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
R8 no longer uses the default file that is provided in the Android SDK. It generates one at build time, and puts it in the module's build directory at build/intermediates/default_proguard_files/global.
Copy the contents of proguard-android-optimize.txt-a.b.c (where a.b.c is the library version, if set) from that location to the top of the module's proguard-rules.pro. Then remove -allowaccessmodification; two times, if it originally appeared in both files.
This was also reported on the R8 bug tracker, and resolved there. See http://issuetracker.google.com/147447502.

How to obfuscate package name in android studio

I have successfully obfuscate class name and methods using following code
buildTypes {
release {
shrinkResources false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
in app level build.gradle file
and
-dontwarn mypackage.**
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-dontwarn
in proguard-rules.pro
but my problem is package name is not obfuscated.
So how can I achive it, please help.
Thanks
In Pro-Guard, package names can be obfuscated in various ways, with increasing levels of obfuscation and compactness. For example, consider the following classes:
mycompany.myapplication.MyMain
mycompany.myapplication.Foo
mycompany.myapplication.Bar
mycompany.myapplication.extra.FirstExtra
mycompany.myapplication.extra.SecondExtra
mycompany.util.FirstUtil mycompany.util.SecondUtil
Let's assume the class name mycompany.myapplication.MyMain is the main application class that is kept by the configuration.
All other class names except Main can be obfuscated.
By default, packages that contain classes that can't be renamed aren't renamed either, and the package hierarchy is preserved. This results in obfuscated class names like these:
mycompany.myapplication.MyMain
mycompany.myapplication.a
mycompany.myapplication.b
mycompany.myapplication.a.a
mycompany.myapplication.a.b
mycompany.a.a
mycompany.a.b
The -flattenpackagehierarchy option obfuscates the package names further, by flattening the package hierarchy of obfuscated packages:
-flattenpackagehierarchy 'myobfuscated'
Alternatively, the -repackageclasses option obfuscates the entire packaging, by combining obfuscated classes into a single package:
-repackageclasses 'myobfuscated'
The obfuscated class names then look as follows:
mycompany.myapplication.MyMain
mycompany.myapplication.a
mycompany.myapplication.b
myobfuscated.a
myobfuscated.b
myobfuscated.c
myobfuscated.d
Additionally specifying the -allowaccessmodification option allows access permissions of classes and class members to be broadened, opening up the opportunity to repackage all obfuscated classes:
-repackageclasses 'myobfuscated'
-allowaccessmodification
The obfuscated class names then look as follows:
mycompany.myapplication.MyMain
myobfuscated.a
myobfuscated.b
myobfuscated.c
myobfuscated.d
myobfuscated.e
myobfuscated.f
The specified target package can always be the root package. For instance:
-repackageclasses ''
-allowaccessmodification
The obfuscated class names are then the shortest possible names:
mycompany.myapplication.MyMain
a
b
c
d
e
f
Note that not all levels of obfuscation of package names may be acceptable for all code. Notably, you may have to take into account that your application may contain resource files that have to be adapted.
To obfuscate code
in Android studio just visit this post.
Or import your code into
NetBeans and use its build-in functional to compile, pre-verify, obfuscate and package the code))).

Android ProGuard how to hide/obfuscate source code of exported library

I'm developing Android library and I want to hide/obfuscate the source code implementation of the library.
The way the user project app will use the library is:
startActivity( new Intent(context, LibraryActivityName.class) );
So I need to keep just the name of entry point Activity inside the library project, That's all.
When I used the default ProGuard settings:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
as well as the suggested example for library - Nothing happened, and by clicking on the Activity name inside the user app (when he imports it) - One can see the source code.
Thanks,
As you do not have a typical library, you should not include the typical library example.
First of all, you need to enable Proguard execution, change this line:
minifyEnabled true
Second, you do not want to keep all public classes, but only the activity:
-keep class LibraryActivityName { public protected <methods>; }
The remaining classes can be fully obfuscated if I understand your question correctly, so there should be no need for further configuration, unless you use reflection somewhere.
It would also be good if you repackage the obfuscated classes into an internal package or something using
-repackageclasses my.library.package.internal
which might also required
-allowaccessmodification
btw. ProGuard will not obfuscate the code itself, only the class / method names.

Categories

Resources