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

Как поддерживать несколько версий Android в коде?

Получить доступ к контактам в android android.jar для версий 1.6 имеет People.CONTENT_URI для вызова информации, связанной с контактами, тогда как в более поздних версиях нам нужна поддержка api для RawContacts.CONTENT_URI.

То же самое верно для доступа к календарю, например, поскольку его URI изменяется в android 2.2.

Есть ли наилучшая практика для управления всеми различными изменениями без добавления дополнительного приложения или сборки отдельно для каждой версии изменений?

4b9b3361

Ответ 1

Совершенно честно, это боль.

Обычно я просто изолирую части кода, которые отличаются друг от друга, и обращаюсь к ним с помощью абстрактных классов. Так технически создавая другую версию для разных ОС.

Но есть и другие способы. Лучшее, что я видел, связано с использованием отражения.

Ответ 2

На мои деньги очень хороший ответ на http://android-developers.blogspot.co.uk/2010/07/how-to-have-your-cupcake-and-eat-it-too.html. Тем не менее, пример немного сложнее, чем нужно, поэтому, основываясь на этом, вот пример того, как справиться с ним при создании уведомлений. Основная причина, по которой это работает, является следствием того, как java-движки интерпретируют классы: она смотрит только на них, когда это необходимо, поэтому, если вы завершаете код определенной версии в классе и создаете его только тогда, когда знаете, что используете эту версию, все это работает...

Есть, насколько я могу судить, два поколения подходов к созданию уведомления и изменение имен по пути во втором. Таким образом, это дает три способа сделать это. Для каждого пути создайте класс с генерацией уведомлений в нем:

Первый подход (используемый до Gingerbread):

public class MyNotificationBuilderToGingerBread {
Notification notification = null;

MyNotificationBuilderToGingerBread(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, int flags) {
    notification = new Notification(R.drawable.ic_sb, ticker, timeStamp);
    notification.setLatestEventInfo(myContext, title, info, pendingIntent);
    notification.flags |= flags;        
}

Notification get() {
    return notification;
}
}

Второй подход, сотовый для IceCreamSandwich:

public class MyNotificationBuilderHoneyCombToIceCreamSandwich {
Notification.Builder mb = null;

MyNotificationBuilderHoneyCombToIceCreamSandwich(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) {
    mb = new Notification.Builder(myContext);
    mb.setSmallIcon(icon);
    mb.setContentIntent(pendingIntent);
    mb.setContentTitle(title);
    mb.setContentText(info);
    mb.setWhen(timeStamp);
    if (ticker != null) mb.setTicker(ticker);       
    mb.setOngoing(onGoing);
}

Notification get() {
    return mb.getNotification();
}   
}

Второе поколение, с изменением названия, Jellybean (далее, пока...):

public class MyNotificationBuilderJellyBean {

Notification.Builder mb = null;

MyNotificationBuilderJellyBean(Context myContext, int icon, String ticker, String title, String info, Long timeStamp, PendingIntent pendingIntent, boolean onGoing) {
    mb = new Notification.Builder(myContext);
    mb.setSmallIcon(icon);
    mb.setContentIntent(pendingIntent);
    mb.setContentTitle(title);
    mb.setContentText(info);
    mb.setWhen(timeStamp);
    if (ticker != null) mb.setTicker(ticker);       
    mb.setOngoing(onGoing);
}

Notification get() {
    return mb.build();
}   
}

Затем вам просто нужно выбрать, какой класс нужно создавать на лету:

// System information
private final int sdkVersion = Build.VERSION.SDK_INT;
// If you want to go really old:
    // (actually, there is a question about how this issue should be handled
    // systematically. Suggestions welcome.)
// final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);

    // This is for a permanent notification. Change the final argument (flags or boolean) if it isn't meant ot be
    // For meaning of other variable, see notification documentation on the android website.
    if (sdkVersion < Build.VERSION_CODES.HONEYCOMB) {
        MyNotificationBuilderToGingerBread mnb = new MyNotificationBuilderToGingerBread(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR);
        notification = mnb.get();
    }
    else if (sdkVersion < Build.VERSION_CODES.JELLY_BEAN) {
        MyNotificationBuilderHoneyCombToIceCreamSandwich mnb = new MyNotificationBuilderHoneyCombToIceCreamSandwich(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true);
        notification = mnb.get();
    }
    else {
        MyNotificationBuilderJellyBean mnb = new MyNotificationBuilderJellyBean(myContext, R.drawable.notification_icon, ticketText, title, infoText, timeStampMillis, pendingIntentForTapOnFullNotitifcation, true);
        notification = mnb.get();
    }

    // Send the notification.
    notificationManager.notify(idForNotificationManager, notification);

Надеюсь, это поможет!

Ответ 3

Есть много ресурсов, которые вы можете использовать для поддержки нескольких версий Android.

  • Прочитайте этот пост в блоге здесь и затем прочитайте этот здесь, они поможет вам определить уровень API версии поддержки.
  • Прочитайте это сообщение в блоге по нескольким поддержки экрана, особенно иерархия активов при анализе res папка. Это поможет вам понимать и разрабатывать, как это сделать структура папок для поддержки различные размеры экрана/плотность и версии для Android.
  • Наконец напишите свой собственный ant build скриптов, чтобы вы могли скомпилировать все версии андроида.

Ответ 4

  • Если вам действительно не нужны новые функции, и действительно нужно поддерживать старые версии Android, оставьте это. Создайте приложение для самой старой версии и не беспокойтесь об этом.
  • В другом случае вы можете обнаружить версию с помощью Build и использовать отражение, чтобы загрузить нужные классы. Пример этого можно найти в исходном коде приложения K9Mail

Ответ 5

Там хорошая статья на android.com об этом: http://developer.android.com/resources/articles/backward-compatibility.html

Лично я бы предложил класс оболочки или решение для библиотеки оберток. Но в малых случаях отражение должно быть хорошим (и в случае, если производительность для вас не проблема).

Если вам нужна дополнительная информация, спросите в комментариях.

Ответ 7

Если на Eclipse, с версии 11 для ADT, вы можете указать код для запуска с некоторой версией, как описано в Lint API Check. Кодовое слово @TargetAPI (XX)

Надеюсь, что это поможет

Ответ 8

Лучшая практика (хотя и не для Android, а для J2ME), насколько я знаю, это использование предпроцессорных инструкций типа C/С++, например:

//#if S40
    ...
//#else
    ...
//#endif

Некоторые IDE поддерживают такую ​​предварительную обработку, например. Netbeans. Насколько мне известно, в Eclipse есть некоторые плагины, которые также позволяют выполнять предварительную обработку. Я действительно не знаю, применимы ли они для разработки Android. Попробуйте сами Google.