Приложение отлично работает на 1.6, но почему я получаю java.lang.VerifyError на Xperia X10 под управлением 1.6? - PullRequest
2 голосов
/ 19 июля 2011

Мое приложение отлично работает как на эмулируемых, так и на реальных устройствах 1.6. Однако серия Sony Xperia X10 (с версией 1.6) дает сбой с ошибкой java.lang.VerifyError. Этот поток наводит меня на мысль, что оптимизация 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.

РЕДАКТИРОВАТЬ (новая информация):

Хорошо, я смог найти старый образ эмулятора X10 под управлением 1.6 и воссоздать проблему. Оказывается, он / это / только сбой на версии выпуска (ProGuard). Выключите ProGuard, и он работает отлично. С какой стати это влияет только на X10, и не каждое устройство 1.6 - это вопрос. Вот некоторая новая информация, которую я собрал, так как у меня есть эмулятор ...

В некоторых моих действиях я использую overridePendingTransition, чтобы перейти к эффекту затухания, однако это не поддерживается в 1.6, поэтому я использую вспомогательный класс с именем VersionHelper:

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

и вызывается из Аниматора:

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

Это позволяет устройствам 1.6 запускать остальную часть кода без сбоев из-за неподдерживаемого метода (спасибо Марку Мерфи за эту технику).

Теперь трассировка стека с дополнительными данными журнала:

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

Использование -dontoptimize в ProGuard позволяет запускать приложение на X10. Я подбираюсь к решению.

Ответы [ 3 ]

3 голосов
/ 21 июля 2011

Шаг оптимизации ProGuard включает встроенные методы, такие как VersionHelper # overrideTransition (), а это не то, что вам нужно, поскольку метод предназначен для изоляции зависимости от 1.6 (хотя ProGuard не может этого знать).

Грубое усилие: отключить все оптимизации:

-dontoptimize

Более детально: отключить все методы встраивания (как вы узнали):

-optimizations !method/inlining/*

Идеальное решение: избегатьПодчеркнем этот конкретный метод и его братьев и сестер:

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

Без подробностей я не могу много сказать о других вопросах.Вы можете задать вопросы на справочном форуме ProGuard.

1 голос
/ 20 июля 2011

Решением было добавить -optimizations !method/inlining/unique в proguard.cfg, который в соответствии с документацией ProGuard обычно называет «встроенными методами, которые вызываются только один раз».Хотелось бы сказать, что я понял это, не исключая каждую отдельную оптимизацию, а затем удаляя их по одному при создании подписанных выпусков ... но это именно то, что я сделал.

Редактировать (новая информация)

Продолжая работать, я обнаруживаю, что есть другие части моего приложения, которые выходят из строя на X10, и для правильной работы требуются другие специальные исключения оптимизации.Я также начинаю видеть шаблон с отчетами о сбоях от других конкретных устройств, которые просто не должны происходить , и фактически не происходят на моих собственных тестовых устройствах и эмуляторах.

Я вынужден сделать вывод, что в данный момент я не могу доверять оптимизации ProGuard.Поскольку проблемы возникают только на определенных устройствах, я скорее возложу вину на настройки производителя, а не на ProGuard.Найти фактическую связь между этими двумя понятиями я не могу.

Так что мое окончательное решение - использовать -dontoptimize или рискнуть получить 1-звездочные обзоры из-за неразрешимых проблем.Ухоженная.Я никогда не жаловался на фрагментацию платформы до сих пор.Это конкретное открытие вызывает серьезное разочарование.

Редактировать 2 (продолжение)

Поскольку я отправил обновление, удаляющее оптимизацию сразу, все сбои прекратились.Теперь я наконец могу вернуться к разработке функций.

1 голос
/ 19 июля 2011

Ваша реализация класса com.twocell.walkabout.Animator относится к некоторому классу или методу, которого нет в Xperia X10.Он не должен быть ограничен чем-то в статическом методе setLayoutAnimation_textFadeIn() - это может быть что угодно в этом классе.К сожалению, VerifyError не говорит , что не может быть найдено.

Вам придется пройтись по своему приложению с помощью зубчатого гребня и определить, что может отсутствовать на Xperia X10.это существует в другом месте.

, но если бы это было так, проблема не существовала бы на каждом устройстве с версией 1.6, а не только на X10?

Да.

...