Главная » Разработка для Android » СОЗДАНИЕ ВИДЖЕТА ДЛЯ ДОМАШНЕГО ЭКРАНА

0

Вопросы, рассматриваемые в этом часе:

•     подготовка дизайна и разработка виджета;

•     обработка событий, генерируемых виджетом в результате действий поль­зователя;

•     работа со службами.

В этом часе вы создадите виджет для приложения «Been There, Done That!». В частности, вы создадите простой виджет в виде элемента управления, который можно добавлять на домашний экран пользователя и который будет отображать аватар пользователя, его ник и информацию о набранных очках, а также предоставлять пользователю возможность продолжить игру.

ПОДГОТОВКА ДИЗАЙНА ВИДЖЕТА

Инструментарий Android SDK предоставляет разработчикам интересную возможность реализации функциональности, выходящей за рамки традиционных приложений для мобильных устройств, — с использованием виджетов. Разработчики могут использовать интерфейс API виджетов для создания маленьких элементов управления или представлений, которые могут быть добавлены на домашний экран пользователя. Эти простые элементы управления могут предоставлять пользователю информацию о приложении и напоминать ему в нужный момент о необходимости запустить приложение.

Виджеты могут оказаться полезными для определенных типов приложений, например, для тех приложений, которые должны сообщать пользователю о некотором статусе или обновлении информации. Приложение прогноза погоды может иметь виджет, который отображает текущие погодные условия для заданного местоположения на домашнем экране. Приложение, управляющее задачами, может иметь виджет, который информирует пользователя о следующей задаче в его списке задач или о том, какое количество задач осталось выполнить на сегодня. Приложение для работы с галереей изображений может иметь виджет, который используется для отображения слайд- шоу, включающего все изображения из галереи.

В этом часе вы создадите простой виджет для приложения «Been There, Done That!». Этот виджет будет выполнять следующее:

•     отображать аватар пользователя;

•     отображать ник пользователя;

•     отображать текущий результат игры пользователя;

•     запускать приложение «Been There, Done That!», когда пользователь нажмет на виджет.

Описание свойств виджета

Описание виджета и свойства его конфигурации задаются в отдельном XML-файле, ссылка на который добавляется в файл манифеста Android. (Подробнее об этом чуть позже.)

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

• Размер. Ширина и высота виджета, выражаемая в независимых от разрешения пикселах (dp или dip), которые применяются для определения количества ячеек таблицы на домашнем экране, необходимых для правильного отображения виджета.

ЗНАЕТЕ ЛИ ВЫ, ЧТО ____________________________________________________

Домашний экран операционной системы Android организован в виде ячеек таблицы, которые обычна представляют собой квадрат с размерами 74×74 пикселов. В каждой ячейке может размещаться только один элемент, например виджет или ярлык прило­жения. Таким образом, элементы на домашнем экране не перекрывют друг друга.

•     Частота обновлений. Интервал (в миллисекундах) между системными вызовами провайдера виджета для обновления содержимого виджета.

•     Исходный макет. Файл макета, используемый при первоначальном добавлении виджета. В дальнейшем этот макет может быть изменен программным путем.

•     Деятельность конфигурации. Описание запускаемой деятельности для настройки различных аспектов виджета перед его первоначальным отображением.

Чтобы добавить описание виджета для данного примера, начните с добавления нового XML-файла с именем widget_info.xml в папку /res/xml. Поместите в этот файл следующее описание виджета:

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider

xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="14 6dp" android:minHeight="14 6dp" android:updatePeriodMillis="10800000" android:initialLayout="@layout/widget"> </appwidget-provider>

В этом файле определяется виджет, который будет обновляться каждые три часа и занимать две ячейки таблицы по вертикали и две ячейки таблицы по горизонтали. Если провести несложные вычисления, вы, возможно, заметите, что значение 146dp, указанное для каждого измерения виджета, нельзя получить путем умножения размера ячейки таблицы (74dp) на два. И хотя размер ячейки таблицы обычно равен значению 74dp, при вычислении размеров вы должны вычитать значение 2dp из итогового результата. В данном примере мы умножили 74 на 2 и получили 148. Затем мы вычли 2 из произведения и получили число 146, которое и указали в файле. Если бы мы не сделали этого, для отображения виджета могло использоваться большее число ячеек таблицы.

