О чем молчат книги по Android. 5 проблем, о которых не пишут в документации
Ты никогда не задумывался, чем работа программиста отличается, например, от работы инженера-конструктора или прочниста (расслабься, сопромат вспоминать не будем)? Первое, что приходит в голову, — право на ошибки: действительно, процеcc тестирования (отладки) занимает значительное время в любом проекте. Если продолжить размышлять, можно прибавить сюда и динамичность профессии.
В основе инженерных специальностей лежат методики, разработанные десятилетия назад, — так, методу конечных элементов скоро исполнится 70 лет, а он до сих пор не потерял актуальности. В программировании же все меняется со скоростью, близкой к скорости света. И нам приходится постоянно что-то изучать, пробовать чужиe решения, изобретать собственные велосипеды, менять алгоритмы, внедрять стеки новых технологий — словом, участвовать в гонке без финиша. И если инженерам в их работе помогают умные книги, проверенные временем, то в нашем случае найти информацию, порой даже в официальных источниках, бывает очень проблематично. Не веришь? Что ж, тогда добро пожаловать в [А]ндрои[Д]…
Виджет и документация
Сегодня мы рассмотрим Android и его виджеты — только практику, никакой теории. За последней отсылаю тебя к недавней статье, где мы подробно рассматривали процесс создания «хакерского» виджета.
Итак, виджет представляет собой реализацию широковещательного приемника, каркас которого представлен ниже:
public class SkeletonAppWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int appWidgetId : appWidgetIds) { ... appWidgetManager.updateAppWidget(appWidgetId, views); Log.d(DEBUG_TAG, "onUpdate : id = " + String.valueOf(appWidgetId)); } } @Override public void onDeleted(Context context, int[] appWidgetIds) { Log.d(DEBUG_TAG, "onDeleted"); super.onDeleted(context, appWidgetIds); } @Override public void onDisabled(Context context) { Log.d(DEBUG_TAG, "onDisabled"); super.onDisabled(context); } @Override public void onEnabled(Context context) { Log.d(DEBUG_TAG, "onEnabled"); super.onEnabled(context); } }
Когда пользователь помещает первый экземпляр виджета на домашний экран, срабатывает метод onEnabled()
, после удаления которого вызывается парный onDisabled()
. Метод onDeleted()
вызывается всякий раз, когда пользователь перетаскивает представление экземпляра виджета в корзину.
Метод onUpdate()
в цикле обновляет все экземпляры виджета по идентификаторам, хранящимся в массиве, дергая updateAppWidget()
.
Все сказанное можно найти в официальнoй документации Google, а также в любой книге по программированию под Android. Типичный виджет представлен на рис. 1.
Рис. 1. Обычный виджет
Виджет vs программист
В качестве разминки предлагаю зaбыть половину из того, что мы написали, так как оно не работает! Я не зря поставил отладочную печать всех методов. Запустив код в эмуляторе или на реальном девайсе, можно легко убедиться, что ни onEnabled
, ни onDisabled
никогда не вызываются в Android 4.4 и ниже! (Чтобы не быть голословным, здесь и далее я тестирую код на устройствах с Android 4.4, 5.1, 6.0.)
Почему так? Видимо, сие есть тайна, доступная только джедаям Google. Вопрос в другом: почему об этом прямо не написать в документации? Особенно доставляют в общем-то правильные по сути механизмы запуска фонового сервиса (или сигнализации) для обновления информации виджетов в onEnabled
с остановкой в onDisabled
в примерах книг, предназначенных для Android 4. Получается, авторы не тестируют код, который сами же пишут?
Кто-то скажет, что в 5-й версии мобильной ОС это исправлено. Да, исправлено, но сбрасывать со счетов Android 4 пока рано. Кроме того, такие вещи не должны выявляться программистом опытным путем.
Виджет vs здравый смысл
Виджет может быть намного полезнее, если предусмотреть возможность настраивать его перед добавлением на домашний экран. В качестве экрана настройки может выступать любая активность в рамках приложения при условии, что она имеет фильтр намерений для действия APPWIDGET_CONFIGURE в манифесте:
<activity android:name=".WidgetSetup" android:label="@string/setup"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter> </activity>
Чтобы назначить для виджета эту активность, нужно добавить ее в соответствующий тег appwidget-provider с помощью атрибута configure, указав полное имя пакета:
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" ... android:configure="com.hacker.widgetSample.WidgetSetup" />
Активность настройки ничем не отличается от обычной, но должна указать RESULT_OK
в качестве результата и вернуть намерение с дополнительным параметром EXTRA_APPWIDGET_ID
, являющимся идентификатором виджета. В противном случае считается, что пользователь отменил свое решение (например, нажал «Назад»), и виджет не будет добавлен.
Фрагмент активности:
Извини, но продолжение статьи доступно только подписчикам
Подписка позволит тебе читать ВСЕ платные материалы сайта, включая эту статью, без каких-либо ограничений. Мы принимаем банковские карты, Яндекс.Деньги и оплату со счетов мобильных операторов. Подробнее о проекте
1 год2700 Р Экономия 1400 рублей! |
1 месяц400 Р |
Уже подписан?
Читайте также
- Ошибка в API Facebook предоставляла доступ к фото 6,8 млн пользователей
- Одного ноутбука оказалось достаточно для компрометации всей корпоративной сети
- Депутаты Госдумы разработали план по обеспечению работы Рунета на случай отключения от Сети
- Морские суда часто подвергаются кибератакам
- 25 декабря состоится встреча сообщества специалистов по кибербезопасности АСУ ТП / RUSCADASEC
- Уязвимость в приложении Logitech позволяла удаленно инициировать нажатие клавиш