How to not obfuscate interface methods & its parameters using Proguard in Android? - android

I have the following code:
public class MyClass {
public void method1(Integer marks) {
}
private String method3(String name){
}
public interface interface1 {
void method4(Integer ID);
void method5(Integer rate, boolean status);
}
}
I have used progaurd-rules.pro
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keepparameternames
-keep public class *
-keepclassmembers public class *{
public *;
}
-keep public interface packageName.MyClass$interface1 { *; }
Obfuscated code as below:
public class MyClass {
public void method1(Integer marks) {
}
private String a(String var1){
}
public interface interface1 {
void method4(Integer var1);
void method5(Integer var1, boolean var2);
}
}
I want the interface methods variables (ID, rate & status) not to obfuscate. i.e as below
public interface interface1 {
void method4(Integer ID);
void method5(Integer rate, boolean status);
}
How can it be possible?

You could keep method's arguments by adding extra flags to -keepattributes. They look like this:
-keepattributes LocalVariableTable,LocalVariableTypeTable
Unfortunately, this keeps arguments from obfuscation not only in the interface you want, but in the entire project. Maybe that's fine for you.
If you're using a default proguard configuration shipped along with Android SDK then you could also use a special annotation to prevent some classes from obfuscation. Check it out.

public interface SSOListener {
void sendDataToAnalytics(String event, JSONArray object);
}
// In my case JsonArray was obfuscated.
Solution :
-keep class org.json.JSONArray**, ** {
protected <fields>;
public <fields>;
<methods>;
}

-keepattributes LocalVariableTable,LocalVariableTypeTable
The above keepattributes didn't work for me. However -keepparameternames did. I added this to the internal Proguard config that our Android Library uses. The other non keot classes still have their params obfuscated.
Note: I'm using R8 to actually obfuscate which is the default when using the Android Gradle Plugin since 3.4.0 also we are enforcing source and target compatibility to 1.8 (due to unrelated okhttp dependency)

ProGuard uses the naming convention of Java bytecode, as seen in class file names and stacktraces. Therefore:
-keep public interface com.somepackage.SomeClass$someInterface {*;}
In case if your interface is not public.
-keep interface com.somepackage.SomeClass$someInterface {*;}.

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.

Android apk not connecting to Azure server after using proguard

I have been looking to a solution to this problem, i have tried many proguard configurations without success.
The app runs perfectly until I make the release version with proguard.
I am getting the error:
"java.lang.IllegalArgumentException:The class representing the mobile serviceTable must have a single id property defined" while assigning the class
I belive that is caused by the class of the table that i am trying to reach, having its variable 'id' name changed.
I have the folowing:
public class User {
public String id;
public String nickname;
public String phone;
}
and the connection is made with:
mClient.getTable(User.class).where().field("nickname")
.eq(nick).execute(new TableQueryCallback<User>() {....
the proguard config file is:
-keep class com.microsoft.azure.storage.table.** { *; }
-dontwarn com.fasterxml.jackson.core**
-keep class com.microsoft.windowsazure.mobileservices.** { *; }
-dontwarn android.os.**
-dontwarn com.microsoft.windowsazure.mobileservices.RequestAsyncTask
##---------------from here is the part that i have modified a lot of times -
-keepattributes Signature
-keepattributes *Annotation*
-keep public class com.company.app.User.** { *; }
-keepclassmembers public class com.company.app.User.** { *; }
I have tried many modifications for hours without success.
I followed this and this among many others.
Can you please help me?
Thanks
EDIT: solved. Just remove the .** after User in the proguard file. Leave it like this:
-keep public class com.company.app.User { *; }
-keepclassmembers public class com.company.app.User { *; }
solved. Just remove the .** after User in the proguard file. Leave it like this:
-keep public class com.company.app.User { *; }
-keepclassmembers public class com.company.app.User { *; }

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*(**);
}

Proguard and HashMap<String, MyObject>

I'm developing some apis for android as a library project and I'd like to export them as an obfuscated jar.
I have various classes but the only public entities are:
MyInterface: An interface listing some methods that the user will have to implement;
MyUtilities: A class with some static methods;
MySingleton: A Singleton (implemented as an enum with a single INSTANCE);
MyObject: A class implementing a particular object I need to handle;
I am new with Obfuscation so I followed some tutorials and read android/proguard docs.
I successfully created a jar from my project and used it in an external application.
I also successfully obfuscated all the non-public classes (so every class apart from the above-mentioned) and it still continue working.
Now my problem:
One of the methods specifed in MyInterface is
public void getObject(HashMap<String, MyObject>);
before obfuscation the user could add implements MyInterface to his activity/class and (auto) generate the implementation of the the interface methods, in particular:
#Override
public void getObject(HashMap<String, MyObject> hashmap){
// User implementation
}
After having obfuscated the jar, when I add implements MyInterface to a user activity and auto-generate the methods implementations, I get:
#Override
public void getObject(HashMap hashmap){
// User implementation
}
So without HashMap types. I honestly don't know why this happens..
I expected to see also the HashMap types because both String and MyObject are kept.
It still works also without HashMap types, but I have to cast it to a Hasmap<String, MyObject>
This is my proguard conf file (generated by the proguard gui tool):
-injars inAPIs.jar
-outjars 'obfAPIs.jar'
-libraryjars /My/android/SDK/Path/platforms/android-15/android.jar
-libraryjars /My/android/SDK/Path/tools/support/annotations.jar
-libraryjars /My/android/SDK/Path/add-ons/addon-google_apis-google-15/libs/effects.jar
-libraryjars /My/android/SDK/Path/add-ons/addon-google_apis-google-15/libs/maps.jar
-libraryjars /My/android/SDK/Path/add-ons/addon-google_apis-google-15/libs/usb.jar
-overloadaggressively
-keep class my.package.MyObject {
public <fields>;
public <methods>;
}
-keep public class my.package.MyUtilities {
public <fields>;
public <methods>;
}
-keep interface my.package.MyInteface {
public <fields>;
public <methods>;
}
-keep public class my.package.MySingleton {
public <fields>;
public <methods>;
}
-keep,allowshrinking public class my.package.MyInterface {
public <fields>;
public <methods>;
}
-keep,allowshrinking public class my.package.MyObject
-keep,allowshrinking public class my.package.MyUtils
-keep,allowshrinking public enum my.package.MySingleton {
public <fields>;
public <methods>;
}
According to Proguard docs, you may want to add the following option:
-keepattributes Signature
Quoting their docs:
The "Signature" attribute is required to be able to access generic
types when compiling in JDK 5.0 and higher.

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