Обновление этого виджета будет происходить каждые 10.800.000 миллисекунд, что соответствует трем часам. Кроме всего прочего, этот виджет изначально будет использовать предопределенный макет, который указан в строке android: initialLayout="@layout/widget". Содержимое этого файла макета будет рассмотрено чуть позже.

Обновление файла манифеста Android

Вы должны обновить файл манифеста Android, чтобы сообщить системе, где находится описание виджета. Виджет представляет собой особую реализацию элемента

BroadcastReceiver.

Следовательно, в файл AndroidManifest.xml должен быть добавлен раздел <receiver>, определяющий получаемые интенты и некоторую другую информацию, относящуюся непосредственно к виджету.

Чтобы решить данную задачу, добавьте следующий раздел <receiver> в раздел <application> файла AndroidManlfastxml:

<receiver

android:name="QuizWidgetProvider"> <intent-filter> <action

android:name= "android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data

android:name="android.appwidget.provider" android:resource="@xml/widget info" /> </receiver>

Представленный раздел <receiver> файла манифеста Android определяет фильтр для интентов, используемых для обновления виджета. Кроме того, он также связывает виджет и его файл описания с основным приложением.

Разработка дизайна макета виджета

К макетам виджетов предъявляются специфические требования. Начнем с того, что отображение виджета осуществляется через интерфейс RemoteViews, накладывающий ограничения на элементы пользовательского интерфейса, которые могут отображаться на экране. Далее, размеры содержимого виджета должны соответствовать размерам, указанным в свойствах данного виджета.

Объект типа RemoteViews используется в тех случаях, когда отображение элемента- представления будет осуществляться из другого процесса. Это именно то, что происходит с виджетом: он отображается из хост-процесса виджетов, а не из основного процесса приложения. В объектах типа RemoteViews допускается использование элементов- контейнеров и элементов-представлений определенных типов. Ниже перечислены некоторые элементы-контейнеры и элементы-представления, поддерживаемые видже- тами:

•      LinearLayout;

•      FrameLayout;

•     RelativeLayout;

•     TextView;

•     ImageView;

•     Button;

•     ImageButton;

•     ProgressBar;

•    AnalogClock;

•     Chronometer.

Использование классов, расширяющих эти элементы макт, не допускается. Это значит, что дизайнер в своих действиях крайне ограничен Но, несмотря на то, что виджеты не предназначены для отображения большого количества информации, когда требуются более мощная функциональность или сложные макеты экранов, вы можете расширить возможности виджета путем запуска с его помощью полноценной деятельности. Деятельность может быть использована для отображения целого экрана или просто всплывающего экрана. В любом случае, на деятельности, запускаемые при помощи виджета, больше не распространяются ограничения, налагаемые на сам виджет и обусловленные использованием объекта типа RemoteViews.

Чтобы подготовить макет виджета, создайте новый файл макета с именем widget.xml и поместите в него следующий код:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout

xmlns:android= "http://schemas.android.com/apk/res/android" android:layout width="wrap content" android:layout height="wrap content" android:id="@+id/widget view"> <ImageView

android:layout centerInParent="true" android:layout height="fill parent" android:layout width="fill parent" android:id="@+id/widget image"></ImageView> <TextView

android:text="@+id/TextView01" android:layout width="wrap content" android:layout height="wrap content" android:layout alignParentTop="true" android:layout centerHorizontal="true" android:id="@+id/widget nickname"></TextView> <TextView

android:text="@+id/TextView02" android:layout width="wrap content" android:layout height="wrap content" android:layout centerHorizontal="true" android:layout alignParentBottom="true" android:id="@+id/widget score"></TextView> </RelativeLayout>

Реализация виджет-провайдера

Теперь, когда у вас есть конфигурация виджета, вам нужно реализовать сам виджет. Для этого необходимо расширить класс AppWidgetProvider, содержащий пять методов, которые могут быть переопределены:

•     onUpdate() — этот метод вызывается по истечении интервала времени, указанного в свойствах виджета.

•     onDeleted() — этот метод вызывается каждый раз, когда происходит удаление виджета.

