Подтвердить что ты не робот

Запись обратно совместимого кода Android

Я пишу приложение, которое использует некоторые функции и классы, доступные только на последнем уровне API - 16, но я хочу, чтобы он запускался без ошибок на устройствах с уровнем API 15.

Позвольте использовать несколько примеров. Новый класс: Android.widget.Advanceable и новый/переименованный метод: View.setBackground():

Я могу сделать что-то вроде этого:

Advanceable myAdvanceable = ...;

if (android.os.Build.VERSION.SDK_INT >= 16)
{
    myView.setBackground(...);
    myAdvanceable.advance();
}
else
{
    myView.setBackgroundDrawable(...); // The old function name.
    // Don't bother advancing advanceables.
}

И если я установил minSdk из 15, но цель построения 16 (т.е. в Project Properties → Android), он фактически скомпилируется без ошибок. По крайней мере, некоторое время. Eclipse немного стохастичен в отношении ошибок и иногда говорит: "setBackground() доступен только в уровне API >= 16" или аналогичном, но если я просто очищу проект, то эти ошибки волшебным образом исчезнут.

Итак, мой вопрос: разрешено ли мне это делать? Не будет ли сбой кода, если я запустил его на устройстве уровня 15 API? Будет ли это только сбой, если он действительно доберется до 16 кода? Почему Eclipse не останавливает меня от его создания?

Изменить 1

Спасибо за ответы, я думаю, вопрос действительно должен быть: почему я не буду предупреждать меня об использовании новых API?

У меня это в моем манифесте, и я использую функции уровня API 16, но он все равно меня не предупреждает:

<uses-sdk android:minSdkVersion="15"
    android:targetSdkVersion="16"/>

Также я все еще не уверен, когда целые классы являются новыми для уровня API, например Advanceable. В частности, если я использую их как переменные-члены.

Изменить 2

Ответ оказался "Eclipse багги, как ад", но ответ Нико также очень помог.

4b9b3361

Ответ 1

Ошибки Inline Api являются новыми для ADT, Eclipse запускают Lint (и я думаю, что-то еще возможно), чтобы проанализировать ваш код и поместить эти ошибки/предупреждения в строку. То же самое относится к макету xml, когда у вас есть предупреждения или подсказки об оптимизации или передовой практике. Вы можете использовать аннотации для подавления этих ошибок в классе или в определенном методе.

@TargetApi (16)
@SuppressLint ( "NewApi" )

В приведенном здесь примере кода есть проблема, помимо проверки уровня API у вас есть экземпляр Advanceable в коде, который не будет работать в API < 16, поэтому проверка уровня API полезна только при вызове новых методов, но вы не можете ссылаться на новые классы API вне блока IF.

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

Например, для создания представления, которое использует некоторые новые классы и методы API внутри, вам необходимо:

1 - Создать абстрактный класс:

public abstract class CustomView {
    public abstract void doSomething();
}
  • Общая реализация, совместимая со всеми API-интерфейсами
  • Определите абстрактный метод здесь, чтобы разделить реализацию.

2 - Унаследованная реализация

public class CustomLegacyView extends CustomView {
    public void doSomething(){
        //implement api < 16
    }
}
  • реализовать абстрактный метод для API < 16

3 - реализация API 16

@TargetApi(16)
public class CustomL16View extends CustomView {

    Advanceable myAdvanceable;

    public void doSomething(){
        //implement api >= 16
    }
}
  • Использовать аннотацию @TargetApi (16)
  • реализовать абстрактный метод для API >= 16
  • Здесь вы можете ссылаться на классы уровня 16 (но не в CustomView).

4 - factory класс

public class ViewFactory {

    public static CustomView getCustomView(Context context) {

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            return new CustomL16View(context);
        }else{
            return new CustomLegacyView(context);
        }

    }
}

Ответ 2

Общепринятой практикой является использование более новой цели сборки и гарантия того, что новый API будет вызван при правильных обстоятельствах. Google даже добавила аннотацию @TargetApi() с ADT 17, чтобы указать локальные переопределения для условно загружаемого кода.

Подробнее см. Lint API check.

Ответ 3

1. У вас есть атрибуты Target Api и Minimum SDK, чтобы определить, какое устройство вы используете      , и это будет наименьшая версия Api, на которой он будет работать.

2. Target Api будет тем, на котором приложение работает с полными функциями, тогда как Minimum SDK сделает приложение запущено на нем с помощью < некоторые компромиссы, так как могут быть шансы, что более низкая версия API не имеет функций, которые находятся в более высоких версиях.