【问题标题】:Proguard obfuscation is breaking simplexmlProguard 混淆正在破坏 simplexml
【发布时间】:2012-08-23 04:43:03
【问题描述】:

我在我的 android 项目中使用 simplexml,在我混淆代码之前一切正常。然后,错误开始涌入。

部分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 not match for class。

如果我包含它,我会在运行时收到“无法确定构造函数参数 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();
}

【问题讨论】:

    标签: android proguard simple-framework


    【解决方案1】:

    您已经发现保留注释是个好主意。您也可以尝试将类型参数添加到 @ElementList 注释 - 显然泛型类型擦除存在问题,simplexml 需要有关列表中元素类型的额外提示

    你也可以玩弄 -keepattributes Signature, *Annotation*:

    “签名”属性是访问通用属性所必需的 在 JDK 5.0 及更高版本中编译时的类型。

    【讨论】:

    • 起初我很难理解你的意思,但现在我完全理解了,这个答案解决了我的问题。
    • 确实有效。最后我的声明如下所示:@ElementList(inline=true, type=Myclass.class)
    【解决方案2】:

    使用SimpleXML库和混淆代码时的问题如下:

    1. 您必须保留实体的“注释”和“签名”

      @Attribute(name = "retcode", required = true) 私有字符串_retcode;

    2. 您必须保留 SimpleXML 库

    3. 您必须防止删除某些代码块,例如,如果不使用实体的构造函数,proguard 将删除它,但该方法可以在 Simple XML Library 内部使用

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

    我在自己的项目中使用它并且它有效;)

    【讨论】:

      【解决方案3】:

      使用来自项目 Subversion 存储库的官方版本。

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

      【讨论】:

        【解决方案4】:

        在 Eclipse 中右键单击您的项目。转到 android -> 运行 Lint。

        Lint 有能力检查 proguard 的错误配置,并且可能会发现并解释您的错误。

        【讨论】:

        • 我发现了一个 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.**
        

        Source

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

        【讨论】:

        • 99% 这个,但对于 'dontwarn' 和 'keepattributes' 有一点不同。 -dontwarn javax.xml.stream.** -keepattributes ElementList, Root, Annotation
        【解决方案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.* *;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-07-20
            • 2013-09-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多