I’ve an application that has a widget already and have a service which updates that widget in every 5 seconds.
Here is my AppWidgetProvider:
public class MyWidget extends AppWidgetProvider {
PendingIntent service = null;
AlarmManager alarmManager;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final Intent i = new Intent(context, MyService.class);
if(service == null) {
service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
}
alarmManager.setRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime(), 1000*5, service);
}
@Override
public void onDisabled(Context context) {
Log.d("LogTag", "onDisabled");
alarmManager.cancel(service);
service.cancel();
}
}
And my Service:
public class MyService extends Service {
int b = 5;
@Override
public void onCreate() { super.onCreate(); }
public int onStartCommand(Intent intent, int flags, int startId) {
this.buildUpdate();
return 0;
}
private void buildUpdate() {
Log.d("AAA", "Update is coming");
RemoteViews rmViews = new RemoteViews(getPackageName(), R.layout.widget_layout);
rmViews.setTextViewText(R.id.hello, "Iterator: " + Integer.toString(b));
ComponentName thisWidget = new ComponentName(this, MyWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, rmViews);
b++;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Service and other things are fine. But still I’ve couple questions about all these stuff:
-
What’s for
SystemClock.elapsedRealtime()which is a parameter insetRepeatingmethod? Does it point when to start? -
When I try to delete widget, I got some errors (on below) and unfortunately
AlarmManagerstill works not cancel. What am I missing? -
I need to do some network operations before widget has been initialized (or called). Widget should has some data from server. Should I use
AsyncTaskor what?
When I try to delete widget, getting:
03-04 23:39:51.428: E/AndroidRuntime(5646): Uncaught handler: thread main exiting due to uncaught exception
03-04 23:39:51.438: E/AndroidRuntime(5646): java.lang.RuntimeException: Unable to start receiver com.example.widget.MyWidget: java.lang.NullPointerException
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2646)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.app.ActivityThread.access$3100(ActivityThread.java:119)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.os.Handler.dispatchMessage(Handler.java:99)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.os.Looper.loop(Looper.java:123)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.app.ActivityThread.main(ActivityThread.java:4363)
03-04 23:39:51.438: E/AndroidRuntime(5646): at java.lang.reflect.Method.invokeNative(Native Method)
03-04 23:39:51.438: E/AndroidRuntime(5646): at java.lang.reflect.Method.invoke(Method.java:521)
03-04 23:39:51.438: E/AndroidRuntime(5646): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
03-04 23:39:51.438: E/AndroidRuntime(5646): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
03-04 23:39:51.438: E/AndroidRuntime(5646): at dalvik.system.NativeStart.main(Native Method)
03-04 23:39:51.438: E/AndroidRuntime(5646): Caused by: java.lang.NullPointerException
03-04 23:39:51.438: E/AndroidRuntime(5646): at com.example.widget.MyWidget(MyWidget.java:33)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:76)
03-04 23:39:51.438: E/AndroidRuntime(5646): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2637)
03-04 23:39:51.438: E/AndroidRuntime(5646): ... 10 more
SystemClock.elapsedRealTime()as you have it is currently in thetriggerAtTimeparameter, meaning that any number you put there is the time that you want the alarm to go off.elapsedRealtime()is counted in milliseconds since the system was booted, including deep sleep. This clock should be used when measuring time intervals that may span periods of system sleep.In you
onDisabledmethod, you need to recreate the entirePendingIntent. My guess is it is null there because it doesn’t actually exist when you callonDisabled, but only exists in theonUpdate. So recreate theservicevariablePendingIntentexactly the same way as you do before and then call cancel on it as you already are.AsyncTasks are good for things like that. AnAsyncTaskspawns a managed thread in the background and does work while the UI thread keeps going, then can update the UI thread when done. So if you have lots of heavy networking to do, anAsyncTaskwill handle that beautifully. The docs onAsyncTaskare very useful. Find them here. There are many options for this depending on what you are doing, so you’d have to explain your issue on this third point in a little more detail to get a more tailored answer.