How to keep/exclude a particular package path when using proguard? - android

I want to exclude some file paths from ProGuard. Example com.myapp.customcomponents
How can I do this? I hate to be placing -keep flags for every single custom component file I have in this directory.
I have tried the following but it doesn't work:
-keep public class com.myapp.customcomponents.*

You don't specify in what way it doesn't work. Your configuration keeps the names of all public classes in the specified package:
-keep public class com.myapp.customcomponents.*
The following configuration keeps the names of all public classes in the specified package and its subpackages:
-keep public class com.myapp.customcomponents.**
The following configuration keeps the names of all public/protected classes/fields/methods in the specified package and its subpackages:
-keep public class com.myapp.customcomponents.** {
public protected *;
}

Add the following line at the bottom of your ProGuard configuration:
-keep class com.facebook.** { *; }
Replace package name accordingly, here the package com.facebook will be excluded from ProGuard.

What worked for me using Android Studio 4.0 is:
-keepclassmembers class com.myapp.customcomponents.* {
<fields>;
<init>();
<methods>;
}
Double asterisks (**) in other answers did not work for me. I also tried the above configuration with R8, works fine.

Lots of people seem to recommend -keep class com.myapp.customcomponents.** { *; } as a way to exclude a path from being processed. See here:
exclude packages from proguard
Make Proguard completely ignore package
Prevent a directory from proguard obfuscation
The problem with this solution is that there is still some level of obfuscation happening, which can break your code. You can see the mapping in the mapping print out:
java.lang.String toString() -> toString
int getMemoizedSerializedSize() -> getMemoizedSerializedSize
void setMemoizedSerializedSize(int) -> setMemoizedSerializedSize
int getSerializedSize() -> getSerializedSize
boolean equals(java.lang.Object) -> equals
int hashCode() -> hashCode
The solution I have opted for is a two step process. First, use injars with a filter to select the package path I would like to process. It is possible to add the other package pathes as libraries.
-injars artifacts/in.jar(org/toprocess/**.class)
-outjars out/processed.jar
-libraryjars artifacts/in.jar(org/skipped/**.class)
-libraryjars artifacts/in.jar(org/moreskipped/**.class)
Second, merge the processed jar with the original jar, but only those paths that were skipped.
-injars out/processed.jar
-injars artifacts/in.jar(org/skipped/**.class)
-injars artifacts/in.jar(org/moreskipped/**.class)
-outjars out/merged.jar
-dontshrink
-dontoptimize
-dontobfuscate
The result is a merged jar that is the combination of the processed package path and the skipped paths. This exercise is invalid, if someone can provide a way to skip processing of certain paths completely (which I haven't found).

Put all your models-related include models, requests and responses object into a central sub package.
For example: com.example.models
Then add this line to your proguard-rules.pro file:
-keepclassmembers class com.example.models.** { <fields>; }

Related

Missing class: com.google.android.aidl.BaseProxy

Occasionally after generating the Signed APK, the following warning would appear
Missing class: com.google.android.aidl.BaseProxy
Missing Class: com.google.android.aidl.BaseStub
However, the APK would be successfully generated. Only when released the warning would be detrimental to the app.
Fatal Exception: java.lang.NoClassDefFoundError
Failed resolution of: Lcom/google/android/aidl/BaseStub
What gradle dependancy is required so this class is found and resolved?
Here are links to my gradle files (shared on google drive):
build.gradle (module: app)
build.gradle (project)
Thanks.
Try to update your proguard rules with the following:
-keepclassmembers class com.google.android.aidl.** { *; }
EDIT: (from proguard documentation)
-keep: Specifies classes and class members (fields and methods) to be preserved as entry points to your code.
-keepclassmembers: Specifies class members (only) to be preserved, if their classes are preserved as well.
If you specify a class, without class members, ProGuard only preserves the class and its parameterless constructor as entry points. It may still remove, optimize, or obfuscate its other class members.
If you specify a method, ProGuard only preserves the method as an entry point. Its code may still be optimized and adapted.
So if you're not sure which option you need, you should probably simply use -keep. It will make sure the specified classes and class members are not removed in the shrinking step, and not renamed in the obfuscation step.
(below -keep includes all classes and class members from aidl)
-keep class com.google.android.aidl.** { *; }
In your case you are missing BaseProxy and BaseStub classes. You can specify only these classes in your -keep and -keepclassmembers and test which method is suitable for you with best code obfuscation for your release build.
(below -keep includes only BaseProxy and BaseStub)
-keep class com.google.android.aidl.BaseProxy { *; }
-keep class com.google.android.aidl.BaseStub { *; }
My suggestion is to specify the class names you don't want to remove and utilize the code obfuscation to reduce your app size.
The symptoms of your issue (only happens in release build means proguard is removing the class) leads me to suggest :
if the class missing is one of yours add this annotation to the that class
#Keep class TheClass { ... }
if the class giving you pain is in the third party lib (mostly you add lib via gradle file in your project ) then normally in the library readme file (from their website like Github repo readme etc ) there is a proguard rules note that you need to add something like :
# Parceler library
-keep interface org.parceler.Parcel
-keep #org.parceler.Parcel class * { *; }
-keep class **$$Parcelable { *; }

proguard warning: the configuration keeps the entry point....but not the descriptor class

I've configured:
-keep ,allowoptimization,allowobfuscation,allowshrinking public class org.jf.dexlib2.dexbacked.** {
*;
}
but still getting the warning:
Note: the configuration keeps the entry point 'com.trusteer.trf.dex_parser { int get_strings_count(org.jf.dexlib2.dexbacked.DexBackedDexFile); }', but not the descriptor class 'org.jf.dexlib2.dexbacked.DexBackedDexFile'
I am using proguard version 4.7 (in Android SDK)
What should I do?
You have told Proguard to keep a certain method void foo(Bar bar); but to obfuscate the descriptor class Bar.
This is only a problem if you are going to invoke the method from an external source as the signature will be changed by the obfuscation (if you use Proguard to obfuscate a library and then use that library in another app).
So have the following choices:
Configure Proguard to also keep Bar.
Use the -dontnote directive to tell Proguard not to print notes like this.
Note: the configuration keeps the entry point '...', but not the descriptor class '...'
Your configuration contains a -keep option to preserve the given method (or field), but no -keep option for the given class that is an argument type or return type in the method's descriptor. You may then want to keep the class too. Otherwise, ProGuard will obfuscate its name, thus changing the method's signature. The method might then become unfindable as an entry point, e.g. if it is part of a public API. You can automatically keep such descriptor classes with the -keep option modifier includedescriptorclasses (-keep,includedescriptorclasses ...). You can switch off these notes by specifying the -dontnote option.
Add this line in your 'proguard-rules.pro' file to fix this problem .
-ignorewarnings
From the docuemnts:
allowshrinking Specifies that the entry points specified in the -keep
option may be shrunk, even if they have to be preserved otherwise.
That is, the entry points may be removed in the shrinking step, but if
they are necessary after all, they may not be optimized or obfuscated
So it appears that you need to remove the allowshrinking modifier.
In my case this problem appears when I add to build.gradle
minifyEnable true
Official instructions: https://flutter.dev/docs/deployment/android
Bug https://github.com/flutter/flutter/issues/19250
Sample proguard-rules.pro file:
#Flutter Wrapper
-ignorewarnings
-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.** { *; }
I did some digging in the docs. You have not supplied your whole configuration file, but I'm guessing that that com.trusteer.trf.dex_parser is set to both keep and not to obfuscate.
This means that there is a refrence from com.trusteer.trf.dex_parser to a class called org.jf.dexlib2.dexbacked.DexBackedDexFile that was either shrunk or obfuscated. This means that the link is now broken - dex_parser can't import DexBackedDexFile.
So either disable shrinking and obfuscation for DexBackedDexFile, or allow optimization and obfuscation on dex_parser.

Proguard and Netty 5 on Android

I've seen a couple questions regarding this issue, but they are for older versions of Netty.
I have tried their answers, switching org.jboss.netty out with io.netty, but the same error occurs.
I'm trying to compile an Android app that uses Netty 5.0.0Alpha2 (build #16) with Proguard enabled.
Without Proguard, the app runs fine.
As soon as I enable Proguard, I get this exception when it tries to use Netty:
java.lang.IllegalStateException: unknown type parameter 'I': class io.netty.channel.SimpleChannelInboundHandler
at io.netty.util.internal.TypeParameterMatcher.find0(Unknown Source)
at io.netty.util.internal.TypeParameterMatcher.find(Unknown Source)
at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
at io.netty.channel.SimpleChannelInboundHandler.<init>(Unknown Source)
...
This is my Proguard config:
# billing
-keep class com.android.vending.billing.**
# butterknife
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector {
*;
}
-keepnames class * {
#butterknife.InjectView *;
}
# admob
-keep public class com.google.android.gms.ads.** {
public *;
}
-keep public class com.google.ads.** {
public *;
}
# logging
-assumenosideeffects class android.util.Log
# netty (partial)
-dontwarn io.netty.**
-dontwarn sun.**
I have tested it without the -dontwarn options to see if the warnings would point me in the right direction, but it's all missing optional dependencies like slf4j and Tomcat.
I have also tried excluding all the Netty classes like so:
-keep class io.netty.** {
*;
}
...but that does not appear to fix it either.
I have fixed this issue with some carefully* applied Proguard rules after reading through parts of the rather huge Netty sources:
-keepattributes Signature,InnerClasses
-keepclasseswithmembers class io.netty.** {
*;
}
-keepnames class io.netty.** {
*;
}
My original exception was caused by the type variables being removed from the bytecode, which Netty uses via reflection. Signature in -keepattributes keeps this information.
You get a slightly different exception if you only do Signature on -keepattributes - adding InnerClasses fixes this one by bringing back even more information in the class files.
Later, I got java.lang.NoSuchFieldException: ctl; that's what -keepnames is for. This way, the field is still called ctl like Netty expects.
Finally, some members (like ctl, seen earlier) were being removed by Proguard because Netty only uses them via reflection. The final rule, -keepclasseswithmembers, makes sure Proguard doesn't remove them.
If you take this approach, I strongly recommend you use only the Netty jars you need, instead of the -all jar. Switching from -all to just the required Netty jars brought my method count way down after I had gone past the 65k limit. Reducing your jars requires bit of trial-and-error though as the separation is unclear and there's not really any resources saying what's what.
* not carefully at all, I just slapped rules into the file and removed them if they did nothing. There's probably a better way to do this that doesn't keep this information in the entire program, but instead just Netty.
Una's answer keep too many classes, which makes my app 1MB larger than usual. So I use the rules below:
# netty
-keepclassmembernames class io.netty.buffer.AbstractByteBufAllocator {
*;
}
-keepclassmembernames class io.netty.buffer.AdvancedLeakAwareByteBuf {
*;
}
-keep public class io.netty.util.ReferenceCountUtil {
*;
}

Enable Proguard for only two packages in large Android application

Background
I am developing an Android application that relies on multiple external libraries (8 added as library project dependencies, 14 added as jar dependencies).
Some of these jar libraries are closed source an have already been obfuscated and some of them rely pretty heavily on reflection.
The application uses ZXing for QR code scanning/recognition and, without Proguard optimization, ZXing is quite slow (at least on Android).
At first, I only needed to optimize the com.google.zxing.** package using Proguard. In order to do that I've added the following Proguard options in my config file (the best I could figure out from this question):
-keep class !com.google.zxing.** { *; }
-keep interface !com.google.zxing.** { *; }
-keep enum !com.google.zxing.** { *; }
-dontwarn !com.google.zxing.**
I exported my application and it works like a charm.
Problem
Now, I want to use Proguard to obfuscate the application's classes.
I've tried changing the above to:
-keep class !(com.google.zxing.**, com.example.app.**) { *; }
-keep interface !(com.google.zxing.**, com.example.app.**) { *; }
-keep enum !(com.google.zxing.**, com.example.app.**) { *; }
-dontwarn !(com.google.zxing.**, com.example.app.**)
-keep com.example.app.activities.** { *; }
-keep com.example.app.receivers.** { *; }
-keep com.example.app.services.** { *; }
-keep com.example.app.views.** { *; }
The problem is that Proguard does not accept !(package.one.**, second.package.**) { *; } as a valid option for a -keep rule.
Another approach would be to put a -keep rule for every package in my application.
This approach has two big disadvantages:
adding or swapping libraries would require changing the Proguard config file
it makes updating libraries a pain, as some of them are obfuscated and, when recompiled by the library's developer, will change package names.
Obviously, I would like to avoid this approach as much as possible (because of the high number of external libraries).
Question
Is it possible to use Proguard to obfuscate just two packages, without defining a -keep rule for each of the other packages in my app? If so, how can I do this?
The correct syntax is a comma-separated list without any parentheses:
-keep class !com.google.zxing.**,!com.example.app.** { *; }
See the ProGuard manual > Usage > Filters.
Note that this single line already implies the two other lines for interfaces and enums. You can imply the -keep options for all subpackages by not letting the last wildcard match subpackages:
-keep class !com.google.zxing.**,!com.example.app.* { *; }

Proguard and XStream with omitField() on Android

I was using XStream for deserialization of xml in my Android app, and now I'm struggling to add Proguard (obfuscator) to the mix.
Here's the runtime exception I run into (full: pastebin):
WARN/System.err(6209): net.lp.collectionista.util.a.g: XStream could not parse the response
WARN/System.err(6209): at net.lp.collectionista.a.s.a(Collectionista:215)
...
WARN/System.err(6209): Caused by: com.thoughtworks.xstream.converters.ConversionException: id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk] : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): ---- Debugging information ----
WARN/System.err(6209): message : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
WARN/System.err(6209): cause-message : id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): class : net.lp.collectionista.jaxb.googlebooks.search.Feed
WARN/System.err(6209): required-type : java.lang.Object
WARN/System.err(6209): path : /feed/entry/id
WARN/System.err(6209): line number : 1
WARN/System.err(6209): -------------------------------
WARN/System.err(6209): at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(Collectionista:89)
...
WARN/System.err(6209): at com.thoughtworks.xstream.XStream.fromXML(Collectionista:861)
...
WARN/System.err(6209): Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: id : id in loader dalvik.system.PathClassLoader[/data/app/net.lp.collectionista-2.apk]
WARN/System.err(6209): at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(Collectionista:68)
...
Needless to say this works fine without Proguard. I'm using shrinking, optimizing and obfuscating here, though I disabled it all on any XStream class, as well as any class that stands model for the xml fields:
-keep class net.lp.collectionista.jaxb.** { *; }
-keep class com.thoughtworks.xstream.** { *; }
I can confirm, from the obfuscated jar, as well as from the mapping.txt (for methods), that any classes mentioned exist and are not obfuscated, so untouched AFAICT. I also am retaining annotations.
The exception is pretty clear to me. I have:
xstream.omitField(Feed.class, "id");
among others. It seems the omitField() call does not work anymore and it starts looking for an "id" model class, because of Proguard. This is where I am stuck, even after diving into the XStream code. The whole omitField call in the obfuscated end result seems to be intact, so what could be additionally broken here? It should also not be "Feed.class" as that one is also still there. What am I missing? What is a good next step for debugging?
EDIT: I did notice the class files of xstream classes in my obfuscated jar are slightly smaller than the original ones, even with -dontoptimize. What is still being dropped?
EDIT2: I'm starting to think it has to do with the absence of dex warnings similar to the following:
[apply] warning: Ignoring InnerClasses attribute for an anonymous inner class
[apply] (com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$1) that doesn't come with an
[apply] associated EnclosingMethod attribute. This class was probably produced by a
[apply] compiler that did not target the modern .class file format. The recommended
[apply] solution is to recompile the class from source, using an up-to-date compiler
[apply] and without specifying any "-target" type options. The consequence of ignoring
[apply] this warning is that reflective operations on this class will incorrectly
[apply] indicate that it is *not* an inner class.
... or maybe not ...
EDIT3: Finally, in spite of dealing with many other bugs and problems such as the SimException bug, I've been able to get it working in some limited cases. That way I could pinpoint it to the obfuscation step. That is, at least, if I add "-dontobfuscate", the problem goes away. it isn't the first time I'm playing with that, so it must be the workarounds for the other problems, or the narrower configuration, that alleviates this problem as well. So here's me asking again: When I've already safeguarded the main parts of xstream and my model classes from obfuscation using "-keep", then what else could be creating this mess?
If you need more info, let me know.
As I said, the problem disappears if you -dontobfuscate but let's suppose you don't want that.
The solution is to keep more attributes:
-keepattributes EnclosingMethod, InnerClasses
-keepattributes *Annotation*
-keepattributes Signature
Once you get it working you can narrow down which parts of the XStream code to keep as well. I have:
-keep class com.thoughtworks.xstream.converters.extended.SubjectConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.ThrowableConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.StackTraceElementConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.CurrencyConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.RegexPatternConverter { *; }
-keep class com.thoughtworks.xstream.converters.extended.CharsetConverter { *; }
-keep class com.thoughtworks.xstream.annotations.** { *; }
You can also disable a lot of warnings related to XStream.
For more details you can find my version controlled project files here:
proguard.cfg
build.xml
I seem to be one of many to have problems with ProGuard and XStream for Android. After some trial and research, the following is what works for me - a complete config file together with some explanatory comments why I did what I did. Note that my priority was to obfuscate, but I did not care much about optimizing or shrinking.
And you need to remember that with this config (which keeps public members for libraries - see below) you will need to use "public" members for the class that is used by XStream to create your XML, because XStream will use member names for XML labels - and you do not want your XML labels to be changed to "a", "b" or "c" :) Good luck!
###########################################################
#
# FLAGS
#
###########################################################
# Not sure if I need this one, but seems to do no harm
-keepdirectories
# I needed NOT to optimize for SWT or XStream would not work, but for Android I do not seem to need to do that.
# However, if I try to shrink, XStream fails for Android. This different behaviour is a bit odd and black magic.
# However, I do not much care about optimization or size, and stability is more important for me, so let's
# neither optimize nor shrink (and shrinking saved us only about 1.5% of the size anyway).
#
# Note: this was not all that was necessary to make XStream run for Android - see other comments
# (search for XStream)
-dontshrink
-dontoptimize
# The following was configured for Android by default but now it does not make sense because I do not optmize, so disable just in case.
# -optimizationpasses 5
# Not sure if I need this one, but seems to do no harm.
-keeppackagenames
# This was configured for Android by default and it can only help.
-dontusemixedcaseclassnames
# This was configured for Android by default, and it is the default option as of ProGuard 4.5 anyway.
-dontskipnonpubliclibraryclasses
# ProGuard documentation says:
# For Java 6, preverification is optional, but as of Java 7, it is required.
# Only when eventually targeting Android, it is not necessary, so you can then
# switch it off to reduce the processing time a bit.
-dontpreverify
# Specifies to write out some more information during processing. If the
# program terminates with an exception, this option will print out the
# entire stack trace, instead of just the exception message.
-verbose
# Since I have turned off optmization, it makes no sense to have the following
# option enabled.
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# The followig was necessary or it would not build, as it otherwise wants a totally clean build first.
-ignorewarnings
###########################################################
#
# -keep SPECIFICATIONS
#
###########################################################
# I tried adding those to fix the XStream problem, but in the end fixed it differently (see other comments).
#-keepattributes EnclosingMethod, InnerClasses
#-keepattributes *Annotation*
#-keepattributes Signature
# The following was configured for Android by default.
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
# I tried adding those to fix the XStream problem, but in the end fixed it differently (see other comments).
# However, it might still be a good idea to stay away from thoughtworks for stability's sake.
# (Not sure if the second keep does not include the first one.)
-keep class com.thoughtworks.xstream.*
-keep class com.thoughtworks.xstream.* {
public protected <methods>;
public protected <fields>;
}
# The following plus not-shrinking seems necessary to make XStream run for Android.
# But again, as for SWT, I did not need to exclude all, public and protected methods and fields:
# just doing the public fields was enough.
# public protected <methods>;
# public protected <fields>;
-keep public class * {
public <fields>;
}
# This was configured for Android by default - and very necessary it is too.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# I put it in because we might need this one in the future.
# This was default for the Windows installation of ProGuard, which said:
# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
-keep class * extends java.sql.Driver
# This was configured for Android by default.
-keepclasseswithmembernames class * {
native <methods>;
}
# This was configured for Android by default.
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
# This was configured for Android by default.
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# This was configured for Android by default.
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# This was configured for Android by default.
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
XStream seems to introspect on the EnclosingMethod attribute, so keeping it in your ProGuard configuration may help:
-keepattributes EnclosingMethod
The ProGuard manual provides a list of attributes that you may want to keep. The error message suggests that you're already keeping the InnerClasses attribute, which is probably required indeed.

Categories

Resources