Как поддерживать несколько версий Android в коде?
Для доступа к контактам в android android.jar для версий 1.6 есть People.CONTENT_URI для вызова информации, связанной с контактами, тогда как в более поздних версиях нам нужна поддержка api для RawContacts.CONTENT_URI.
То же самое верно для доступа к календарю, например, поскольку его URI изменяется в android 2.2.
Существует ли наилучшая практика для управления всеми различными изменениями без добавления дополнительного приложения или сборки отдельно для каждой версии изменений?
- Преобразование JSONArray в String Array
- Как установить выбранный элемент Spinner по значению, а не положением?
- Метод getText () должен быть вызван из streamа пользовательского интерфейса (Android Studio)
- Подписывает ли подпись метода в Java свой тип возврата?
- Выполнение не выполнено для задачи ': app: dexDebug'. com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException
- Полноэкранный просмотр без растягивания видео
- преобразовать маленький файл Endian в большой Endian
- Разделить строку на отдельные слова Java
- Исходный код исходного кода Java
- Java-настройка classpath
- javax.mail.AuthenticationFailedException выбрасывается при отправке электронной почты в java
- Является ли массив объектом java
- НЕОПРЕДЕЛЕННОЕ ТОП-УРОВЕННОЕ ИСКЛЮЧЕНИЕ: com.android.dex.DexException: несколько файлов dex определяют
Честно говоря, это боль.
Обычно я просто изолирую части кода, которые отличаются друг от друга и получают доступ к ним с помощью абстрактных 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.
- Прочтите это сообщение в блоге здесь, а затем прочитайте здесь здесь , они помогут вам решить проблемы с версией версии API.
- Прочитайте это сообщение в блоге с поддержкой нескольких экранов, особенно, как иерархия активов анализируется в папке res. Это поможет вам понять и разработать, как создать структуру папок для поддержки различных размеров экрана и плотности и версий Android.
- Наконец, напишите свои собственные скрипты сборки 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. Попробуйте сами.