Proguard 混淆正在破坏 simplexml
Posted
技术标签:
【中文标题】Proguard 混淆正在破坏 simplexml【英文标题】:Proguard obfuscation is breaking 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();
【问题讨论】:
【参考方案1】:您已经发现保留注释是个好主意。您也可以尝试将类型参数添加到 @ElementList 注释 - 显然泛型类型擦除存在问题,simplexml 需要有关列表中元素类型的额外提示
你也可以玩弄 -keepattributes Signature, *Annotation*:
“签名”属性是访问通用属性所必需的 在 JDK 5.0 及更高版本中编译时的类型。
【讨论】:
起初我很难理解你的意思,但现在我完全理解了,这个答案解决了我的问题。 确实有效。最后我的声明如下所示:@ElementList(inline=true, type=Myclass.class)
【参考方案2】:
使用SimpleXML库和混淆代码时的问题如下:
您必须保留实体的“注释”和“签名”
@Attribute(name = "retcode", required = true) 私有字符串_retcode;
您必须保留 SimpleXML 库
您必须防止删除某些代码块,例如,如果不使用实体的构造函数,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.* *;
【讨论】:
以上是关于Proguard 混淆正在破坏 simplexml的主要内容,如果未能解决你的问题,请参考以下文章
在构建“maven-plugin”包时如何使用 Proguard 混淆?
使用 Proguard 混淆 ActionBarSherlock