•     onEnabied() — этот метод вызывается при создании первого экземпляра виджета, но не вызывается при создании последующих экземпляров.

•     onDisabied() — этот метод вызывается в том случае, когда удаляется последний экземпляр данного виджета.

•     onReceive() — этот метод вызывается для всех получаемых широко­вещательных событий; в стандартной реализации данного метода вызываются все вышеперечисленные методы обработки событий (методы onUpdate(), onDeleted(), onEnabled() и onDisabied()). Этот метод может быть переопределен, когда требуется реализовать нестандартное поведение.

В этом примере необходимо переопределить только метод onUpdate() для обновления содержимого объекта типа RemoteViews. Поскольку поддержка автономной установки виджета не требуется, переопределять другие методы нет никакой необходимости. Итак, ниже представлена реализация класса, расширяющего класс AppWidgetProvider:

public class QuizWidgetProvider2 extends AppWidgetProvider { @Override

public void onUpdate(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetIds) { WidgetData widgetData = new WidgetData("Unknown", "NA", ""); getWidgetData(widgetData);

String packageName = context.getPackageName(); RemoteViews remoteView =

new RemoteViews(context.getPackageName(), R.layout.widget); remoteView.setTextViewText(

R.id. widget nickname, widgetData.nickname); remoteView.setTextViewText(

R.id.widget score, "Score: " + widgetData.score); if (widgetData.avatarUrl.length() > 0) { URL image; try {

image = new URL(widgetData.avatarUrl);

Bitmap bitmap =

BitmapFactory.decodeStream(image.openStream()); if (bitmap == null) {

Log.w(DEBUG_TAG, "Failed to decode image"); remoteView.setImageViewResource(

R.id.widget image, R.drawable.avatar); } else {

remoteView.setImageViewBitmap(

R.id.widget image, bitmap);

}

} catch (MalformedURLException e) {

Log. e(DEBUG_TAG, "Bad url in image", e); } catch (IOException e) {

Log.e(DEBUG_TAG, "IO failure for image", e);

}

} else {

remoteView.setImageViewResource(

R.id.widget image, R.drawable.avatar);

}

try {

ComponentName quizWidget =

new ComponentName(context, QuizWidgetProvider.class); AppWidgetManager appWidgetManager =

AppWidgetManager.getlnstance(context); appWidgetManager.updateAppWidget(quizWidget, remoteView); } catch (Exception e) {

Log. e(DEBUG_TAG, "Failed to update widget", e);

} }

private void getWidgetData(WidgetData widgetData) { }

}

Сначала вам нужно получить данные, которые будут отображаться в виджете. Эту задачу выполняет метод getWidgetData(), получая идентификатор игрока из экземпляра класса SharedPreferences и затем загружая данные с сервера. Загрузка данных осуществляется именно с сервера, а не непосредственно из экземпляра класса SharedPreferences, поскольку в дальнейшем такой подход позволит легко изменить метод getWidgetData() для загрузки данных друзей или других игроков.

После этого вы создаете объект типа RemoteViews. При инициализации данного объекта требуется указать не только используемый макет, но и пакет, к которому принадлежит этот макет. Напомним, что объект типа RemoteViews не будет отображаться из того же процесса, в котором выполняется приложение, поэтому для доступа к ресурсам этому объекту требуется дополнительная информация.

У вас есть доступ к информации о нике пользователя и набранных им очках (или указанным значениям по умолчанию), поэтому вы можете поместить эту информацию в объект типа RemoteViews при помощи метода setTextViewText(), передав в него соответствующий идентификатор элемента макета и значение, которое должно отображаться в этом элементе. Код для передачи изображения аватара в объект типа RemoteViews отдаленно напоминает предыдущий код, однако сначала происходит проверка доступности указанного адреса URL для изображения аватара и что данное изображение может быть декодировано. Наконец, изображение аватара передается в объект типа RemoteViews путем вызова метода setImageViewBitmap() или метода setImageViewResource() .

После этого вы должны непосредственно обновить виджет. Для этого используется метод updateAppWidget() класса AppWidgetManager. В этот метод передается объект

типа RemoteViews и объект типа ComponentName для класса QuizWidgetProvider, получаемый путем непосредственного создания экземпляра класса ComponentName.

