Виджеты приложений предоставляют пользователям легкий доступ к наиболее часто используемым функциям вашего приложения, в то же время предоставляя вашему приложению доступ к домашнему экрану пользователя. Добавив виджет в ваш проект, вы можете обеспечить лучший пользовательский опыт, поощряя пользователей продолжать работать с вашим приложением, поскольку каждый раз, когда они смотрят на свой домашний экран, они видят ваш виджет, отображая некоторые из наиболее полезных и полезных приложений вашего приложения. интересный контент.
В этой серии из трех частей мы создаем виджет приложения, который обладает всеми функциями, которые есть практически во всех виджетах приложений Android.
В первом посте мы создали виджет, который извлекает и отображает данные и выполняет уникальное действие в ответ на события onClick
. Затем во втором посте мы расширили наш виджет, чтобы получать и отображать новые данные автоматически по расписанию и в ответ на взаимодействие с пользователем .
Мы начинаем с того места, где остановились, поэтому, если у вас нет копии виджета, созданного в первой части, вы можете загрузить ее с GitHub .
Улучшение виджета с помощью действия по настройке
Хотя наш виджет работает «из коробки», некоторые виджеты требуют начальной настройки — например, виджет, отображающий сообщения пользователя, будет требовать их адрес электронной почты и пароль. Возможно, вы также захотите дать своим пользователям возможность настраивать виджет, например изменять его цвет или даже изменять его функциональные возможности, например, как часто обновляется виджет.
Если ваш виджет настраиваемый или требует какой-либо настройки, вы должны включить конфигурационное действие , которое запустится автоматически, как только пользователь поместит виджет на свой домашний экран.
Действия по настройке также могут пригодиться, если у вас есть много идей об информации и функциях, которые вы хотите включить в свой виджет. Вместо того, чтобы втиснуть весь этот контент в сложный и потенциально запутанный макет, вы можете предоставить конфигурационное действие, где пользователи выбирают контент, который им важен.
Если вы включите конфигурационное задание, то не увлекайтесь, поскольку есть момент, когда выбор становится слишком большим . Настройка виджета не должна быть сложной, поэтому рекомендуется ограничить свой виджет двумя или тремя вариантами конфигурации. Если вы изо всех сил пытаетесь не превысить этот предел, подумайте, действительно ли необходим весь этот выбор, или он просто добавляет ненужную сложность процессу установки.
Чтобы создать конфигурацию Activity, вам необходимо выполнить следующие шаги.
1. Создайте макет деятельности
Это точно так же, как создание макета для обычной деятельности, поэтому создайте новый файл ресурсов макета и добавьте все элементы пользовательского интерфейса, как обычно.
Активность конфигурации — это место, где пользователь выполняет начальную настройку, поэтому, как только он завершит эту операцию, он вряд ли будет нуждаться в ней снова. Поскольку компоновка виджета уже меньше обычной компоновки «Активность», вам не следует тратить драгоценное пространство, предоставляя пользователям возможность перезапустить активацию конфигурации непосредственно из компоновки виджета.
Здесь я создаю простой файл ресурсов макета configuration_activity.xml, содержащий кнопку, при нажатии которой создается виджет приложения.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?xml version=»1.0″ encoding=»utf-8″?>
http://schemas.android.com/apk/res/android»
android:layout_width=»match_parent»
android:layout_height=»match_parent» >
<Button
android:id=»@+id/setupWidget»
android:layout_width=»fill_parent»
android:layout_height=»wrap_content»
android:layout_alignParentLeft=»true»
android:layout_marginTop=»175dp»
android:text=»Create widget»
android:textColor=»#FFFFFF» />
<TextView
android:layout_width=»fill_parent»
android:layout_height=»wrap_content»
android:layout_alignBottom=»@+id/setupWidget»
android:layout_alignParentLeft=»true»
android:layout_marginBottom=»67dp»
android:text=»Configuration options go here!»
</RelativeLayout>
|
2. Создайте свой класс конфигурации
Ваше действие по настройке должно включать идентификатор виджета приложения, переданный Intent
, запустившим действие по настройке.
Если вы включили действие конфигурации, то обратите внимание, что метод onUpdate()
не будет вызываться, когда пользователь создает экземпляр виджета, поскольку широковещание ACTION_APPWIDGET_UPDATE
не отправляется при запуске действия конфигурации. Ответственность за запрос первого обновления прямо из AppWidgetManager
на деятельности по AppWidgetManager
. Метод onUpdate()
будет вызываться как обычно для всех последующих обновлений.
Создайте новый класс Java с именем configActivity
и добавьте следующее:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.os.Bundle;
import android.widget.Button;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
public class configActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.configuration_activity);
setResult(RESULT_CANCELED);
Button setupWidget = (Button) findViewById(R.id.setupWidget);
setupWidget.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleSetupWidget();
}
});
}
private void handleSetupWidget() {
showAppWidget();
}
int appWidgetId;
private void showAppWidget() {
appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
//Retrieve the App Widget ID from the Intent that launched the Activity//
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
appWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
//If the intent doesn’t have a widget ID, then call finish()//
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
//TO DO, Perform the configuration and get an instance of the AppWidgetManager//
…
…
…
//Create the return intent//
Intent resultValue = new Intent();
//Pass the original appWidgetId//
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//Set the results from the configuration Activity//
setResult(RESULT_OK, resultValue);
//Finish the Activity//
finish();
}
}
}
|
3. Объявите активность по настройке в манифесте вашего проекта
Когда вы объявляете свою конфигурационную активность в манифесте , вам нужно указать, что она принимает действие ACTION_APPWIDGET_CONFIGURE
:
1
2
3
4
5
|
<activity android:name=».configActivity»>
<intent-filter>
<action android:name=»android.appwidget.action.APPWIDGET_CONFIGURE»/>
</intent-filter>
</activity>
|
4. Объявите действие по настройке в файле AppWidgetProviderInfo
Поскольку на активность конфигурации ссылаются за пределы области действия вашего пакета, вам необходимо объявить ее, используя полное пространство имен:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<?xml version=»1.0″ encoding=»utf-8″?>
http://schemas.android.com/apk/res/android»
android:initialKeyguardLayout=»@layout/new_app_widget»
android:initialLayout=»@layout/new_app_widget»
android:minHeight=»40dp»
android:minWidth=»40dp»
android:previewImage=»@drawable/example_appwidget_preview»
android:resizeMode=»horizontal|vertical»
android:updatePeriodMillis=»1800000″
android:widgetCategory=»home_screen»
//Add the following line//
android:configure=»com.jessicathornsby.widget.configActivity»>
</appwidget-provider>
|
Теперь, когда вы создаете новый экземпляр этого виджета, запускается конфигурирование Activity, и вам нужно будет выполнить все параметры в этом Activity, прежде чем ваш виджет будет создан. В данном случае это просто означает нажатие кнопки « Создать виджет» .
Помните, что вы можете загрузить готовый виджет , в комплекте с конфигурацией Activity, с GitHub.
Рекомендации по применению виджетов
На протяжении всей этой серии мы создавали виджет приложения, который демонстрирует все основные функции, которые вы найдете практически во всех виджетах приложений Android. К этому моменту вы знаете, как создать виджет, который извлекает и отображает данные, реагирует на события onClick
, обновляет новую информацию на основе расписания и в ответ на взаимодействие с пользователем, а также имеет настраиваемое изображение для предварительного просмотра.
Они могут быть основными строительными блоками виджетов приложений Android, но создания чего-то, что просто работает , никогда не достаточно — необходимо также убедиться, что ваш виджет обеспечивает хороший пользовательский опыт, следуя рекомендациям.
Выполнять трудоемкие операции вне основного потока
Виджеты имеют те же ограничения времени выполнения, что и обычные широковещательные приемники, поэтому они могут блокировать важнейший основной поток пользовательского интерфейса Android.
В Android есть один поток, в котором весь код приложения выполняется по умолчанию, и, поскольку Android может одновременно обрабатывать только одну задачу, этот важный поток легко заблокировать. Выполните любую длительную или интенсивную операцию в главном потоке, и пользовательский интерфейс вашего приложения не будет отвечать до завершения операции. В худшем случае это может привести к ошибке Android Not Application Responding ( ANR ) и сбоям приложения.
Если вашему виджету необходимо выполнять какие-либо трудоемкие или трудоемкие задачи, вам следует использовать службу, а не основной поток. Вы можете создать службу как обычно, а затем запустить ее в AppWidgetProvider
. Например, здесь мы используем сервис для обновления нашего виджета:
1
2
3
4
5
|
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
context.startService(new Intent(context, AppWidgetService.class));
}
}
|
Создать гибкий макет
Создание макета, который может адаптироваться к ряду конфигураций экрана, является одним из наиболее важных правил разработки для Android, и это правило распространяется и на виджеты. Как и обычные действия, макет вашего виджета должен быть достаточно гибким, чтобы отображаться и функционировать правильно, независимо от конфигурации экрана, но есть некоторые дополнительные причины, по которым макеты виджетов должны быть максимально гибкими.
Во-первых, если размер вашего виджета можно изменить, тогда пользователь может вручную увеличить или уменьшить размер вашего виджета, и вам не о чем беспокоиться в традиционных видах деятельности.
Во-вторых, нет никакой гарантии, что измерения minWidth
и minHeight
вашего виджета будут идеально совпадать с сеткой minWidth
minHeight
конкретного устройства. Когда виджет не идеально подходит, операционная система Android будет растягивать этот виджет по горизонтали и / или по вертикали, чтобы занимать минимальное количество ячеек, необходимое для удовлетворения ограничений виджета minWidth
и minHeight
. Хотя это не должно быть значительным увеличением, все же стоит отметить, что с самого начала ваш виджет может занимать больше места, чем вы ожидали.
Создание гибкого макета виджета следует тем же рекомендациям, что и разработка гибкого макета «Деятельность». По этой теме уже доступно много информации, но вот некоторые из наиболее важных моментов, которые следует учитывать при создании макетов виджетов:
- Избегайте абсолютных единиц измерения, таких как определение кнопки в пикселях. Из-за разной плотности экрана 50 пикселей не соответствуют одному физическому размеру на каждом устройстве. Таким
50px
кнопка50px
будет выглядеть больше на экранах с низкой плотностью и меньше на экранах с высокой плотностью. Вы должны всегда указывать размеры макета в единицах, не зависящих от плотности (dpi), и использовать гибкие элементы, такие какwrap_content
иmatch_parent
. - Предоставьте альтернативные ресурсы, оптимизированные для разных плотностей экрана. Вы также можете предоставить макеты, оптимизированные для экранов разных размеров, используя квалификаторы конфигурации, такие как
smallestWidth
(sw<N>dp
). Не забудьте указать версию каждого ресурса по умолчанию, чтобы в вашем приложении было что-то, к чему можно обратиться, если оно когда-либо обнаружит экран с характеристиками, для которых у него нет определенного ресурса. Вы должны разработать эти ресурсы по умолчанию для обычных экранов средней плотности . - Протестируйте свой виджет на как можно большем количестве экранов с помощью эмулятора Android. При создании AVD вы можете указать точный размер и разрешение экрана, используя элементы управления « Экран», которые отображаются в меню « Настроить этот профиль оборудования» . Не забудьте проверить, как ваш виджет обрабатывает изменение размера на всех этих разных экранах!
Не будите устройство
Обновление виджета требует заряда батареи, и операционная система Android не стесняется разбудить спящее устройство, чтобы выполнить обновление, которое усиливает влияние вашего виджета на батарею устройства.
Если пользователь понимает, что ваш виджет разряжает батарею, то по крайней мере он собирается удалить этот виджет со своего домашнего экрана. В худшем случае они могут даже полностью удалить ваше приложение.
Вы всегда должны стремиться обновлять свой виджет как можно реже, при этом отображая своевременную и актуальную информацию. Однако некоторые виджеты могут иметь законную причину для необходимости частых обновлений, например, если виджет содержит очень чувствительный ко времени контент.
В этом сценарии вы можете уменьшить влияние, которое эти частые обновления оказывают на срок службы батареи, выполняя обновления на основе сигнала тревоги, который не разбудит спящее устройство. Если этот сигнал тревоги сработает, когда устройство находится в спящем режиме, обновление не будет доставлено до следующего пробуждения устройства.
Для обновления на основе сигнала тревоги вам нужно использовать AlarmManager
чтобы установить сигнал тревоги с Intent
, которое получит ваш AppWidgetProvider
, а затем установить тип сигнала тревоги либо ELAPSED_REALTIME
либо RTC
, поскольку эти типы сигналов тревоги не будут ELAPSED_REALTIME
спящее устройство. Например:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Intent i = new Intent(context, WidgetService.class);
if (service == null) {
service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
}
manager.setRepeating(AlarmManager.ELAPSED_REALTIME,
//Set your update interval.
SystemClock.elapsedRealtime(), 60000, service);
}
}
|
Если вы используете сигнал тревоги, убедитесь, что вы открыли файл AppWidgetProviderInfo вашего проекта ( res / xml / new_app_widget_info.xml ) и установили updatePeriodMillis
в ноль (» 0
«). Если вы забудете этот шаг, значение updatePeriodMillis
переопределит AlarmManager
и ваш виджет будет пробуждать устройство каждый раз, когда требуется обновление.
Вывод
В этой серии из трех частей мы создали виджет приложения Android, который демонстрирует, как реализовать все наиболее распространенные функции, присутствующие в виджетах приложений.
Если вы следили с самого начала, то к этому моменту вы создадите виджет, который обновляется автоматически и в ответ на пользовательский ввод и способен реагировать на события onClick
. Наконец, мы рассмотрели некоторые рекомендации по обеспечению удобства работы вашего виджета и обсудили, как усовершенствовать ваш виджет с помощью действия по настройке.
Спасибо за чтение, и пока вы здесь, ознакомьтесь с некоторыми другими нашими замечательными статьями по разработке приложений для Android!