Proguard - PersistenceException: Constructor not matched for class
Asked Answered
M

2

9

I am using retrofit2.0 in my app with simpleframework.xml library.

The problem is when I run the app without proguard it works fine however when I run proguard I get the following Error in logs.

E/ERROR: java.lang.RuntimeException: org.simpleframework.xml.core.PersistenceException: Constructor not matched for class A

The class A has no/default constructor which should work. Still I added a No Argument Constructor. But that didn't rectify the issue.

Class A

@Root(name = "data",strict = false)
public class A {
    @Element(name = "baseurl",required = false)
    private String baseURl;
    @Element(name = "country_code")
    private String country_code;

    //  Setters and getters
}

As you can see there is no constructor (Adding the default empty constructor keeps the issue). So default No Argument Constructor should work just as well. However I tried with the following constructor and this removes the error.

public A(@ELement(name = "baseurl") String baseUrl,
         @Element(name = "country_code") String country_code) {    // Add all the elements from the xml in the constructor i.e. if a new element is added a new constructor would have to be written.
    baseURl = baseUrl;
    this.country_code = country_code;
}

But I have too many files to change if I want to do it this way. Besides a constructor requiring all the values mapped shouldn't be required. I have quite a few classes which host more than 50 member variables (I simplified the example class to include only two member variables). This class contains about 30 and code would've been simply too long to post here.

The thing is I have loads of classes working on the assumption of No Argument constructor for each class.

Simply adding constructors for all is not feasible.

My proguard-rules.pro (with only relevant lib obfuscation rules).

#-keepattributes *Annotation*

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }

-dontwarn com.bea.xml.stream.**
-dontwarn org.simpleframework.xml.stream.**
-keep class org.simpleframework.xml.**{ *; }
-keepclassmembers,allowobfuscation class * {
    @org.simpleframework.xml.* <fields>;
    @org.simpleframework.xml.* <init>(...);
}

It might be worth noting that before this Error I was getting

E/ERROR: java.lang.RuntimeException: org.simpleframework.xml.core.ElementException: Element 'version' does not have a match in class A at line 1

Solved that by adding 'name' argument in @Element Annotation. So one of the reasons I'm reluctant to change all the files is what if another Error creeps up.

EDIT 1: So after 2 days of searching for a solution I gave up and finally added constructors to all the classes. The thing is the library calls constructor for only the available xml-tags. Say for the above class A if only country_code was available in the xml

<xml>
    <data>
        <country_code>PK</country_code>
    </data>
</xml>

Then I'd need a constructor with only one argument of country_code to make it work

public A(@Element(name = "country_code") String country_code) {
    this.country_code = country_code;
}

Which makes the found solution unusable.

EDIT 2: Found a workaround! Keeping the POJO classes in the proguard rules fixes this error. But I would rather not keep these classes.

And so I'm keeping this question open at-least for now or until someone can tell me why I should keep these files.

Mate answered 21/11, 2017 at 7:33 Comment(5)
I am also facing same problem and I am unable to solve itSouthey
Can you share your entire xml? I can check it on my end.Suspend
Also can you update if your application works without proguard and with release buildSuspend
As long as the proguard's not enabled the app works fine. BTW I have found a solution I don't like: keep all the POJO objects (in proguard). I really don't like it! I am still open to a solution that fixes this without keeping all those classes.Mate
@Southey see the update.Mate
R
2

I guess that your problem is that you are not keeping any attributes and that obviously depends in which attributes you are using. In my case, this is how I dealt with it, let me know if it works for you:

## https://square.github.io/retrofit/ ##
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
 -keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

## Simple XML ##
-dontwarn org.simpleframework.xml.stream.**
-keep public class org.simpleframework.** { *; }
-keep class org.simpleframework.xml.** { *; }
-keep class org.simpleframework.xml.core.** { *; }
-keep class org.simpleframework.xml.util.** { *; }

-keepattributes ElementList, Root, *Annotation*

-keepclassmembers class * {
    @org.simpleframework.xml.* *;
}
Route answered 28/6, 2018 at 13:16 Comment(2)
Doesn't work, still getting the same exception in logs. BTW there is no need to keep retrofit2.Mate
did you also keep the attribute Exceptions ?Route
B
0

try adding these below lines in your proguard file. It should solve your problem

-dontnote retrofit2.Platform
-keepattributes Signature
-keepattributes Exceptions

and remove these below lines

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
Bawd answered 4/7, 2018 at 10:5 Comment(1)
@abbas can you check this.Bawd

© 2022 - 2024 — McMap. All rights reserved.