Android Dalvik Verification в Eclair

Недавно я изучал фрагментацию уровней API и нашел отличный учебник по поддержке различных уровней API в ваш исходный код:

Как указано в учебнике, во избежание ошибки во время использования новых классов/методов, чем уровень API, необходимо проверить уровень API и использовать ленивую загрузку.

Я проверил код и могу подтвердить, что на Android < 2.0 вы должны использовать ленивую загрузку, чтобы избежать VerifyError. Для меня было большим сюрпризом, так как в 2.1 ленивая загрузка больше не нужна.

Я использую метод Camera.setDisplayOrientation, чтобы продемонстрировать проблему. Метод был введен в Froyo 2.2.

import android.hardware.Camera;
...
public class CameraActivity extends Activity implements SurfaceHolder.Callback{
   Camera mCamera;

   ...

   public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
      final int APIversion = Integer.parseInt(Build.VERSION.SDK);
      if (APIversion >= Build.VERSION_CODES.FROYO){
         camera.setDisplayOrientation(90);
      }
      ...
   }
}

Код компилируется с использованием компилятора Froyo (API 8)

Как и предполагалось, если я запустил APK в версии для Android версии 2.0, я получаю исключение VerifyError при запуске CameraActivity.

Но меня удивляет то, что когда я запускаю тот же APK на Eclair 2.1, приложение загружается без каких-либо проблем. И я дважды проверил интерфейс камеры и обнаружил, что метод setDisplayOrientation был введен только в Froyo 2.2.

Напротив, если я попытаюсь вызвать метод, я получу исключение, т.е.

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){    
    final int APIversion = Integer.parseInt(Build.VERSION.SDK);
    camera.setDisplayOrientation(90);
}

В Eclair это вызовет NoSuchMethodError.

Почему это работает? Имеет ли это какое-либо отношение к отключению проверки класса?

PS: я проверил, что setDisplayOrientation действительно не существует в Eclair 2.1. Я сделал это, пытаясь удалить проверку версии SDK версии до вызова метода. Если я просто вызову метод, я получу исключение NoSuchMethod. Но если IF есть, я не получаю VerifyError!

Ответ 1

Начиная с Android 2.0 верификатор Dalvik умнее всего проверять классы, которые фактически используются во время работы.

Тем не менее, код, который вы здесь показываете, будет работать, только если вы никогда не касаетесь класса CameraActivity при работе на старых версиях платформы. Учитывая, что это не то, что вы показываете, может быть объяснено, что на некоторых старых сборках платформы API был, но еще не доступен в SDK.