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