Запутывание Proguard ломает симплекс

Я использую 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: Конструктор не соответствует классу.

Если я включу его, я получу исключение "Невозможно определить универсальный тип для параметра 1 конструктора", все это во время выполнения.
Как видите, имена есть, и я пытался держать весь класс, держащий их, но все безрезультатно.

Как я могу настроить Proguard для работы с simplexml?

РЕДАКТИРОВАТЬ: Мой файл 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();
}

7 ответов

Решение

Вы уже поняли, что держать аннотацию - хорошая идея. Вы также можете попытаться добавить параметр типа в аннотацию @ElementList - очевидно, существует проблема с стиранием универсального типа, и симплексм требуется дополнительная подсказка о типе элементов в списке.

вы также можете поиграть с -keepattributes Signature, *Annotation*:

Атрибут "Signature" необходим для доступа к универсальным типам при компиляции в JDK 5.0 и выше.

При использовании библиотеки SimpleXML и запутывании кода возникают следующие проблемы:

  1. Вы должны сохранить "Аннотации" и "Подписи" ваших лиц

    @Attribute(name = "retcode", обязательный = true) private String _retcode;

  2. Вы должны сохранить библиотеку SimpleXML

  3. Вы должны предотвратить удаление определенных блоков кода, например, если конструктор объекта не используется, 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 *;
}

Я использую его в своем собственном проекте, и он работает;)

Используйте официальный репозиторий проекта Subversion.

https://simple.svn.sourceforge.net/svnroot/simple/trunk/download/stream/proguard.pro

Щелкните правой кнопкой мыши ваш проект в затмении. Перейти на Android -> запустить Lint.

У Lint есть возможность проверить неправильную конфигурацию Proguard, и он может подобрать и объяснить вашу ошибку.

Я продолжал получать следующие ошибки:

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.* *;
}

Попробуйте добавить это в ваш файл 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.* *;
}

Это исправило это для меня.

Это точное дополнение к файлу 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.* *;
}
Другие вопросы по тегам