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

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

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

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

Честно говоря, это боль.

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

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

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

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

Первый подход (используемый до 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; } } 

Второй подход, Honeycomb к 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(); } } 

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

 // 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); 

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

У вас много ресурсов для поддержки нескольких версий Android.

  1. Прочтите это сообщение в блоге здесь, а затем прочитайте здесь здесь , они помогут вам решить проблемы с версией версии API.
  2. Прочитайте это сообщение в блоге с поддержкой нескольких экранов, особенно, как иерархия активов анализируется в папке res. Это поможет вам понять и разработать, как создать структуру папок для поддержки различных размеров экрана и плотности и версий Android.
  3. Наконец, напишите свои собственные скрипты сборки ant, чтобы вы могли скомпилировать все версии Android.
  • Если вам действительно не нужны новые функции, и действительно нужно поддерживать старые версии Android, отбросьте их. Создайте приложение для самой старой версии и не беспокойтесь об этом.
  • В другом случае вы можете обнаружить версию с помощью Build и использовать reflection для загрузки classов, которые вам нужны. Пример этого можно найти в исходном коде приложения K9Mail

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

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

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

Это отличная статья, когда вам нужно делать размышления в Android (для поддержки нескольких уровней API).

И когда вам нужно иметь разные ресурсы для разных уровней API, это ссылка на использование (см. Раздел «Версия платформы (уровень API)»).

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

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

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

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

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

  • Как отправить данные из диалогового windows в fragment?
  • Отладка Android InetAddress.isReachable
  • Как передать объект Bitmap из одной активности в другую
  • Не удалось войти в систему. Проверьте подключение к сети и повторите попытку.
  • Насколько велика ссылка на объект в Java и какая именно информация содержится в ней?
  • Android: как приостановить и возобновить таймер обратного отсчета?
  • java.io.IOException: обнаружено не было
  • Как добавить каталог в путь к classам в профиле запуска приложения в IntelliJ IDEA?
  • Почему я не могу использовать метод overulateViewHolder override?
  • Передача функции в качестве параметра в java
  • Как я могу сделать ячейку в ListView в Android расширяться и сокращаться вертикально, когда ее касаются?
  • Давайте будем гением компьютера.