Fix widget updates

Fix widgets that stop updating.  If the Launcher got killed, the Email
widget service gets unbound.  When this happens the cursor loader for the
widget is stopped.  Since widget is relying on the loader to update the data,
when the loader is stopped, the widget would never update.

Now when email recognizes a change, it will send a broadcast intent, which
will cause the widget service to be started, if it isn't.

Bug: 5811810
Change-Id: Ia840e58f10e780b94440119662c2e48e7785c507
This commit is contained in:
Paul Westbrook 2012-01-09 11:36:16 -08:00
parent 9b4240f7c5
commit 07676012f7
4 changed files with 46 additions and 0 deletions

View File

@ -486,6 +486,9 @@
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="com.android.email.MESSAGE_LIST_DATASET_CHANGED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />

View File

@ -23,6 +23,7 @@ import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
@ -86,6 +87,14 @@ public class EmailProvider extends ContentProvider {
public static final String ATTACHMENT_UPDATED_EXTRA_FLAGS =
"com.android.email.ATTACHMENT_UPDATED_FLAGS";
/**
* Notifies that changes happened. Certain UI components, e.g., widgets, can register for this
* {@link android.content.Intent} and update accordingly. However, this can be very broad and
* is NOT the preferred way of getting notification.
*/
public static final String ACTION_NOTIFY_MESSAGE_LIST_DATASET_CHANGED =
"com.android.email.MESSAGE_LIST_DATASET_CHANGED";
public static final String EMAIL_MESSAGE_MIME_TYPE =
"vnd.android.cursor.item/email-message";
public static final String EMAIL_ATTACHMENT_MIME_TYPE =
@ -2345,6 +2354,20 @@ outer:
} else {
resolver.notifyChange(baseUri, null);
}
// We want to send the message list changed notification if baseUri is Message.NOTIFIER_URI.
if (baseUri.equals(Message.NOTIFIER_URI)) {
sendMessageListDataChangedNotification();
}
}
private void sendMessageListDataChangedNotification() {
final Context context = getContext();
final Intent intent = new Intent(ACTION_NOTIFY_MESSAGE_LIST_DATASET_CHANGED);
// Ideally this intent would contain information about which account changed, to limit the
// updates to that particular account. Unfortunately, that information is not available in
// sendNotifierChange().
context.sendBroadcast(intent);
}
@Override

View File

@ -19,12 +19,14 @@ package com.android.email.provider;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViewsService;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.widget.EmailWidget;
import com.android.email.widget.WidgetManager;
import com.android.emailcommon.Logging;
@ -74,6 +76,20 @@ public class WidgetProvider extends AppWidgetProvider {
Log.d(EmailWidget.TAG, "onReceive");
}
super.onReceive(context, intent);
if (EmailProvider.ACTION_NOTIFY_MESSAGE_LIST_DATASET_CHANGED.equals(intent.getAction())) {
// Retrieve the list of current widgets.
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final ComponentName component = new ComponentName(context, WidgetProvider.class);
final int[] widgetIds = appWidgetManager.getAppWidgetIds(component);
// Ideally, this would only call notify AppWidgetViewDataChanged for the widgets, where
// the account had the change, but the current intent doesn't include this information.
// Calling notifyAppWidgetViewDataChanged will cause onDataSetChanged() to be called
// on the RemoteViewsService.RemoteViewsFactory, starting the service if necessary.
appWidgetManager.notifyAppWidgetViewDataChanged(widgetIds, R.id.message_list);
}
}
/**

View File

@ -505,6 +505,10 @@ public class EmailWidget implements RemoteViewsService.RemoteViewsFactory,
@Override
public void onDataSetChanged() {
// Note: we are not doing anything special in onDataSetChanged(). Since this service has
// a reference to a loader that will keep itself updated, if the service is running, it
// shouldn't be necessary to for the query to be run again. If the service hadn't been
// running, the act of starting the service will also start the loader.
}
public void onDeleted() {