In the preiouse exercise "Schedule a repeating alarm", we know how to triger a repeating service using Alarm Manager. It will be used here to trigger the onReceive() method of the AppWidgetProvider.
Modify AndroidManifest.xml to add a new custom intent-filter, "MY_OWN_WIDGET_UPDATE".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.HelloWidget"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name="HelloWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="MY_OWN_WIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/hellowidgetproviderinfo" />
</receiver>
<activity android:name=".HelloWidgetConfig"
android:label="Hello Widget Config">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>
Modify HelloWidgetProvider.java to implement onReceive() method, to handle the "MY_OWN_WIDGET_UPDATE" action.
package com.exercise.HelloWidget;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import android.widget.Toast;
public class HelloWidgetProvider extends AppWidgetProvider {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy hh:mm:ss a");
static String strWidgetText = "";
public static String MY_WIDGET_UPDATE = "MY_OWN_WIDGET_UPDATE";
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
if(MY_WIDGET_UPDATE.equals(intent.getAction())){
Toast.makeText(context, "onReceiver()", Toast.LENGTH_LONG).show();
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
// TODO Auto-generated method stub
//super.onDeleted(context, appWidgetIds);
Toast.makeText(context, "onDeleted()", Toast.LENGTH_LONG).show();
}
@Override
public void onDisabled(Context context) {
// TODO Auto-generated method stub
//super.onDisabled(context);
Toast.makeText(context, "onDisabled()", Toast.LENGTH_LONG).show();
}
@Override
public void onEnabled(Context context) {
// TODO Auto-generated method stub
//super.onEnabled(context);
Toast.makeText(context, "onEnabled()", Toast.LENGTH_LONG).show();
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
updateAppWidget(context, appWidgetManager, appWidgetId);
Toast.makeText(context, "onUpdate(): " + String.valueOf(i) + " : " + String.valueOf(appWidgetId), Toast.LENGTH_LONG).show();
}
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId){
String currentTime = formatter.format(new Date());
strWidgetText = currentTime;
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.hellowidget_layout);
updateViews.setTextViewText(R.id.widgettext, "[" + String.valueOf(appWidgetId) + "]" + strWidgetText);
appWidgetManager.updateAppWidget(appWidgetId, updateViews);
Toast.makeText(context, "updateAppWidget(): " + String.valueOf(appWidgetId) + "\n" + strWidgetText, Toast.LENGTH_LONG).show();
}
}
Modify HelloWidgetConfig.java to start Alarm Manager.
package com.exercise.HelloWidget;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class HelloWidgetConfig extends Activity {
Button configOkButton;
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setResult(RESULT_CANCELED);
setContentView(R.layout.config);
configOkButton = (Button)findViewById(R.id.okconfig);
configOkButton.setOnClickListener(configOkButtonOnClickListener);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If they gave us an intent without the widget id, just bail.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
}
private Button.OnClickListener configOkButtonOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
final Context context = HelloWidgetConfig.this;
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
//RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.hellowidget_layout);
//appWidgetManager.updateAppWidget(mAppWidgetId, views);
HelloWidgetProvider.updateAppWidget(context, appWidgetManager, mAppWidgetId);
Toast.makeText(context, "HelloWidgetConfig.onClick(): " + String.valueOf(mAppWidgetId) , Toast.LENGTH_LONG).show();
//prepare Alarm Service to trigger Widget
Intent intent = new Intent(HelloWidgetProvider.MY_WIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(HelloWidgetConfig.this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 20*1000, pendingIntent);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
}};
}
Download the files.
Known Issues:
Please note that it's a simple exercise to implement App Widget using Alarm Manager, not a completed code. There are some issues:
- It's strongly recommanded that NOT to set Widget in such high repeating rate if not necessage, otherwise your battery will go low soon.
- The exercise haven't cancel the Alarm Service, it will not stop even all the Widget removed from Home Screen. (Refer to the article: Cancel Alarm Service in onDisabled()).
- There are no appWidgetManager and appWidgetId passed to onReceive() method, how to handle the individual Widget is another issue. (Refer to the article: Update Widget in onReceive() method).