На сегодняшний день уже опубликовано большое количество учебного материала, в котором подробно, по шагам описывается процесс создания простого App Widget в стиле «HelloWorld». Под App Widget-ами подразумеваются приложения, которые можно поместить на основной экран в ОС Android. Как правило это различные индикаторы (состояние батареи, яркость экрана, погода, твитты, пробки и т.д.). На мой взгляд лучшим руководством является статья, размещенная непосредственно на сайте гугл.
Здесь мне хотелось больше уделить внимание общей схеме работы с AppWidget-ами и некоторым особым моментам работы с ними. Публикация сделана на основе моего собственного опыта и актуальна на момент написания публикации, но поскольку платформа Android очень быстро развивается, при изучении этой статьи в будущем прошу сверяться с текущей официальной документацией.
Почему виджеты.
Идея попробовать написать свои виджеты возникла у меня давно, но до реальных опытов руки все-таки не доходили. По большому счету, для меня основным мотивов их создания было и остается любопытство и желание сделать что-то забавное.
В итоге в декабре, перед новым годом все-таки удалось выкроить пару недель для плотной работы с ними.
Для пробы были сделаны и выложены на Маркете пара виджетов (бесплатных):
1. Рождественская ёлка, на игрушках которой загораются различные индикаторы (громкость, включен ли WiFi, заряд батареи и т.д.)
Сhristmas Tree Widget
2. Робот. Тоже пять-в-одном виджет — показывает уровень громкости, заряд батареи, включен ли Wi-Fi, 3G, вибро-режим.
Face Widget
Приложения сейчас не только бесплатные, но и без рекламы. Я просто еще не начинал разбираться с работой AdMob SDK. Возможно, если все-таки разберусь, напишу об этом позже.
Итак.
Принципиальные отличия в работе с виджетами и диаграмма классов.
При работе с виджетами самое главное — нужно понимать, что виджеты обновляются в специальном отдельном процессе. Например, если вы работаете внутри обычного активити, то поменять содержимое текстового поля можно просто вызвав метод setText в UI нитке.
Если говорить про AppWidget-ы, то для того, чтобы изменить состояние графического элемента (TextView, ImageView и т. д.), из которого он состоит, нужно использовать специальные классы и методы.
Упрощенно изменения осуществляются в два шага:
1. Вначале нужно воспользоваться объектом RemoteViews, чтобы указать, что именно вы планируете поменять (например, метод setTextViewText).
2. Затем с помощью AppWidgetManager применить изменения, передав созданный объект RemoteViews в метод update.
Если вы хотите обрабатывать событие нажатия на виджет, то это также можно сделать через объект класса RemoteViews с помощью метода setOnClickPendingIntent
Объект класса AppWidgetManager можно получить либо с помощью статического фабричного метода AppWidgetManager.getInstance(context). Также ссылка на менеджер виджетов передается в виде аргумента в методе onUpdate класса AppWidgetProvider.
Класс AppWidgetProvider наследуется от BroadcastReceiver. Поэтому желательно не забыть добавить его в файл AndroidManifest.xml и указать, где расположено xml-описание виджета:
<receiver android:name="ExampleAppWidgetProvider" > ... <meta-data android:name="android.appwidget.provider" android:resource="@xml/example_appwidget_info" /> </receiver> |
Подробное XML-описание виджета находится в XML-файле в папке res/xml/ и содержит в себе разные свойства и настройки виджета (размеры, активити для настройки, layout и т.д.).
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp" android:updatePeriodMillis="86400000" и т.д. > </appwidget-provider> |
Этому XML-файлу соответствует класс AppWidgetProviderInfo (еще раз повторюсь, подробные примеры и пошаговое описание создание виджета нужно смотреть на сайте гугла).
В целом, диаграмма класса может быть описана грубо следующем образом:
Анимация.
AnimationDrawable может работать, а может не работать. Зависит от конкретной модели телефона/планшета. Поэтому анимация – это больная тема для многих программистов, которые пытаются сделать анимированный виджет.
Стабильного универсального способа, который бы обеспечивал полноценную работу анимации на всех телефонах пока нет.
Есть два подхода:
1. Делать анимацию самому. Например, с определенной частотой меняя картинку у ImageView.
Здесь есть один нюанс, поскольку виджет работает в отдельном процессе, то при определенной частоте обновлений bitmap-ы перестанут «пролезать» через межпроцессорную связывалку. Как вариант можно передавать не сами картинки, а идентификаторы их ресурсов, но тогда ограничиваемся только существующим набором изображений.
2. Использовать неопределенный прогресс бар, установив для него свой ресурс для отрисовки indeterminateDrawable.
История изменений
API по работе с App Widget-ами наращивалось следующими образом:
- Появление виджетов. Level 3 (Android 1.5)
- Изменения размера пользователем. Коллекции. Level 11 (Android 3)
- Возможность добавления на экран блокировки. Level 17 (Android 4.2)
Итоги
С виджетами работать интересно, хотя и неудобно. У меня получилось, что времени на работу с ними ушло немного больше, чем планировал.
Сейчас, если удастся выкроить свободное время на эти приложения, то в первую очередь планирую заняться доработкой активити, но это уже скорее рутинная операция.
Благодарности.
В первую очередь огромное спасибо супер-программистке Татьяне за совместную работу и разработку активити.
За бета-тестирование и замечания — Вове (Московскому), Нику (Лондонскому), Даниэлю (Балийскому), Беке, Гарику, Артуру и Валерии (Ива Виннер). Если кого забыл, прошу прощения, не специально.
Отдельно хочу поблагодарить художника Гришу за суперский дизайн и графику!