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

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

То же самое верно для доступа к календарю, например, поскольку его URI изменяется в android 2.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; } } 

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

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

 // 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 и использовать отражение для загрузки классов, в которых вы нуждаетесь. Пример этого можно найти в исходном коде приложения K9Mail

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

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

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

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

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

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

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

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

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

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

Intereting Posts
Android Obfuscation для кода, а также ресурсов Оптимизация и опускание GPU Overdraw – Android Ошибка @Override аннотации (андроидные prefs) Как заполнить два разных цвета в пользовательской форме? Оптимизация огромного рисунка VBO на устройствах Android / iOS Javax.net.ssl.SSLPeerUnverifiedException: нет сертификата peer при попытке подключения с использованием https с .bks keystore Android Studio INSTALL_FAILED_DEXOPT и INSTALL_FAILED_UID_CHANGED при запуске проекта Сброс AutoExposureLock после вызова takePicture () Android 2.3 имеет более низкий бюджет VM, чем 2,1 и 2,2? Разница между вольдом и udevd Не получать ответ в сокетном соединении Служение, убитое при сохранении блокировки во время разговора и после вызова startForeground Можно ли рисовать прямоугольник в XML? Проблема с интерполяцией панели инструментов с помощью библиотеки поддержки дизайна Android Как создать новый проект Android в eclipse и поделиться им в локальном репозитории git?