Android上的ProGuard和Gson(类CastException)

qyuhtwio  于 2022-11-06  发布在  Android
关注(0)|答案(8)|浏览(205)

我在使用Gson和ProGuard时遇到了麻烦。我有一个简单的对象,当我解析tojson,保存到sqllite并从数据库读回以便将json加载回我的对象时,我得到了一个java. lang. classcastexception。如果我不使用ProGuard,一切都很好。
我已经验证了发送到数据库和从数据库获取的json字符串是相同的。当它从json转换时不会抛出异常,而是当我试图访问对象时抛出异常。
下面是我的简单对象:

public class ScanLog extends ArrayList<SingleFrame>
{
     private static final long serialVersionUID = 1L;

     public ScanLog()
     {

     }
}

public final class SingleFrame 
{
    public int Position;
    public int Time;
    public Map<Integer,String> MainDataMap;
    public Map<Integer,String> DataMap;

    public SingleFrame(int position, int time, 
                    Map<Integer,String> mainDataMap, Map<Integer,String> dataMap)
    {
        this.Position = position;
        this.Time = time;
        this.MainDataMap = mainDataMap;
        this.DataMap = dataMap;
    }

}

我的应用程序的所有其他方面都很好,但是proguard的一些东西导致了这种情况的发生...我试过proguardidercfg中的各种-keep命令,但是我不确定我所做的是正确的。
编辑-添加程序配置文件

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-dontshrink
-dontoptimize

-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

# keep all classes that might be used in XML layouts

-keep public class * extends android.view.View
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.Fragment

# keep all classes

-keep public class *{
public protected *;
}

# keep all public and protected methods that could be used by java reflection

-keepclassmembernames class * {
    public protected <methods>;
}

-keepclasseswithmembernames class * {
    native <methods>;
}

-keep public class org.scanner.scanlog.SingleFrame

-keepclassmembers class org.scanner.scanlog.ScanLog { 
        private <fields>; 
        public <fields>; 
}

-keepclassmembers class org.scanner.scanlog.SingleFrame { 
        private <fields>; 
        public <fields>; 
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames 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**CompatHoneycomb
-dontwarn org.htmlcleaner.*

# -keep class android.support.v4.**{ *; }

编辑-好的,我在我的应用程序中成功设置了ACRA,非常棒的功能!下面是堆栈跟踪:

java.lang.ClassCastException: java.lang.Object
    at org.scanner.activity.ReaderMainActivity.AdvanceScanLog(SourceFile:1499)
    at org.scanner.activity.r.onProgressChanged(SourceFile:271)
    at android.widget.SeekBar.onProgressRefresh(SeekBar.java:89)
    at android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:507)
    at android.widget.ProgressBar.refreshProgress(ProgressBar.java:516)
    at android.widget.ProgressBar.setProgress(ProgressBar.java:565)
    at android.widget.AbsSeekBar.trackTouchEvent(AbsSeekBar.java:337)
    at android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:292)
    at android.view.View.dispatchTouchEvent(View.java:3932)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1784)
    at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1157)
    at android.app.Activity.dispatchTouchEvent(Activity.java:2181)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1759)
    at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2336)
    at android.view.ViewRoot.handleMessage(ViewRoot.java:1976)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:143)
    at android.app.ActivityThread.main(ActivityThread.java:4263)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    at dalvik.system.NativeStart.main(Native Method)
u59ebvdq

u59ebvdq1#

有关推荐的proguard配置文件的最新版本,请参见gson提供的android proguard示例,网址为:https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg

wb1gzix0

wb1gzix02#

配置中的这些设置在我的一个应用程序中适用:


# Add the gson class

-keep public class com.google.gson

# Add any classes the interact with gson

-keep class com.someapp.android.models.ChatModel { *; }
-keep class com.someapp.android.models.FeedModel { *; }

# Add the path to the jar

-libraryjars /Users/someuser/Documents/workspace/someapp/lib/gson-1.7.1.jar

希望这对你有帮助。

z4bn682m

z4bn682m3#

在Gson项目中应用Android example中的更改对我很有效
所需的行为:

-keepattributes Signature
-keep class sun.misc.Unsafe { *; }

# and keeping the classes that will be serialized/deserialized
uxhixvfz

uxhixvfz4#

我知道最初的问题是通过采取不同的方法解决的,但我在Android上使用flexjson和Proguard时遇到了一个非常类似的问题,我已经解决了它,以防有人自己遇到它。
当从JSON转换回包含一些ArrayLists的值对象时,我会得到相同的ClassCastException。我基本上是通过启用模糊处理,但关闭模糊处理的所有部分(-keep everything,-keepclassmembers everything和-keepattributes everything),然后反向工作,一次启用一点。
结果;保留整个flexjson库:

-keep class flexjson**
--keepclassmembers class flexjson**{
   *;
}

Annotation 属性:

-keepattributes Signature, *Annotation*

在那之后,我能够在我的应用程序的一个受保护的发布版本中使用flexjson库而没有发生任何事件。

gkn4icbw

gkn4icbw5#

使用proguard的Model类出现错误如果您查看
GSON Proguard您将找到一条线


# Application classes that will be serialized/deserialized over Gson

-keep class com.google.gson.examples.android.model.**{ *; }

用你的model包替换com.google.gson.examples.android.model.同样在我的例子中我用-keep class com.consumer.myProject.model.**{ *; }替换了它
其余的我这样复制

0qx6xfy6

0qx6xfy66#

因此,我最终放弃了Gson库,并没有使用gson将对象转换为json,而是在应用程序中创建了一个自定义类来序列化和反序列化对象,并以这种方式存储数据。
我总体上更高兴,尽管这花了我超过12个小时的时间来弄清楚。显然,PROGUARD和gson一定不会太喜欢对方吧?

作为不必使用GSON的一个巨大的额外好处,我注意到通过删除GSON库,我的应用程序大小减少了一半。我的应用程序原来是577kb,删除gson库后现在只有260kb。

wljmcqd8

wljmcqd87#

看起来您确实保留了类中的所有内容(字段、方法和类本身),但为了确保您可以将-printseeds outputfile.txt添加到proguard.cfg文件中,以验证模糊处理完成后proguard是否确实保留了您需要的所有内容。
顺便说一句,您可能会考虑添加一些类似ACRA or Android Remote stacktrace的东西,让您可以检查构建的应用程序上的堆栈跟踪。

eimct9ow

eimct9ow8#

为了补充所有其他的答案,如果你们到达这里,这意味着你想模糊你的代码,并使用Gson。
如果在最后,您选择-keep class您的示例,这意味着这些Gson类将不会过时,并且此解决方案(甚至Gson一般来说,对您来说不是最佳解决方案)。
在这种情况下,我建议您自己序列化类,并将它们存储在See @Jessy's answer中。

相关问题