1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.launcher2; 18 19import android.content.BroadcastReceiver; 20import android.content.ContentResolver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.SharedPreferences; 24import android.database.Cursor; 25import android.net.Uri; 26import android.widget.Toast; 27 28import com.android.launcher.R; 29 30import java.net.URISyntaxException; 31import java.util.ArrayList; 32import java.util.HashSet; 33import java.util.Iterator; 34import java.util.Set; 35 36public class UninstallShortcutReceiver extends BroadcastReceiver { 37 private static final String ACTION_UNINSTALL_SHORTCUT = 38 "com.android.launcher.action.UNINSTALL_SHORTCUT"; 39 40 // The set of shortcuts that are pending uninstall 41 private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue = 42 new ArrayList<PendingUninstallShortcutInfo>(); 43 44 // Determines whether to defer uninstalling shortcuts immediately until 45 // disableAndFlushUninstallQueue() is called. 46 private static boolean mUseUninstallQueue = false; 47 48 private static class PendingUninstallShortcutInfo { 49 Intent data; 50 51 public PendingUninstallShortcutInfo(Intent rawData) { 52 data = rawData; 53 } 54 } 55 56 public void onReceive(Context context, Intent data) { 57 if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) { 58 return; 59 } 60 61 PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data); 62 if (mUseUninstallQueue) { 63 mUninstallQueue.add(info); 64 } else { 65 processUninstallShortcut(context, info); 66 } 67 } 68 69 static void enableUninstallQueue() { 70 mUseUninstallQueue = true; 71 } 72 73 static void disableAndFlushUninstallQueue(Context context) { 74 mUseUninstallQueue = false; 75 Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator(); 76 while (iter.hasNext()) { 77 processUninstallShortcut(context, iter.next()); 78 iter.remove(); 79 } 80 } 81 82 private static void processUninstallShortcut(Context context, 83 PendingUninstallShortcutInfo pendingInfo) { 84 String spKey = LauncherApplication.getSharedPreferencesKey(); 85 SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE); 86 87 final Intent data = pendingInfo.data; 88 89 LauncherApplication app = (LauncherApplication) context.getApplicationContext(); 90 synchronized (app) { 91 removeShortcut(context, data, sharedPrefs); 92 } 93 } 94 95 private static void removeShortcut(Context context, Intent data, 96 final SharedPreferences sharedPrefs) { 97 Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); 98 String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); 99 boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true); 100 101 if (intent != null && name != null) { 102 final ContentResolver cr = context.getContentResolver(); 103 Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, 104 new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT }, 105 LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null); 106 107 final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); 108 final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID); 109 110 boolean changed = false; 111 112 try { 113 while (c.moveToNext()) { 114 try { 115 if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) { 116 final long id = c.getLong(idIndex); 117 final Uri uri = LauncherSettings.Favorites.getContentUri(id, false); 118 cr.delete(uri, null, null); 119 changed = true; 120 if (!duplicate) { 121 break; 122 } 123 } 124 } catch (URISyntaxException e) { 125 // Ignore 126 } 127 } 128 } finally { 129 c.close(); 130 } 131 132 if (changed) { 133 cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null); 134 Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name), 135 Toast.LENGTH_SHORT).show(); 136 } 137 138 // Remove any items due to be animated 139 boolean appRemoved; 140 Set<String> newApps = new HashSet<String>(); 141 newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps); 142 synchronized (newApps) { 143 do { 144 appRemoved = newApps.remove(intent.toUri(0).toString()); 145 } while (appRemoved); 146 } 147 if (appRemoved) { 148 final Set<String> savedNewApps = newApps; 149 new Thread("setNewAppsThread-remove") { 150 public void run() { 151 synchronized (savedNewApps) { 152 SharedPreferences.Editor editor = sharedPrefs.edit(); 153 editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, 154 savedNewApps); 155 if (savedNewApps.isEmpty()) { 156 // Reset the page index if there are no more items 157 editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1); 158 } 159 editor.commit(); 160 } 161 } 162 }.start(); 163 } 164 } 165 } 166} 167