1 package com.android.launcher3; 2 3 import android.appwidget.AppWidgetHost; 4 import android.appwidget.AppWidgetManager; 5 import android.appwidget.AppWidgetProviderInfo; 6 import android.content.BroadcastReceiver; 7 import android.content.ContentResolver; 8 import android.content.ContentValues; 9 import android.content.Context; 10 import android.content.Intent; 11 import android.database.Cursor; 12 import android.os.AsyncTask; 13 import android.util.Log; 14 15 import com.android.launcher3.LauncherSettings.Favorites; 16 17 import java.util.ArrayList; 18 import java.util.List; 19 20 public class AppWidgetsRestoredReceiver extends BroadcastReceiver { 21 22 private static final String TAG = "AppWidgetsRestoredReceiver"; 23 24 @Override onReceive(Context context, Intent intent)25 public void onReceive(Context context, Intent intent) { 26 if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) { 27 int[] oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS); 28 int[] newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); 29 if (oldIds.length == newIds.length) { 30 restoreAppWidgetIds(context, oldIds, newIds); 31 } else { 32 Log.e(TAG, "Invalid host restored received"); 33 } 34 } 35 } 36 37 /** 38 * Updates the app widgets whose id has changed during the restore process. 39 */ restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds)40 static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) { 41 final ContentResolver cr = context.getContentResolver(); 42 final List<Integer> idsToRemove = new ArrayList<Integer>(); 43 final AppWidgetManager widgets = AppWidgetManager.getInstance(context); 44 45 for (int i = 0; i < oldWidgetIds.length; i++) { 46 Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]); 47 48 final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]); 49 final int state; 50 if (LauncherModel.isValidProvider(provider)) { 51 // This will ensure that we show 'Click to setup' UI if required. 52 state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY; 53 } else { 54 state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY; 55 } 56 57 ContentValues values = new ContentValues(); 58 values.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]); 59 values.put(LauncherSettings.Favorites.RESTORED, state); 60 61 String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) }; 62 63 int result = cr.update(Favorites.CONTENT_URI, values, 64 "appWidgetId=? and (restored & 1) = 1", widgetIdParams); 65 if (result == 0) { 66 Cursor cursor = cr.query(Favorites.CONTENT_URI, 67 new String[] {Favorites.APPWIDGET_ID}, 68 "appWidgetId=?", widgetIdParams, null); 69 try { 70 if (!cursor.moveToFirst()) { 71 // The widget no long exists. 72 idsToRemove.add(newWidgetIds[i]); 73 } 74 } finally { 75 cursor.close(); 76 } 77 } 78 } 79 // Unregister the widget IDs which are not present on the workspace. This could happen 80 // when a widget place holder is removed from workspace, before this method is called. 81 if (!idsToRemove.isEmpty()) { 82 final AppWidgetHost appWidgetHost = 83 new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID); 84 new AsyncTask<Void, Void, Void>() { 85 public Void doInBackground(Void ... args) { 86 for (Integer id : idsToRemove) { 87 appWidgetHost.deleteAppWidgetId(id); 88 Log.e(TAG, "Widget no longer present, appWidgetId=" + id); 89 } 90 return null; 91 } 92 }.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR); 93 } 94 95 LauncherAppState app = LauncherAppState.getInstanceNoCreate(); 96 if (app != null) { 97 app.reloadWorkspace(); 98 } 99 } 100 } 101