Proguard setting to not remove unused method - android

Conside the following code structure for android:
package blah;
class A{
class B{
public void foo(String s){
}
}
}
How can I tell proguard to not remove or obfuscate foo.
foo is unused function in code at compile time but is run at run-time from another code.
I have tried:
-keep class blah.A.B;
-keepclassmembers class blah.A.B {
public void foo(String s);
}
etc. but nothing stops Proguard from removing that function.
I do not want proguard to change name of 'foo'. Proguard may change the name of class A or class B but not the function name 'foo'.
Any suggestions?

Almost right. In java bytecode, the $ character separates the names of inner classes and their outer classes (to avoid ambiguities with package names). So, to keep just the method:
-keepclassmembers class blah.A$B {
public void foo(java.lang.String);
}

I have a method 'myClickHandler' referenced only in an xml file.
This
-keepclassmembers class * extends android.app.Activity {
public void myClickHandler(android.view.View );
}
stops it being removed in my application. Perhaps the extends .. will work for you

Related

How to Obfuscated Jar or AAR files

Can someone help me about, obfuscated or give me example to do this?
I created an .aar file and .jar file and put the class of getter and setter that will give value if they access on it.
but the thing in need to put the hidden values that someone will not see what is the value on it.
package com.example.test;
public class MyClass extends privateClass{
String testing;
public MyClass() {
this.testing = getStringExample();
}
public String getTesting() {
return testing;
}
public void setTesting(String testing) {
this.testing = testing;
}
}
and this class must be hide/obfuscated to the other developers if i give my library
package com.example.test;
public class privateClass {
String getStringExample()
{
return "TEST RESULT";
}
}
Note: I tried to put proguard too, and check the library but still they can see my private class, , i tried to use interface and extends the class but still the same,
here is my proguard example:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontwarn ccom.example.test.R*
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class
-keepclassmembers class com.example.test.** { *; }
-keep class com.example.eyefixdata.** {
void set*(***);
void set*(int, ***);
boolean is*();
boolean is*(int);
*** get*();
*** get*(int);
}
Please save my day. hope you help me.
Thanks in advance.
You can move your private classes/interfaces to other packages, e.g. put your privateClass to an internal package package com.example.your.library.internal; to distinguish with your public classes/interfaces.
package com.example.your.library.internal;
public class privateClass {
String getStringExample()
{
return "TEST RESULT";
}
}
And add below line to your proguard configuration
-keep public class com.example.your.library.* { public *; }
Note that you should use single wild char * to NOT obfuscate the internal packages.

How to keep the classes with native functions

Is it possible to tell the ProGuard to completely skip the class if there is native function in it ?
-keepclasseswithmembernames class * { native <methods>; }
Above doesn't work for me because it keeps the class names and the native functions names but obfuscates other members
I'd like to know if it's possible to keep everything in such classes without explicitly specifying every class
Thank you
Is it possible to tell the ProGuard to completely skip the class if there is native function in it
Use these rules:
-keepclasseswithmembers class com.your.packages.** {
native <methods>;
}
-keepclassmembers class com.your.packages.** {
native <methods>;
}
Note, that "completely skipping" class with Proguard is a always bad idea, because it may also indirectly keep some classes, used from code of your kept classes. Instead I recommend the following mode:
-keepclasseswithmembers,allowshrinking,allowoptimization class com.your.packages.** {
native <methods>;
}
-keepclassmembers class com.your.packages.** {
native <methods>;
}
It will allow shrinking and optimizing code of non-native methods, present in the same class.
You can do even better: if your native methods are resolved by names (e.g. they are called something like Java_com_your_packages_methodName), and you don't use RegisterNatives to register them explicitly, you may allow shrinking away unused native methods by removing the second rule, which will leave only
-keepclasseswithmembers,allowshrinking,allowoptimization class com.your.packages.** {
native <methods>;
}
If you want some of class members to be accessible from JNI (e.g. you have some static callback methods to be called from native code), you should keep them explicitly: annotate each such member with specialized annotation and use an annotation-based rule to keep them:
-keepclassmembers,allowoptimization,includedescriptorclasses class com.your.packages.** {
#android.support.annotation.Keep *;
}
You can use your own annotation in place of the one from Android support library — in fact, it is better to use your own in order to avoid interference from existing consumer rules, coming from Android Gradle plugin or other libraries.
In general, I recommend you to reduce the amount of friction between JNI and Java code as much as possible. If you have multiple related Java methods, called from JNI, try to put them together in the same method:
#Keep
public static void callback(int action, String arg) {
switch (action) {
...
}
}
Throw your exceptions from Java code (you was going to reflectively invoke their constructors anyway, so may as well invoke a static helper method instead):
#Keep
public static void throwException(int type, String message) {
switch (type) {
case 0:
throw new BadThingsHappenedException(message);
case 1:
throw new AllHopeIsLostError();
...
}
}
If you have a class, that has to be passed to JNI, try to pass individual fields instead of that class:
public final class DataClass {
int intField;
String stringField;
public void doSomeNativeOperation() {
JNI.doSomeNativeOperation(this);
}
}
public final class JNI {
public static void doSomeNativeOperation(DataClass arg) {
doSomeNativeOperation0(arg.intField, arg.stringField);
}
private static native void doSomeNativeOperation0(int intField, String stringField);
}
If you have a native peer class (a class, closely connected to some structure in native memory), you can keep a pointer to native structure in that class in long field, and pass that field to native methods. Then in native methods cast that long to pointer:
public final class Peer {
long pointer;
// constructor is invoked from JNI
#Keep
protected Peer(long pointer) {
this.pointer = pointer;
}
public void doSomeNativeOperation() {
JNI.doSomeNativeOperation(this);
}
}
public final class JNI {
public static void doSomeNativeOperation(Peer peer) {
doSomeNativeOperation0(peer.pointer);
}
private static native void doSomeNativeOperation0(long pointer);
}
And in native code:
void JNIEXPORT Java_com_your_packages_methodName(JNIEnv* env, jobject type, jlong ptr) {
struct my_struct peer = (struct my_struc*) (intptr_t) ptr;
...
}
These simple rules will allow you to fully obfuscate any huge application using JNI, except for a single small class, that contains all native methods.
I suggest you go even further and push for repackaging classes, referenced by native callbacks.
Instead of
#Keep
public static void callback(YourCustomType arg) {
...
}
You can omit a type of parameter by replacing it with Object:
#Keep
public static void callback(Object arg) {
// this cast won't make much difference in performance, but it makes huge
// difference for Proguard!
YourCustomType instance = (YourCustomType) arg;
...
}
This will let you obfuscate and repackage even types of callback arguments.
Use -keep instead of -keepclasseswithmembernames
-keep class * { native <methods>; }
For more info: https://jebware.com/blog/?p=418
-keep disables all of ProGuard’s goodness. No shrinking, no obfuscation; not for classes, not for members.