КСТАТИ ________________________________________________________________

Если вы внимательно изучили представленный код, возможно, вы заметили, что два параметра метода onUpdate() — appWidgetManager и appWidgetIds – не ис­пользуются. Параметр appWidgetManager не используется потому, что вы скоро переместите код в другой метод, где экземпляр класса AppWidgetManager будет получаться отдельно. Параметр appWidgetIds используется в тех случаях, когда необходимо поддерживать несколько уникальных экземпляров виджета, которые ото­бражают разные данные. В данном случае приложение должно отслеживать отдельные значения параметра appWidgetIds, которые генерируются системой, и сопоставлять их с данными, которые должны отображаться в каждом экземпляре виджета. Обычно это осуществляется путем использования отдельной конфигурационной деятельности для каждого экземпляра виджета, благодаря чему пользователь может управлять теми данными, которые должны отображаться в каждом отдельном экземпляре этого вид- жета.

Теперь созданный виджет должен появиться в списке виджетов домашнего экрана, как показано на рис. 18.1.

Рис. 18.1. Добавление виджета на домашний экран

ВЫПОЛНИТЕ САМОСТОЯТЕЛЬНО _______________________________

Чтобы добавить виджет на домашний экран телефона работающего под управлением

операционной системы Android или эмуляторе, выполните следующие простые шаги:

1.   Откройте домашний экран.

2.      Найдите подходящую область на экране. (Помните что для виджета приложения «Been There, Done That!» требуются две ячейки по горизонтали и две – по вертикали).

3.      Нажмите и удерживайте ваш палец (или щелкните и удерживайте кнопку мыши при использовании эмулятора).

4.      Когда на экране появится меню Add to Home Screen (Добавить на главный экран), выберите пункт Widgets (Виджеты).

5.      В открывшемся меню Choose widget (Выбор виджета) выберите виджет, который вы только что создали (или любой другой виджет), чтобы добавить его на ваш домашний экран.

Виджет будет выглядеть аналогично тому, который изображен на рис 18.2.

Рис. 18.2. Виджет приложения «Been There, Done That!»

ОБРАБОТКА СОБЫТИЙ, ГЕНЕРИРУЕМЫХ ВИДЖЕТОМ В РЕЗУЛЬТАТЕ ДЕЙСТВИЙ ПОЛЬЗОВАТЕЛЯ

На данном этапе созданный вами виджет работает, однако он представляет весьма скромные интерактивные возможности. Вы хотите, чтобы он не просто отображал информацию для пользователя, – вы хотите чтобы он также возвращал пользователя в приложение. Еще одна возможная область для улучшения виджета – изящная обработка ситуаций, связанных с медленной загрузкой изображений аватаров.

Виджеты отображаются через объекты типа RemoteView, а не и приложения, в котором они создаются. Отображение виджетов осуществляется из виджет-хоста. Это обстоятельство влияет на способ обработки событий, связанных с действиями пользователя. Если вернуться к списку элементов представлений, поддерживаемых виджетом, вы увидите, что в этом списке отсутствуют поля ввода. По существу, единственное событие, поддерживаемое виджетом, – это нажатие.

КСТАТИ________________________________________________________________

Возможно, вы встречали виджеты, например, виджет сети Facebook, которые выглядят как поля ввода EditText. Тем не менее, если вы нажмете на них, чтобы ввести текст вы увидите, что во всех случаях для ввода используется другой пользовательский ин­терфейс. Это отличный способ предоставить пользователю элементы с расширенной функциональностью, тем самым обойдя ограничение платформы разработчика видже- тов.

Поскольку отображение виджета осуществляется не из этого процесса, в котором выполняется приложение, для получения событий нажатий требуется новый подход. Инструментарий Android SDK предоставляет для этих целей специальный тип интента под названием PendingIntent. Это интент, который еще только будет отправлен когда- то впоследствии и, возможно, из другого процесса. Чтобы создать интент типа PendingIntent, сначала необходимо создать экземпляр класса Intent. После этого создается экземпляр класса PendingIntent с некоторой дополнительной информацией, например с указанием того, что делать при последующем использовании того же интента. То есть может быть использован тот же экземпляр или создан новый экземпляр. Как только объект типа PendingIntent будет создан, его можно связать с объектом типа RemoteView, вызвав метод setonClickPendingIntent() . Вам нужно добавить следующий код перед вызовом метода updateAppWidget () .

