Java Joda时间库无法在启用Proguard的Android 5上运行

Java Joda时间库无法在启用Proguard的Android 5上运行,java,android,proguard,jodatime,Java,Android,Proguard,Jodatime,这个问题只发生在Android 5中。应用程序在此点崩溃,我创建了一个新的DateTime对象,如: mStartTime = new DateTime(DateTimeZone.getDefault()); 事故报告如下: java.lang.AbstractMethodError: abstract method "long boq.f()" at org.joda.time.chrono.BasicYearDateTimeField.(BasicYearDateTimeField.

这个问题只发生在Android 5中。应用程序在此点崩溃,我创建了一个新的
DateTime
对象,如:

mStartTime = new DateTime(DateTimeZone.getDefault());
事故报告如下:

java.lang.AbstractMethodError: abstract method "long boq.f()"
   at org.joda.time.chrono.BasicYearDateTimeField.(BasicYearDateTimeField.java:46)
   at org.joda.time.chrono.BasicChronology.assemble(BasicChronology.java:273)
   at org.joda.time.chrono.GregorianChronology.assemble(GregorianChronology.java:197)
   at org.joda.time.chrono.AssembledChronology.setFields(AssembledChronology.java:323)
   at org.joda.time.chrono.AssembledChronology.(AssembledChronology.java:102)
   at org.joda.time.chrono.BasicChronology.(BasicChronology.java:131)
   at org.joda.time.chrono.BasicGJChronology.(BasicGJChronology.java:75)
   at org.joda.time.chrono.GregorianChronology.(GregorianChronology.java:153)
   at org.joda.time.chrono.GregorianChronology.getInstance(GregorianChronology.java:133)
   at org.joda.time.chrono.GregorianChronology.getInstance(GregorianChronology.java:99)
   at org.joda.time.chrono.GregorianChronology.(GregorianChronology.java:70)
   at org.joda.time.chrono.GregorianChronology.getInstanceUTC(GregorianChronology.java:80)
   at org.joda.time.chrono.ISOChronology.(ISOChronology.java:59)
   at org.joda.time.base.BaseDateTime.(BaseDateTime.java:73)
   at org.joda.time.DateTime.(DateTime.java:184)
   at com.znapo.photo_sharer.asynctasks.GetAllSessionTask.onPostExecute(GetAllSessionTask.java:149)
   at com.znapo.photo_sharer.asynctasks.GetAllSessionTask.onPostExecute(GetAllSessionTask.java:1)
   at android.os.AsyncTask.finish(AsyncTask.java:636)
   at android.os.AsyncTask.access$500(AsyncTask.java:177)
   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:135)
   at android.app.ActivityThread.main(ActivityThread.java:5254)
   at java.lang.reflect.Method.invoke(Method.java)
   at java.lang.reflect.Method.invoke(Method.java:372)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
我的完整Proguard配置文件是:

-dontwarn org.apache.**
-dontwarn com.google.android.**
-dontskipnonpubliclibraryclassmembers

##---------------Begin: proguard configuration common for all Android apps ----------
-optimizationpasses 5
-dontpreverify
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-allowaccessmodification
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-repackageclasses ''

-keep public class * extends android.app.Activity
#-keep public class * extends android.support.v7.app.ActionBarActivity
-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
-dontnote com.android.vending.licensing.ILicensingService

# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    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();
}

# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
    native <methods>;
}

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

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

# Preserve static fields of inner classes of R classes that might be accessed
# through introspection.
-keepclassmembers class **.R$* {
  public static <fields>;
}

# Preserve the special static methods that are required in all enumeration classes.
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}


-keep public class * {
    public protected *;
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
##---------------End: proguard configuration common for all Android apps ----------

#for support library
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
-keep class android.support.v4.** { *; }
-keep class android.support.v13.** { *; }
-keep interface android.support.v4.** { *; }
-keep interface android.support.v13.** { *; }

#for retracing obfuscated stack traces
-keepattributes SourceFile,LineNumberTable

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.tweetstudio.tweet_studio_app.dto.** { *; }

##---------------End: proguard configuration for Gson  ----------


##--------For Google Play services-------------##

-keep class * extends java.util.ListResourceBundle {
    protected Object[][] getContents();
}

-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
    public static final *** NULL;
}

