New update:
Project Information: Meta-information about the project.
Platform Version : Android API Level 16.
IDE : Eclipse Helios Service Release 2
Emulator: Android 4.1
Prerequisite: Preliminary knowledge of Android application framework, Intent Broadcast receiver and AlarmManager.
Example with fixed update interval less than 30 mins.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/time_widget_layout"
android:minHeight="40dp"
android:minWidth="130dp"
android:updatePeriodMillis="1800000" >
</appwidget-provider>
- onEnabled(): An instance of AlarmManager is created here to start the repeating timer and register the intent with the AlarmManager. As this method gets called at the very first instance of widget installation, it helps to set repeating alarm only once.
- onDisabled(): In this method, alarm is canceled because this method gets called as soon as the very last instance of widget is removed/uninstalled and we don’t want to leave the registered alarm even when it’s not being used.
- onUpdate(): This method updates the time on remote TextView.
- onAppWidgetOptionsChanged(): This method gets called when the widget is resized.
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()+ 1000 * 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();
}
}
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();
}
}
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());
}
}
In Android manifest file, we need to include WAKE_LOCK permission because wake lock is used in broadcast receiver. AlarmManagerBroadcastReceiver has been registered as broadcast receiver. Remaining part is simple to understand.
<manifest android:versioncode="1" android:versionname="1.0"
package="com.rakesh.widgetalarmmanagerexample"
xmlns:android="http://schemas.android.com/apk/res/android">
<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>
you can download source code from here.
Related tutorial:
Your valuable comments are always welcomed. It will help to improve my post and understanding.
“By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest.”
By : Confucius

superb…..10 out of 10 from me.step by step explanation
really like it. is a good base example for my needs.
I noticed a small mistake. You wrote // after 3 seconds, but used 100 * 3, what is actually a 0.3 second.
Thanks Seta for your comment ,
It was a typo. I have fixed the code.
Good example!, it really helped me a lot! thanks .
well done great tutorial and code,was using widgets but all other code failed due to bugs but this code is amazing – worked very well for me ,using it in a free clock app now ,cheers….
Thanks for the example. Sure is a shame that all the examples found on this topic include the text: But in real world scenario, it is not recommended to use….
Suprrbbbb….Thanks for sharing
Thanks for the tutorial. But I do not understand from where the widget is getting updated.
updateAppWidget is called from 2 places :
1) appWidgetManager.updateAppWidget(widgetId, remoteViews) in TimeWidgetProvider.onUpdate : Here there is a loop for all the widgets
2) manager.updateAppWidget(thiswidget, remoteViews) in AlarmManagerBroadcastReceiver.OnReceive : Here there is no loop for all widgets.
Why is it required to call updateAppWidget from 2 different places?
@Elison Niven Good catch.
TimeWidgetProvider.onUpdate get called in response to the ACTION_APPWIDGET_UPDATE broadcast when this AppWidget provider is being asked to provide RemoteViews for a set of AppWidgets. Where as AlarmManagerBroadcastReceiver.OnReceive is called whenever AlarmManager triggers an intent. In this particular example, we need to update the time whenever we receive Intent from AlarmManager and this was the best place to update the RemoteView. Ideally I should have called updateAppWidget() in the loop for all instance of Widget in this method but I avoided it.
Hope I answered your question.