Intent launchAppIntent =

new Intent(context, QuizMenuActivity.class); PendingIntent launchAppPendingIntent =

PendingIntent.getActivity(context, 0, launchAppIntent, PendingIntent. FLAG_UPDATE_CURRENT); remoteView.setOnClickPendingIntent(

R.id. widget_view, launchAppPendingIntent);

Идентификатор элемента-представления, с которым связывается объект типа PendingIntent путем вызова метода setClickpendingIntent(), указывает на элемент-контейнер RealativeLayout из файла макета widget.xml. Теперь, когда пользователь нажмет на виджет, запустится деятельность QuizmenuActivity; именно эта деятельность запускается при открытии приложения «Been There, Done That!». (Обратите внимание, что по нажатию можно запустить любую деятельность, например, деятельность, отображающую результаты игры, однако в данном случае деятельность QuizMenuActivity имеет наибольший смысл.)

ЗНАЕТЕ ЛИ ВЫ, ЧТО… __________________________________________________

При создании динамического виджета с отдельными элементами-представления могут быть связаны свои собственные объекты типа PendingIntent. В этом случае от­правляемые запросы приводят к вызову метода updateAppWidget (), позволяя изменить по нажатию внешний вид виджета.

ВЫПОЛНЕНИЕ ФОНОВЫХ ОПЕРАЦИЙ В ВИДЖЕТЕ

Возможно, вы считаете, что, поскольку виджет не выполняется в процессе приложения, вам не нужно беспокоиться об операциях, которые могут занимать достаточно длительное время. Также, возможно, вы предполагаете, что. поскольку виджет представляет собой объект типа BroadcastReceiver, он будет автоматически выполнять все операции в фоновом режиме. Оба предположения неверны.

Для операций, которые могут занимать продолжительное время, обычно запускается отдельный поток, в котором выполняются необходимые задачи. Тем не менее в случае с виджетами запустить отдельный поток не представляется возможным. Вместо этого, вы должны создать и запустить экземпляр класса Service, представляющий службу в операционной системе Android, и уже из этой службы можно запустить фоновый поток. Служба в операционной системе Android предоставляет две полезных возможности: она позволяет осуществлять выполнение задач в фоновом режиме, и она может предоставлять интерфейс к удаленному объекту, например доступ к расширениям или к программным библиотекам.

КСТАТИ ________________________________________________________________

Почему нельзя использовать класс Thread непосредственно в виджете? И, хотя подробное рассмотрение этой особенности выходит за рамки данной книги, попробуем ответить коротко: когда завершает выполнение метода onUpdate (), процесс виджета может также завершится, попутно уничтожив все выполняющиеся потоки. В отличии от этого, экземпляр класса Service, представляющий службу в операционной сис­теме Android, удален не будет, и поэтому вы можете использовать его для выполнения фоновых операций.

Рис. 18.3. Экран Running Services

(Работающие программы)

Вы можете увидеть все службы, выполняющиеся в данный момент на мобильном устройстве Android или на эмуляторе, выбрав приложение Settings (Настройки) в списке приложений, а затем выбрав в меню команд) Applications (Приложения) и затем команду Running Services (Работающие программы). Здесь вы также можете завершить выполнение выбранной службы. На рис. 18.3 изображен экран Running Services (Работающие программы).

Создание службы

Объект типа Service создается путем расширения класса Service, переопределением трех основных методов и описанием соответствующей службы в файле AndroidManifest.xml. Для приложения «Been There, Done That!-» вы должны определить объект типа Service в классе OuizWidgetProvider. Затем вы можете перенести большую часть кода из метода onUpdate() в метод onStartCommand() объекта типа Service и создать объект типа Thread, который будет выполнять всю работу, чтобы виджет и служба могли продолжать реагировать на действия пользователя.

ЗНАЕТЕ ЛИ ВЫ, ЧТО… __________________________________________________