-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
    @com.google.android.gms.common.annotation.KeepName *;
}

-keepnames class * implements android.os.Parcelable {
    public static final ** CREATOR;
}

##---------- End: proguard configuration for google play ---------------

##---------- proguard configuration for joda-time ---------------

-dontwarn org.joda.convert.**
-dontwarn javax.xml.bind.DatatypeConverter

在将
joda-convert-2.7.jar
转换为
zip
并探索
basicyeardatetime字段
的第46行之后,我看到了这行代码:

super(DateTimeFieldType.year(), chronology.getAverageMillisPerYear());

也许浏览一下某些文档可以了解一些情况:

当应用程序尝试调用抽象方法时引发。通常,编译器会捕获此错误;仅当自上次编译当前执行的方法以来,某个类的定义发生了不兼容的更改时,才会在运行时发生此错误

有些东西承诺会实现“long boq.f()”,但这是谎言。只有当本应重新编译的内容未重新编译时,才可能在运行时执行此操作

我将编写一个简单的独立程序,使用joda time和
newdatetime(DateTimeZone.getDefault())查看问题是否容易重现。如果是的话,你已经将问题隔离到了joda time的版本中。看看回到旧版本是否能解决问题


你也可以重新编译joda time和任何与joda time对话的东西。这样做至少会将此运行时错误转化为编译时错误。这应该可以很容易地看出问题所在。

也许浏览一下某些文档会发现一些问题:

当应用程序尝试调用抽象方法时引发。通常,编译器会捕获此错误;仅当自上次编译当前执行的方法以来,某个类的定义发生了不兼容的更改时,才会在运行时发生此错误

有些东西承诺会实现“long boq.f()”,但这是谎言。只有当本应重新编译的内容未重新编译时,才可能在运行时执行此操作

我将编写一个简单的独立程序,使用joda time和
newdatetime(DateTimeZone.getDefault())查看问题是否容易重现。如果是的话,你已经将问题隔离到了joda time的版本中。看看回到旧版本是否能解决问题


你也可以重新编译joda time和任何与joda time对话的东西。这样做至少会将此运行时错误转化为编译时错误。这应该可以很容易地看出问题所在。

您可以使用此github Joda时间库

您可以使用此github Joda时间库

您可以添加以下行:-

-keep class org.joda.** { *; }
到您的proguard配置。这将阻止删除joda库中的代码。添加此行仅为我增加了2.8 KB的apk大小。

您可以添加以下行:-

-keep class org.joda.** { *; }

到您的proguard配置。这将阻止删除joda库中的代码。添加这一行仅为我增加了2.8 KB的apk大小。

“这个问题只发生在Android 5中”,意味着它不会发生在…?是的,在运行低于Andriod 5的操作系统的设备上,应用程序工作正常。在Android 4.4.4和4.0.2上测试,即使启用proguard,该应用程序也工作正常。“这个问题只发生在Android 5中”,意味着它不会发生在…?是的,在运行Andriod 5以下操作系统的设备上,应用程序工作正常。在Android 4.4.4和4.0.2上测试,即使启用proguard,应用程序也工作正常。但解决方案是什么?嗯,重新编译?不管怎么说,当我看第46行时,它只是
iChronology=年代学所以我认为我看的版本不对。您的版本的第46行有什么内容?我的版本中
BasicYearDateTimeField
的第46行:
super(DateTimeFieldType.year(),chronology.getAverageMillisPerYear())事实上,我在清理/构建后多次尝试导出apk,因此我认为重新编译将不起作用。我正在尝试验证什么与什么版本同步。有些东西不同步,我正试图消除这种可能性。但那个么解决方案是什么呢?嗯,重新编译?不管怎么说,当我看第46行时,它只是
iChronology=年代学所以我认为我看的版本不对。您的版本的第46行有什么内容?我的版本中
BasicYearDateTimeField
的第46行:
super(DateTimeFieldType.year(),chronology.getAverageMillisPerYear())事实上,我在清理/构建后多次尝试导出apk,因此我认为重新编译将不起作用。我正在尝试验证什么与什么版本同步。有些东西不同步,我正试图消除这种可能性。