Новое обновление: в Android 4.1 была добавлена новая функция для виджета Homescreen, которая позволяет виджету реорганизовывать свой вид при изменении размера. Для поддержки этой функции в классе AppWidgetProvider был представлен новый метод onAppWidgetOptionsChanged () . Этот метод вызывается в ответ на трансляцию ACTION_APPWIDGET_OPTIONS_CHANGED, когда этот виджет был размещен в новом размере.
Информация о проекте: Мета-информация о проекте.
Версия платформы: Android API Level 16.
IDE: Eclipse Helios Service Release 2
Эмулятор: Android 4.1
Предварительные условия: предварительные знания о структуре приложений Android, приемнике Intent Broadcast и AlarmManager.
Пример с фиксированным интервалом обновления менее 30 минут.
В этом уроке мы создадим виджет времени, который показывает текущее время. Этот виджет будет обновляться каждую секунду, и мы будем использовать AlarmManager для него. Здесь повторяющийся сигнал тревоги устанавливается на интервал в одну секунду. Но в сценарии реального мира не рекомендуется использовать одну секунду повторяющегося сигнала тревоги, потому что он быстро разряжает батарею. Вы должны выполнить аналогичные шаги, упомянутые в предыдущем руководстве по виджетам, чтобы написать файл макета виджета. Но на этот раз мы вводим поле TextView в макет, который будет отображать время. Содержание «time_widget_layout.xml» приведено ниже.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
android:layout_width = "match_parent" android:layout_height = "match_parent" android:orientation = "vertical" android:background = "@drawable/widget_background" > < TextView android:id = "@+id/tvTime" style = "@android:style/TextAppearance.Medium" android:layout_width = "match_parent" android:layout_height = "match_parent" android:layout_gravity = "center" android:layout_margin = "4dip" android:gravity = "center_horizontal|center_vertical" android:textColor = "#000000" /> </ LinearLayout > |
Выполните ту же процедуру, чтобы создать файл метаданных AppWidgetProvider. Содержимое файла метаданных ”widget_metadata.xml” приведено ниже.
1
2
3
4
5
6
|
android:initialLayout = "@layout/time_widget_layout" android:minHeight = "40dp" android:minWidth = "130dp" android:updatePeriodMillis = "1800000" > </ appwidget-provider > |
В этом уроке onEnabled (), onDsiabled (), onUpdate () и onAppWidgetOptionsChanged () были определены в отличие от предыдущего урока виджетов, где был определен только onUpdate ().
- onEnabled (): здесь создается экземпляр AlarmManager, чтобы запустить повторяющийся таймер и зарегистрировать намерение в AlarmManager. Поскольку этот метод вызывается при самом первом случае установки виджета, он помогает установить повторяющуюся тревогу только один раз.
- onDisabled (): в этом методе сигнал тревоги отменяется, потому что этот метод вызывается, как только самый последний экземпляр виджета удаляется / удаляется, и мы не хотим оставлять зарегистрированный сигнал тревоги, даже когда он не используется.
- onUpdate (): этот метод обновляет время на удаленном TextView.
- onAppWidgetOptionsChanged (): этот метод вызывается при изменении размера виджета.
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
|
package com.rakesh.widgetalarmmanagerexample; import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.widget.RemoteViews; import android.widget.Toast; public class TimeWidgetProvider extends AppWidgetProvider { @Override public void onDeleted(Context context, int [] appWidgetIds) { Toast.makeText(context, "TimeWidgetRemoved id(s):" +appWidgetIds, Toast.LENGTH_SHORT).show(); super .onDeleted(context, appWidgetIds); } @Override public void onDisabled(Context context) { Toast.makeText(context, "onDisabled():last widget instance removed" , Toast.LENGTH_SHORT).show(); Intent intent = new Intent(context, AlarmManagerBroadcastReceiver. class ); PendingIntent sender = PendingIntent.getBroadcast(context, 0 , intent, 0 ); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(sender); super .onDisabled(context); } @Override public void onEnabled(Context context) { super .onEnabled(context); AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, AlarmManagerBroadcastReceiver. class ); PendingIntent pi = PendingIntent.getBroadcast(context, 0 , intent, 0 ); //After after 3 seconds am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ 100 * 3 , 1000 , pi); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) { ComponentName thisWidget = new ComponentName(context, TimeWidgetProvider. class ); for ( int widgetId : appWidgetManager.getAppWidgetIds(thisWidget)) { //Get the remote views RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.time_widget_layout); // Set the text with the current time. remoteViews.setTextViewText(R.id.tvTime, Utility.getCurrentTime( "hh:mm:ss a" )); appWidgetManager.updateAppWidget(widgetId, remoteViews); } } @Override public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { //Do some operation here, once you see that the widget has change its size or position. Toast.makeText(context, "onAppWidgetOptionsChanged() called" , Toast.LENGTH_SHORT).show(); } } |
Приемник широковещания определен для обработки намерения, зарегистрированного с тревогой. Этот широковещательный приемник вызывается каждую секунду, потому что повторяющийся сигнал тревоги был установлен в классе AppWidgetProvider на 1 секунду. Здесь был определен метод onReceive (), который обновляет виджет с текущим временем, а getCurrentTime () используется для получения текущего времени.
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
|
package com.rakesh.widgetalarmmanagerexample; import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.widget.RemoteViews; import android.widget.Toast; public class AlarmManagerBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG" ); //Acquire the lock wl.acquire(); //You can do the processing here update the widget/remote views. RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.time_widget_layout); remoteViews.setTextViewText(R.id.tvTime, Utility.getCurrentTime( "hh:mm:ss a" )); ComponentName thiswidget = new ComponentName(context, TimeWidgetProvider. class ); AppWidgetManager manager = AppWidgetManager.getInstance(context); manager.updateAppWidget(thiswidget, remoteViews); //Release the lock wl.release(); } } |
Всегда полезно хранить служебные методы в каком-либо служебном классе, доступ к которому можно получить из других пакетов. getCurrentTime () был определен в классе Uitility. Этот метод используется в классах AppWidgetProvider и BroadcastReciever.
01
02
03
04
05
06
07
08
09
10
11
12
|
package com.rakesh.widgetalarmmanagerexample; import java.text.Format; import java.text.SimpleDateFormat; import java.util.Date; public class Utility { public static String getCurrentTime(String timeformat){ Format formatter = new SimpleDateFormat(timeformat); return formatter.format( new Date()); } } |
В файле манифеста Android нам нужно включить разрешение WAKE_LOCK, потому что в широковещательном приемнике используется блокировка пробуждения. AlarmManagerBroadcastReceiver был зарегистрирован как широковещательный приемник. Оставшаяся часть проста для понимания.
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
|
< manifest android:versioncode = "1" android:versionname = "1.0" package = "com.rakesh.widgetalarmmanagerexample" < uses-sdk android:minsdkversion = "16" android:targetsdkversion = "16" /> < uses-permission android:name = "android.permission.WAKE_LOCK" /> < application android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" > < activity android:label = "@string/title_activity_widget_alarm_manager" android:name = ".WidgetAlarmManagerActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > < receiver android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" android:name = ".TimeWidgetProvider" > < intent-filter > < action android:name = "android.appwidget.action.APPWIDGET_UPDATE" /> </ intent-filter > < meta-data android:name = "android.appwidget.provider" android:resource = "@xml/widget_metadata" /> </ receiver > < receiver android:name = ".AlarmManagerBroadcastReceiver" /> </ application > </ manifest > |
После выполнения кода виджет регистрируется. Когда вы устанавливаете виджет на домашний экран, он выглядит так, как показано ниже.
Вы можете скачать исходный код здесь .
Ссылка: Учебное пособие по Android Homescreen Widget с AlarmManager. от нашего партнера JCG Ракеша Кусата в блоге Code4Reference .