Жизненный цикл экземпляра класса Service отличается от жизненного цикла экзем­пляра класса Activity. Поскольку предоставленный пример был упрощен, вы не увидели полный жизненный цикл службы. Тем не менее, в сущности, после вызова метода onCreate() происходит вызов либо метода onStartCommand(), либо метода onBind (), в зависимости от типа службы и способа ее запуска. Когда служба завершает свою работу в нормальном режиме или когда не остается процессов, связан­ных со службой, вызывается метод onDestroy () .

Добавьте следующий код в класс QuizWidgetProvider:

public static class WidgetUpdateService extends Service { Thread widgetUpdateThread = null;

private static final String DEBUG_TAG = "WidgetUpdateService"; @Override

public int onStartCommand(Intent intent, int flags, final int startId) {

widgetUpdateThread = new Thread() { public void run() {

// code moved from onUpdate() method

}

};

widgetUpdateThread.start(); return START_REDELIVER_INTENT;

}

@Override

public void onDestroy() {

widgetUpdateThread.interrupt();

super.onDestroy();

}

@Override

public IBinder onBind(Intent intent) {

// no binding; can’t from an App Widget return null;

}

}

Так выглядела бы реализация службы, если бы код из метода onUpdate () был перемещен в метод run () потока, созданного в методе onStartCommand () .

КСТАТИ ________________________________________________________________

Полная реализация виджета доступна на диске, прилагаемом к данной книге.

Теперь необходимо обновить файл манифеста Android, чтобы система знала о данной службе. Для этого добавьте следующий блок <service> раздел <application> файла манифеста:

<service

android:name="QuizWidgetProvider$WidgetUpdateService" /> Этот код сообщает системе о существовании службы и о том, где она находится.

Управление службой

Теперь вы должны запустить службу из метода onUpdate() виджета. Вы можете запустить службу одним из двух способов: либо путем вызова метода Context. startService(), либо путем вызова метода Context.bindService() . В данном примере используется метод startService() после замены метода onUpdate() следующим кодом:

@Override

public void onUpdate(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetIds) { Intent serviceIntent = new Intent(context, WidgetUpdateService.class); context.startService(serviceIntent);

}

Когда служба завершит выполнение поставленной задачи, желательно остановить эту службу, чтобы освободить ценные системные ресурсы. Виджет будет обновляться каждые три часа. И, хотя со службой можно ничего не делать — она будет бездействовать, — воз­можно, вы захотите остановить эту службу до тех пор, пока она не понадобится снова. Этот результат достигается путем добавления следующего кода в конец метода run() класса Thread, который вы используете для выполнения фоновых задач:

if (!WidgetUpdateService.this.stopSelfResult(startId)) {

Log. e(DEBUG_TAG, "Failed to stop service");

}

Вызов метода stopSelfResult() отправляет службе сигнал об остановке и возвращает информацию о том, был ли вызов успешным или нет. Если результат вызова данного метода вас не интересует, вы можете просто вызвать метод stopSelf() . Вызов этого метода происходит в тот момент, когда обработка данных в потоке уже завершена, и больше нет смысла продолжать выполнение службы, поскольку в данном случае новых задач больше нет. Служба может быть запушена снова при последующем обновлении виджета, что для данного виджета произойдет по истечении трех часов.

Ест и виджет будет удален из своего хоста, например домашнего экрана, во время выполнения операции обновления, службу придется завершать другим способом. Для этого поместите следующий код метода onDeleted() в реализацию класса

AppWidgetProvider:

@Override

public void onDeleted(Context context, int[] appWidgetIds) { Intent serviceIntent = new Intent(context, WidgetUpdateService.class); context.stopService(serviceIntent); super.onDeleted(context, appWidgetIds);

}

Вызов метода StopService о приводит к вызову метода onDestroy() класса

Service, который, в свою очередь, пытается прервать выполнение

потока.

КСТАТИ ________________________________________________________________

Пример, представленный в данном часе, достаточно прост. Все будет работать пре­красно для одного экземпляра виджета. Тем не менее, если вы захотите добавить под­держку нескольких экземпляров виджета, выполняющихся одновременно, вам понадо­бится реализовать код, который позволит проводить различия между экземплярами виджета.

ИТОГИ

