Обфускация Proguard ломает simplexml
Я использую simplexml в моем проекте Android, и все работает нормально, пока я не запутываю код. Затем начинаются ошибки.
Часть XML выглядит следующим образом:
<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" >
...
У меня есть два класса: 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;
}
}
и 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;
}
}
Теперь, когда я запутываю код, если я не упоминаю "-keepattributes Annotation", я получаю PersistenceException: Constructor не соответствует классу.
Если я включу его, я получаю исключение "Невозможно определить общий тип для параметра 1 конструктора", все это во время выполнения.
Как вы можете видеть, имена есть, и я попытался -подготовьте весь класс, держащий их, все безрезультатно.
Как настроить Proguard для работы с simplexml?
EDIT: Мой файл proguard.cfg выглядит следующим образом: (он немного заполнен всеми вещами, которые я пробовал, но это текущая версия)
-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();
}
Ответы
Ответ 1
Вы уже поняли, что аннотация - хорошая идея. Вы также можете попытаться добавить параметр типа в аннотацию @ElementList - видимо, существует проблема с стиранием типа generic, а simplexml нуждается в дополнительном намеке на тип элементов в списке
вы также можете поиграть с -keepattributes Signature, * Annotation *:
Атрибут "Подпись" необходим для доступа к родовому типы при компиляции в JDK 5.0 и выше.
Ответ 2
Использовать официальное из репозитория Subversion.
https://simple.svn.sourceforge.net/svnroot/simple/trunk/download/stream/proguard.pro
Ответ 3
Проблемы при использовании библиотеки SimpleXML и обфускации кода следующие:
-
Вы должны хранить "Аннотации" и "Подписи" ваших сущностей
@Attribute (name = "retcode", required = true)
private String _retcode;
-
Вы должны хранить библиотеку SimpleXML
- Вы должны предотвратить удаление определенных блоков кода, например, если конструктор объекта не используется, proguard удалит его, но этот метод может быть внутренне использован в библиотеке Simple XML
Файл proguard.cfg может быть примерно таким:
# 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 *;
}
Я использую его в своем собственном проекте, и он работает;)
Ответ 4
Щелкните правой кнопкой мыши ваш проект в eclipse. Перейдите в android → запустите Lint.
Lint имеет возможность проверить неправильные конфигурации proguard и может забрать и объяснить вашу ошибку.
Ответ 5
Я продолжал получать следующие ошибки:
can't find referenced class javax.xml.stream.XMLEventReader
can't find referenced class javax.xml.stream.events.XMLEvent
Это связано с тем, что они являются частью среды выполнения Java (rt.jar
), но не являются частью среды выполнения Android (android.jar
), поэтому ProGuard предупреждает, что что-то может быть нарушено. На самом деле это не проблема, поэтому мы можем сделать следующее:
-dontwarn javax.xml.stream.events.**
Источник
В сочетании с ответом zmicer я получаю следующее
-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.* *;
}
Ответ 6
Попробуйте добавить это в свой файл proguard:
-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.* *;
}
Это исправило это для меня.
Ответ 7
Это точное дополнение к файлу proguard работало для меня:
-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.* *;
}