Новое обновление: в 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 .
