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();
}
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.
The problems when you use the SimpleXML library and obfuscate the code are the followings:
You have to keep the "Annotations" and "Signatures" of your entities
@Attribute(name = "retcode", required = true) private String _retcode;
You have to keep the SimpleXML Library
- You have to prevent certain blocks of code be remove, for example, if the constructor of an entity is not used, proguard will remove it, but that method can be internally used by Simple XML Library
The proguard.cfg file may to be something like this:
# The following line may be different
-libraryjars <java.home>/lib/rt.jar(java/**,javax/**)
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
# (3)Not remove unused code
-dontshrink
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-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
-keep public class com.android.vending.licensing.ILicensingService
# (2)Simple XML
-keep public class org.simpleframework.**{ *; }
-keep class org.simpleframework.xml.**{ *; }
-keep class org.simpleframework.xml.core.**{ *; }
-keep class org.simpleframework.xml.util.**{ *; }
# (1)Annotations and signatures
-keepattributes *Annotation*
-keepattributes Signature
-keepclasseswithmembernames 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 class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
I use it in my own project and it works ;)
Use the official one from the project Subversion repository.
https://simple.svn.sourceforge.net/svnroot/simple/trunk/download/stream/proguard.pro
Right click your project in eclipse. Go to android -> run Lint.
Lint has the ability to check for proguard misconfigurations and may pick up, and explain your error.
I kept getting the following errors:
can't find referenced class javax.xml.stream.XMLEventReader
can't find referenced class javax.xml.stream.events.XMLEvent
This is because these are part of the Java runtime (rt.jar
) but not part of the Android runtime (android.jar
), so ProGuard warns that something might be broken. This isn't actually a problem, so we can do the following:
-dontwarn javax.xml.stream.events.**
Combined with the answer of zmicer, I get the following
-dontwarn javax.xml.stream.events.**
-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
-keepclassmembers class * {
@org.simpleframework.xml.* *;
}
Try adding this to your proguard file:
-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
-keepclassmembers class * {
@org.simpleframework.xml.* *;
}
This fixed it for me.
This exact addition to the proguard file worked for me:
-dontwarn javax.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
-keepclassmembers class * {
@org.simpleframework.xml.* *;
}
来源:https://stackoverflow.com/questions/12163250/proguard-obfuscation-is-breaking-simplexml