Remove LibGDX logs in Android using ProGuard

I have a proguard.cfg file which contains several statements including optimization passes and logs suppression as :
-assumenosideeffects class android.util.Log { *; }
-assumenosideeffects class com.badlogic.gdx.Application {
public static void debug(...);
public static void error(...);
public static void log(...);
}
Calls to Log.* are correctly removed in the final output APK file. But gdx log calls are still in the code. For example I can still see things like that in the output :
Gdx.app.debug("debug()", "^");
Gdx.app.error("error()", "^");
Gdx.app.log("log()", "^");
I also tried to put this part of my config in a proguard-optimize.txt file as I have seen on similar questions and then setting the proper value in project.properties files like this : proguard.config=proguard-optimize.txt:proguard.txt but it doesn't work !
These calls get removed only if I put a general wildcard :
-assumenosideeffects class com.badlogic.gdx.Application {
*;
}
But I don't want to remove calls to other Application's static methods, like add* and get*() ones.
Optimization step is enabled (6 passes).
Gdx.app.debug is not static its an instance method (app is a static field of the Gdx class).
Try:
-assumenosideeffects class com.badlogic.gdx.Application {
public void debug(...);
public void error(...);
public void log(...);
}
Try something like this in your application's code:
Gdx.app.setLogLevel(Application.LOG_NONE);
That will prevent messages from being logged.
Cheers!

EventBus and Proguard: Could not dispatch event

I'm trying to export a signed app and when I run my app i get this exception
Could not dispatch event: class com.achlan.myapp.events.e to subscribing class class com.achlan.myapp.b.d
mapping.txt:
com.achlan.myapp.events.RestResult -> com.achlan.myapp.events.e
com.achlan.myapp.data.DataManager -> com.achlan.myapp.b.d:
I've already added this line to my proguard config:
-keepclassmembers class ** {
public void onEvent*(**); }
Am I missing something in my proguard config?
I also had an issue with EventBus and ProGuard and I contacted the creator of ProGuard/DexGuard and he sent me the following 'workaround' which might help:
-keepclassmembers,includedescriptorclasses class ** { public void onEvent*(**); }
Add includedescriptorclasses to your config file to prevent ProGuard/DexGuard's optimization step to add a suffix to the method name.
Do not confuse the method. I do like this:
If I use
EventBus.getDefault().register(this, "getName", Name.class);
I will do
-keepclassmembers class ** {
public void getName(**);
}
It can work.
If you use a non public (package private) onEvent method you will need to update your progaurd config as follows:
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}

How to keep my test methods with proguard.cfg

For my Android instrumentation test I need a few extra entry point into my classes. Those methods are not used in the actual application. My idea was to start them all with test_ and have a general rule to exclude them from being optimized away. This is how far I got:
-keepclassmembers class com.xxx.**.* {
public ** test_* ();
public ** test_* (**);
public static ** test_* ();
public static ** test_* (**);
}
But it still does not work. public static void test_destroy (final android.content.Context context) and private void dropTables (final SQLiteDatabase db) has just been removed from the code. And I have no idea why.
How is it properly used for wildcard patterns?
The solution is
-keepclassmembers class com.XXX.**.* {
*** test_* (...);
}
Another way to do this is to use an annotation (i.e. guava's #VisibleForTesting) to mark those methods. Then in proguard you can keep all entry points and members with that annotation:
-keep #com.google.common.annotations.VisibleForTesting class *
-keepclasseswithmembers class * {
#com.google.common.annotations.VisibleForTesting *;
}

Categories

Resources