В этом часе вы создали простой виджет для приложения «Been There, Done That!», который отображает аватар пользователя, его ник и набранные очки. В этом часе были рассмотрены все детали реализации виджета, включая разработку дизайна макета и описание свойств виджета. Вы также добавили простейшую обработку событий, позволяя пользователю нажать на виджет, чтобы запустить приложение «Been There, Done That!». Наконец, вы использовали фоновую службу для выполнения обработки событий виджета и обновления его содержимого.

ВОПРОСЫ И ОТВЕТЫ

Вопрос: Домашний экран — это единственное место, где можно размещать виджеты?

Ответ: Нет. Виджеты могут размещаться в любом виджет-хосте. Домашний экран — это просто то место, где виджеты используются чаще всего. Дополнительную информацию можно найти в документами по классам AppWidgetHost и AppWidgetHostView.

Вопрос: Как можно добавить в виджет дополнительные интерактивные возможности, например, элементы Button?

Ответ: Если вы хотите добавить элементы управления пользовательского интерфейса в виджет и предоставить пользователю возможность обновлять содержимое виджета, вам потребуется описать каждое событие по отдельности и реализовать соответствующие обработчики событий нажатий для отправки определенных команд, связанных с событиями, посредством объектов типа PendingIntent в зарегистрированный получатель объектов типа Intent. Затем приложение виджета должно получить эти команды и обработать их соответствующим образом, при необходимости обновив со­держимое виджета. Вы можете найти полнофункциональный пример интерактивного виджета в статье «Handling User Interaction with Android App Widgets», которая доступна по адресу www.developer.com/ws/artide.php/3837531/Handling-User-lnteraction-with- Android-App-Widgets.htm.

Вопрос: Могу ли я создать несколько экземпляров виджета?

Ответ: Для виджета, который вы реализовали для приложения «Been There, Done That!», создание нескольких экземпляров не имеет смысла. Тем не менее в определенных ситуациях бывает полезно предоставить пользователю возможность создания нескольких экземпляров виджета с разными конфигурациями. Один из способов решить эту задачу — предоставить пользователю возможность настройки каждого экземпляра виджета при помощи конфигурационной деятельности, указанной для данного вцджета. После этого приложение должно отслеживать различия между созданными экземплярами, запоминая настройки, указанные пользователем, для каждого идентификатора экземпляра виджета. Мы также рассмотрели эту интересную тему в статье «Handling User Interaction with Android App Widgets» (дополнительную информацию можно найти в ответе на предыдущий вопрос).

ПРАКТИКУМ Контрольные вопросы

1.                                Верно ли это? Виджеты могут размещаться только на домашнем экране.

2.                                 Укажите пример элемента-представления, который не может быть ис­пользован в виджете:

A.                                Button.

B.                                WebView.

C.                                ProgressBar.

4.

3.                                                               Верно ли это? Несмотря на то, что размеры виджетов определяются

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

С какой целью в виджетах применяются службы?

Для выполнения продолжительных фоновых операций. Б. Дня выполнения рисования непосредственно на экране. Для доступа к конфиденциальным данным.

Ответы

3.                                                   Неверно. Виджеты могут размешаться в любом приложении, в котором используется объект типа AppWidgetHost.

4.                                                   B. Элементы Button и ProgressBar могут использоваться, а элемент- представление WebView — нет.

5.                                                   Верно. Размеры каждой ячейки составляют 74 пикселов по

горизонтали и по вертикали, но если вы планируете размещать виджет в нескольких ячейках, от полученной суммы необходимо отнять 2 пиксела. Таким образом, ширина двух соседних ячеек будет равна (72 х 2) — 2, или 146 пикселам.

A.        

B.        

C.        

a.Виджет выполняется в другом процессе, поэтому он должен всегда реагировать на запросы. Класс Thread нельзя использовать для этих целей, поскольку его экземпляр может быть уничтожен, когда завершится выполнение кода, связанного с обновлением содержимого виджета. Таким образом, служба запускается для выполнения фоновых операций.

Литература: Дэрси JI., Android за 24 часа. Программирование приложений под операционную систему Google/ ДэрсиЛ., КондерШ. — М.: Рид Групп, 2011. — 464 с. — (Профессиональные компьютерные книги). ISBN 978-5-4252-0318-2

По теме:

  • Комментарии