A friend of mine said he wanted a beer app for the Android, really what’s that ? It goes something like this, a beer glass on your Android desktop. The beer glass fills up from 9am to 5pm, once it’s full, well then it’s time to stop working and go out for a beer. On the weekends the glass is always full of course. This would have to be a widget on the desktop so the image / icon can be changed on a timer through the day. Since I hadn’t written an Android widget before, I told my friend, no problem I will write it for you.
Lets declare the widget in the manifest, the service and the alarm receiver as well.
<action android:name=“android.appwidget.action.APPWIDGET_UPDATE” />
<meta-data android:name=“android.appwidget.provider” android:resource=“@xml/beerwidgetlayout” />
<service android:name=“.CxUpdateWidgetService” />
<receiver android:name=“.CxBeerAlarmReceiver” />
Then in the AppWidgetProvider we use AlarmManager to update our receiver
AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0,
new Intent(context, CxBeerAlarmReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT);
// Use inexact repeating which is easier on battery (system can phase events and not wake at exact times)
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 500, (60*1000), pendingIntent2);
Note that you have to be mindful of the resources you are using and use a long interval. If the person using the phone is playing a game for example when the timer goes off. You do not want to take much resources in order for his game to keep playing smoothly. In our case it’s a simple check and a quick update of a icon if needed.
The CxBeerAlarmReceiver is a BroadcastReceiver which when woken up will start the CxUpdateWidgetService which is a IntentService. The CxUpdateWidgetService will take care of updating the widgets.
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final int appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, FxBeerWidget.class));
// Remote view for the widget
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.beerwidget );
// Setup the beer main Activity as Intent
Intent beerIntent = new Intent();
beerIntent.setClass( context, FxMain.class);
// Setup pending intent, when widget clicked show main screen
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, beerIntent, 0);
// Time status
int iCurrentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
// Format it in clock like format, leading zero
views.setTextViewText( R.id.lbStatus, CxUtil.getTimeString() );
// Update image only if needed
int plusNum = whichIcon( iCurrentHour);
CxLog.d( CxLog.TOKEN, “updating beer image, currhour=” + iCurrentHour + “, plusNum=” + plusNum );
// Set the current image
views.setImageViewResource( R.id.widgetImage, R.drawable.beer72_0 + plusNum );
// Associate the update views – Loop all id’s
for(int i=0; i<appWidgetIds.length; ++i)
AppWidgetManager.getInstance(context).updateAppWidget( appWidgetIds[i], views );
Note that the user can have more than more widget running, there could be one on each desktop, etc. The for loop will take care of that and update all of the widgets. Another cotcha is that you will have to set the click intent for the widget each time the update function is called. Otherwise it will get disconnected from the widget and clicking the widget will not open the FxMain screen.
Here is the Widget if you like to download and install on your Android – BeerTimeWidget