java - 应用程序在 1.6 上完美运行,但为什么我在运行 1.6 的 Xperia X10 上收到 java.lang.VerifyError 错误?

标签 java android proguard

我的应用程序在模拟和真实 1.6 设备上都能完美运行。然而,Sony Xperia X10 系列(运行 1.6)因 java.lang.VerifyError 崩溃。 This thread让我相信 ProGuard 优化可能是罪魁祸首,但如果是这样的话,这个问题不是存在于所有运行 1.6 的设备上,而不仅仅是 X10 上吗?

这是堆栈跟踪:

java.lang.VerifyError: com.twocell.walkabout.Animator
at com.twocell.walkabout.Main.void onCreate(android.os.Bundle)(SourceFile:197)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2443)
at android.app.ActivityThread.access$2100(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1815)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)

这是触发错误的代码(在名为“Animator”的类中):

static void setLayoutAnimation_textFadeIn(ViewGroup vg, Context context)
{
    Animation text_fadeIn = AnimationUtils.loadAnimation(context, R.anim.text_fade_in);
    LayoutAnimationController controller = new LayoutAnimationController(text_fadeIn, 0.25f);
    vg.setLayoutAnimation(controller);
}

调用自:

LinearLayout HeaderBar_Text = (LinearLayout) findViewById(R.id.HeaderBar_Text);
Animator.setLayoutAnimation_textFadeIn(HeaderBar_Text, this); // this is line 197

这里是text_fade_in.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
<alpha
    android:fromAlpha="0.0" 
    android:toAlpha="1.0"
    android:duration="1000"
    />
</set>

我无法访问 X10,因此我依赖通过 ACRA 提供的堆栈跟踪。

编辑(新信息):

好的,我找到了运行 1.6 的 X10 的旧模拟器镜像并重新创建了问题。事实证明,它仅在发布(ProGuard)版本上崩溃。关闭 ProGuard 即可完美运行。到底为什么这只影响 X10 而不是所有 1.6 设备?这是自从我拥有模拟器以来我收集的一些新信息...

在我的一些 Activity 中,我使用 overridePendingTransition 来更改淡入淡出效果,但是 1.6 不支持此功能,因此我使用名为 VersionHelper 的帮助程序类:

class VersionHelper
{   
    static void overrideTransition(Context context)
    {
        ((Activity)context).overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out);
    }
}

它是从 Animator 调用的:

static void overrideTransition(Context context)
{
    if (Build.VERSION.SDK_INT > 4)
    {
        VersionHelper.overrideTransition(context);
    }
}

这允许 1.6 设备运行其余代码,而不会因不受支持的方法而崩溃(感谢 Mark Murphy 提供的这项技术)。

现在,带有额外日志数据的堆栈跟踪:

07-19 23:42:29.150: ERROR/dalvikvm(705): Could not find method android.app.Activity.overridePendingTransition, referenced from method com.twocell.walkabout.Animator.overrideTransition
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: unable to resolve virtual method 14: Landroid/app/Activity;.overridePendingTransition (II)V
07-19 23:42:29.150: WARN/dalvikvm(705): VFY:  rejecting opcode 0x6e at 0x0012
07-19 23:42:29.150: WARN/dalvikvm(705): VFY:  rejected Lcom/twocell/walkabout/Animator;.overrideTransition (Landroid/content/Context;)V
07-19 23:42:29.150: WARN/dalvikvm(705): Verifier rejected class Lcom/twocell/walkabout/Animator;
07-19 23:42:29.160: DEBUG/AndroidRuntime(705): Shutting down VM
07-19 23:42:29.160: WARN/dalvikvm(705): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): Uncaught handler: thread main exiting due to uncaught exception
07-19 23:42:29.160: ERROR/AndroidRuntime(705): java.lang.VerifyError: com.twocell.walkabout.Animator
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at com.twocell.walkabout.Main.onCreate(SourceFile:199)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.ActivityThread.access$2100(ActivityThread.java:116)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.os.Looper.loop(Looper.java:123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at android.app.ActivityThread.main(ActivityThread.java:4203)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at java.lang.reflect.Method.invokeNative(Native Method)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at java.lang.reflect.Method.invoke(Method.java:521)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
07-19 23:42:29.160: ERROR/AndroidRuntime(705):     at dalvik.system.NativeStart.main(Native Method)

就是这样 - 当我使用 ProGuard 时,并且仅在 X10 上,它仍然会看到 overridePendingTransition 并崩溃。 (我确认 X10/is/报告“4”为其 API 版本。)

最后,我的 proguard.cfg:

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-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
-keep class com.android.vending.billing.**

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

#ACRA specifics
# we need line numbers in our stack traces otherwise they are pretty useless
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

# ACRA needs "annotations" so add this... 
-keepattributes *Annotation*

# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
        *;
}

# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
   *;
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public void addCustomData(java.lang.String,java.lang.String);
}

# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public org.acra.ErrorReporter$ReportsSenderWorker   handleSilentException(java.lang.Throwable);
}

-keep class org.acra.ReportField {*;}

有什么想法吗?

编辑 2

在 ProGuard 中使用 -dontoptimize 让应用程序在 X10 上运行。我正在悄悄寻找解决方案。

最佳答案

ProGuard 的优化步骤将内联像 VersionHelper#overrideTransition() 这样的方法,这不是您想要的,因为该方法旨在隔离对 1.6 的依赖(尽管 ProGuard 无法知道这一点)。

暴力解决方案:关闭所有优化:

-dontoptimize

更细粒度:关闭所有方法内联(正如您所发现的):

-optimizations !method/inlining/*

理想的解决方案:避免内联此特定方法及其同级方法:

-keepclassmembers,allowobfuscation,allowshrinking somepackage.VersionHelper {
  <methods>;
}

没有详细信息,我无法对其他问题说太多。您可以在 ProGuard 的帮助论坛上提问。

关于java - 应用程序在 1.6 上完美运行,但为什么我在运行 1.6 的 Xperia X10 上收到 java.lang.VerifyError 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6751242/

相关文章:

java - 我们怎样才能创建一个每次都会发生的 for 循环呢?

断电后Android Studio无法识别类

android - 在运行时检测你是否被 ProGuarded?

java - 如何在 Android 中的 Mainactivity 和另一个类之间传递全局计数器?

java - 最终变量的理解

java - 在mavenLocal()中为.jar文件成功添加gradle依赖关系之后,我如何实际从Java类导入和使用该jar

Android 4.0 Eclipse 编译失败

Android Wear 操作项目图标大小与电话通知操作项目大小

org.xmlpull.v1.XmlPullParser 的 Android ProGuard 错误

android - 为什么 ProGuard 保留 onCreate() 方法?