VerifyError развертывание на API 1.6 - PullRequest
14 голосов
/ 27 июня 2011

Я столкнулся с проблемой обратной совместимости при развертывании моего приложения на Android 1.6.Я получаю VerifyError для этого фрагмента кода:

if(android.os.Build.VERSION.SDK_INT >= 11) {
    getActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.actionbar_bg));
}

Это не является неожиданным, поскольку getActionBar () не существует до API 11, однако после 1.6 (API 5 и выше?) Создаются все полуизящно обойти это в соответствии с сообщением logcat, которое я получаю при развертывании, например, на устройстве уровня API 8;

06-27 16:47:04.333: INFO/dalvikvm(11529): Could not find method com.me.app.MyActivity.getActionBar, referenced from method com.me.app.MyActivity.init
06-27 16:47:04.333: WARN/dalvikvm(11529): VFY: unable to resolve virtual method 1090: Lcom.me.app.MyActivity;.getActionBar ()Landroid/app/ActionBar;
06-27 16:47:04.333: DEBUG/dalvikvm(11529): VFY: replacing opcode 0x6e at 0x004f
06-27 16:47:04.333: DEBUG/dalvikvm(11529): VFY: dead code 0x0052-005f in Lcom.me.app.MyActivity;.init (Z)V

1.6 и более ранние версии не будут этого делать, а вместо этого выдают VerifyError:

06-27 16:23:45.561: ERROR/dalvikvm(427): Could not find method com.me.app.MyActivity.getActionBar, referenced from method com.me.app.MyActivity.init
06-27 16:23:45.561: WARN/dalvikvm(427): VFY: unable to resolve virtual method 1090: Lcom/me/app/MyActivity;.getActionBar ()Landroid/app/ActionBar;
06-27 16:23:45.561: WARN/dalvikvm(427): VFY:  rejecting opcode 0x6e at 0x004f
06-27 16:23:45.561: WARN/dalvikvm(427): VFY:  rejected Lcom/me/app/MyActivity;.init (Z)V
06-27 16:23:45.561: WARN/dalvikvm(427): Verifier rejected class Lcom/me/app/MyActivity;
06-27 16:23:45.561: WARN/dalvikvm(427): Class init failed in newInstance call (Lcom/me/app/MyActivity;)
06-27 16:26:44.841: ERROR/AndroidRuntime(427): Uncaught handler: thread main exiting due to uncaught exception
06-27 16:26:44.941: ERROR/AndroidRuntime(427): java.lang.VerifyError: com.me.app.MyActivity
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at java.lang.Class.newInstanceImpl(Native Method)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at java.lang.Class.newInstance(Class.java:1472)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.Instrumentation.newActivity(Instrumentation.java:1097)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2316)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.ActivityThread.access$2100(ActivityThread.java:116)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.os.Handler.dispatchMessage(Handler.java:99)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.os.Looper.loop(Looper.java:123)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at android.app.ActivityThread.main(ActivityThread.java:4203)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at java.lang.reflect.Method.invokeNative(Native Method)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at java.lang.reflect.Method.invoke(Method.java:521)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
06-27 16:26:44.941: ERROR/AndroidRuntime(427):     at dalvik.system.NativeStart.main(Native Method)

Есть ли способ исправить это элегантно и иметь обратную совместимость с 1.6?

Редактировать: Итак, я закончил создание класса HoneycombHelper со статическими методами:

public class HoneycombHelper {
    public static void setActionBarBackgroundDrawable(Activity a, Drawable d) {
        a.getActionBar().setBackgroundDrawable(d);
    }
    ...
}

Не уверен, что этоэто самый элегантный способ, но, похоже, он работает.

1 Ответ

24 голосов
/ 27 июня 2011

Когда Dalvik компилирует ваш класс / функцию из байт-кода в собственный машинный код, он компилирует все операторы, даже те, которые находятся в условиях if.В Android 1.6 виртуальная машина пытается разрешить (проверить) функцию getActionBar, и поскольку такой функции нет, Dalvik создает VerifyError.

. Вы можете выполнить следующий трюк:

class ActionBarHelper{
   void setBackground(){
      getActionBar().setBackgroundDrawable(...);
   }
}

...

if(android.os.Build.VERSION.SDK_INT >= 11) {
   new ActionBarHelper().setBackground();    
}

Таким образом, ActioBarHelper класс будет скомпилирован / проверен только при работе на SDK 11+.Это, в свою очередь, позволит вызывать функцию getActionBar без использования отражения (отражение является еще одним возможным решением этой проблемы).

...