Proguard obfuscation is breaking simplexml
android, proguard, simple-framework
Solution
You already figured out that keeping annotation is a good idea. You may also try to add type parameter to @ElementList annotation - apparently there is a problem with generic type erasure and simplexml needs additional hint about type of elements in the list
you may also play around with -keepattributes Signature, *Annotation*:
The "Signature" attribute is required to be able to access generic types when compiling in JDK 5.0 and higher.
Problem
I am using simplexml in my android project, and everything works fine until I obfuscate the code. Then, errors start pouring in. Part of the XML is as follows: ``` <categories success="true"> <category id="102" caption="Magazin" parent="0" num_mags="114" > <category id="15" caption="Kunst" parent="102" num_mags="13" > <category id="17" caption="Design" parent="15" num_mags="10" ></category> <category id="18" caption="Haute+Couture" parent="15" num_mags="2" > ... ``` I have two classes: CategoryItemList: ``` @Root(name = "categories") public class CategoryItemList { private final List<CategoryItem> mCategoryItems; /** * Create a new category items list. * * @param categoryItems the list of category items */ public CategoryItemList(@ElementList(name = "category", inline = true) final List<CategoryItem> categoryItems) { mCategoryItems = categoryItems; } @ElementList(name = "category", inline = true) public List<CategoryItem> getCategoryItems() { return mCategoryItems; } } ``` and CategoryItem: ``` @Root(name = "category") public class CategoryItem { private final int mId; private final String mCaption; private final int mParent; private final int mNumberOfMagazines; private final ArrayList<CategoryItem> mSubCategoryItems; /** * Creating a new category item. * * @param id the category id * @param caption the name of category * @param parent the parent category * @param numMags the number of magazines from that category */ public CategoryItem(@Attribute(name = "id") final int id, @Attribute(name = "caption") final String caption, @Attribute(name = "parent") final int parent, @Attribute(name = "num_mags") final int numMags, @ElementList(name = "category", inline = true, required = false) final ArrayList<CategoryItem> subCategoryItems) { mId = id; mCaption = caption; mParent = parent; mNumberOfMagazines = numMags; mSubCategoryItems = subCategoryItems; } @Attribute(name = "id") public int getId() { return mId; } @Attribute(name = "caption") public String getCaption() { String categoryName = null; try { categoryName = URLDecoder.decode(mCaption, "UTF-8"); } catch (final UnsupportedEncodingException e) { e.printStackTrace(); } return categoryName; } @Attribute(name = "parent") public int getParentId() { return mParent; } @Attribute(name = "num_mags") public int getNumbersOfMagazines() { return mNumberOfMagazines; } @ElementList(name = "category", inline = true, required = false) public ArrayList<CategoryItem> getSubCategory() { return mSubCategoryItems; } } ``` Now, when I obfuscate the code, if I leave out "-keepattributes Annotation" I get a PersistenceException: Constructor not matched for class. If I include it, I get an "Unable to determine generic type for parameter 1 of constructor" exception, all these at runtime. As you can see, the names are there, and I tried to -keep the entire class holding them, all to no avail. How can I configure Proguard to work with simplexml? EDIT: My proguard.cfg file is as follows: (it's a bit stuffed with all the things I've tried, but this is the current version) ``` -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -printseeds -dontoptimize -keepattributes *Annotation* -keepattributes EnclosingMethod -libraryjars <java.home>/lib/rt.jar (javax/xml/stream/** ) -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 -keepclasseswithmembers class * { native <methods>; } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } -dontwarn android.support.**,de.greenrobot.**,org.simpleframework.xml.** -keep class com.crittercism.**{ *; } -keepclassmembernames class com.crittercism.**{ *; } -keepclasseswithmembers class com.crittercism.**{ *; } -keep class org.simpleframework.**{ *; } -keepclassmembernames class org.simpleframework.**{ *; } -keepclasseswithmembers class org.simpleframework.**{ *; } -keep class crittercism.android.** -keepclassmembers public class com.crittercism.*{ *;} -keep public class database.** { public static <fields>; } -keep class android.support.** -keepclasseswithmembers class android.support.** { *;} -keep class org.simpleframeork.** -keepclasseswithmembers class org.simpleframeork.** { *;} -keep class javax.** -keepclasseswithmembers class javax.** { *;} -keep class com.test.category.** -keepclassmembernames class com.test.category.** { *; } -keepclasseswithmembers class com.test.category.** { *;} -keep class com.test.download.** -keepclassmembernames class com.test.download.** { *; } -keepclasseswithmembers class com.test.download.** { *;} -keep class org.simpleframework.**{ *; } -keep class org.simpleframework.xml.**{ *; } -keep class org.simpleframework.xml.core.**{ *; } -keep class org.simpleframework.xml.util.**{ *; } -keep class org.simpleframework.xml.stream.**{ *; } -keepclassmembers class * implements java.io.Serializable { private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } ```