Proguard Error- NoSuchMethodException in EnumTypeInt - android

I have an interface named EnumInt and using it as below
case EnumInt:
#SuppressWarnings("unchecked")
Class<? extends EnumInt> enumType = (Class<? extends EnumInt>) field.getType();
Method enumStaticMethod = enumType.getMethod("fromVal", int.class);
Object enumInstance = enumStaticMethod.invoke(null, object);
field.setAccessible(true);
field.set(entity, enumInstance);
break;
I have already keep whole package in progaurd but still getting
-keep class abc.cde.** { *; } // package having EnumInt interface and other files
java.lang.NoSuchMethodException: fromVal [int]
at java.lang.Class.getMethod(Class.java:2068)
at java.lang.Class.getMethod(Class.java:1690)
I have tried Keeping EnumInt Interface, All native method, fields in proguard for preventing obfuscation but still unable to remove error.
Please note without proguard it is working fine.
Please help. Thanks in advance. Problem is specific to Enums.

Answering my own question for the future readers.
I was using another enum implementing EnumInt like below
public static enum CustomeType implements EnumInt {
ALL(MSG_TYPE_ALL),
IN(MSG_TYPE_IN),
OUT(MSG_TYPE_OUT),
int val;
private CustomeType(int val) {
this.val = val;
}
public static CustomeType fromVal(int val) {
for (CustomeType messageType : values()) {
if (messageType.val == val) {
return messageType;
}
}
return null;
}
}
and i was missing the proguard obfuscation to prevent this enum.
Solution
Below line in proguard
-keep public enum abc.cde.a.CustomeType$** {
**[] $VALUES;
public *;
}

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 not obfuscate interface methods & its parameters using Proguard in 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 {*;}.

Proguard causing RuntimeException (Unmarshalling unknown type code) in Parcelable class

I get this exception if I leave my app and open it after some time. My main activity consist of a ViewPager with three different fragments. I also do some stuff in Application class which I don't think relates to the problem.
This is the exception:
RuntimeException (#Parcel:readValue:2065) {Unable to start activity
ComponentInfo{com.emu/com.emu.ActivityMain}:
java.lang.RuntimeException: Parcel android.os.Parcel#419526d0:
Unmarshalling unknown type code 2131361816 at offset 332}
I see lots of this exception happening on users phones in google analytics. All of them are the same except number after readValue and hex number after # which are 2065 and 419526d0 in above exception.
The exception doesn't point any line of code. I searched about this and it seems it relates to wrong writing to parcel. Although I don't have any parcel in my MainActivity. I don't know what may cause this.
--- EDIT ------------------------------------------------------------------------
I reproduced the exception. It happens when App is leaved with home button, and got cleared from memory after opening some other memory consuming app. When starting it again exception happens. Till now I was thinking that closing app from recent task or from DDMS have the same effect but apparently it doesn't.
#EricWoodruf helped me to find that parcel is somewhere in imported library. I find the parcel in PagerSlidingTabStrip which I had downloaded from web. This is the parcel related code, but I don't really know what is wrong here:
public class PagerSlidingTabStrip extends HorizontalScrollView
{
#Override
public void onRestoreInstanceState(Parcelable state)
{
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
#Override
public Parcelable onSaveInstanceState()
{
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
static class SavedState extends BaseSavedState
{
int currentPosition;
public SavedState(Parcelable superState)
{
super(superState);
}
private SavedState(Parcel in)
{
super(in);
currentPosition = in.readInt();
}
#Override
public void writeToParcel(Parcel parcel, int flags)
{
super.writeToParcel(parcel, flags);
parcel.writeInt(currentPosition);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
{
#Override
public SavedState createFromParcel(Parcel in)
{
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size)
{
return new SavedState[size];
}
};
}
}
---- EDIT 2 -----------------------------------------------------------------
After I could reproduce the problem I found out that this happens only in Artifact which is signed by my key and proguarded! The debug one doesn't have the problem!
I disabled proguard on artifact and it works like a charm without the exception. But, what proguard do that result in this problem?
I tried adding this to proguard but didn't work:
-keep class toolfa.android.base.ui.PagerSlidingTabStrip { *; }
-dontwarn toolfa.android.base.ui.PagerSlidingTabStrip
this is my current proguard config:
-keep class com.nineoldandroids.** { *; }
-dontwarn com.nineoldandroids.**
-keep class ir.adad.** { *; }
-dontwarn ir.adad.**
-keep class android.support.v4.** { *; }
-dontwarn android.support.v4.**
-keep class toolfa.android.base.ui.PagerSlidingTabStrip { *; }
-dontwarn toolfa.android.base.ui.PagerSlidingTabStrip
-keep class toolfa.android.sega.ActivityEmulator { *; }
-keep class toolfa.android.sega.Zip { *; }
As we found out in the comments, the exception was the result of ProGuard obfuscating Parcelable classes. The fix is to include this snippet in the ProGuard configuration file:
-keepclassmembers class * implements android.os.Parcelable {
static ** CREATOR;
}
I guess the specific problem here was that ProGuard obfuscated the CREATOR member of PagerSlidingTabStrip, but since SavedState is a subclass of View.BaseSavedState, the superclass member was still available (this is why it didn't throw a BadParcelableException), but that uses a different data structure and didn't write the custom attributes into the Parcel output.
There is a recommended configuration for Android applications available in the ProGuard Manual, with detailed explanation about entries. For example, it includes that you should keep all class names used in the manifest or other XML files.

ProGuard: Keep inner static class but rename parent class

I want to know if its possible to keep the name of a public static inner Class but renaming the parent classname.
My code looks like this:
public class MyDao extends AbstractDao {
public static final String TABLENAME = "BOX_DOWNLOAD";
public static class Properties {
public final static Property ID = new Property(0, Long.class, "ID", true, "ID");
public final static Property Name = new Property(1, String.class, "name", false, "NAME");
public final static Property Done = new Property(2, Boolean.class, "done", false, "DONE");
// SOME MORE CONSTANTS
};
// SOME CODE WHICH CAN BE OBFUSCATED
}
I want ProGuard to replace:
MyDao (the className)
the PROPERTIES' variables (ID, Name, Done)
I want ProGuard NOT to replace:
TABLENAME (variable name)
PROPERTIES (className only)
I tried this
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static <fields>;
public static class *;
}
But this is not working. The classNames are not obfuscated.
// EDIT
I forgot to say that there are several classes like MyDao. Eg. MyDao1, MyDao2, etc.
I want to use wildcards.
Cfr. ProGuard manual > Usage > Keep Options
-keepclassmembers class de.greenrobot.dao.MyDao {
String TABLENAME;
}
-keep class de.greenrobot.dao.MyDao$Properties
Update: When keeping the name "MyDao$Properties", the current version of ProGuard appears to keep the name "MyDao" as well (even if the InnerClasses attribute is not preserved). This is somewhat more conservative than strictly necessary.
I have made following scripts, which works for me.
-keep class my.dao.package.*$Properties {
public static <fields>;
}
-keepclassmembers class my.dao.package.** {
public java.lang.String TABLENAME;
}
I have used wildcard for inner classes, which worked.

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