131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 1931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.BroadcastReceiver; 20f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chungimport android.content.ContentResolver; 2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context; 2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent; 2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.database.Cursor; 2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.net.Uri; 25d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guyimport android.widget.Toast; 2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.net.URISyntaxException; 28f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chungimport java.util.ArrayList; 29f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chungimport java.util.Iterator; 3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpublic class UninstallShortcutReceiver extends BroadcastReceiver { 3251ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy private static final String ACTION_UNINSTALL_SHORTCUT = 3394d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung "com.android.launcher.action.UNINSTALL_SHORTCUT"; 3451ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy 35f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung // The set of shortcuts that are pending uninstall 36f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue = 37f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung new ArrayList<PendingUninstallShortcutInfo>(); 38f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 39f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung // Determines whether to defer uninstalling shortcuts immediately until 40f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung // disableAndFlushUninstallQueue() is called. 41f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung private static boolean mUseUninstallQueue = false; 42f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 43f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung private static class PendingUninstallShortcutInfo { 44f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung Intent data; 45f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 46f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung public PendingUninstallShortcutInfo(Intent rawData) { 47f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung data = rawData; 48f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 49f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 50f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onReceive(Context context, Intent data) { 5251ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) { 5351ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy return; 5451ed5b9bc05c6eb37dcb3fe38fa021f1044c0f88Romain Guy } 55f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 56f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data); 57f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung if (mUseUninstallQueue) { 58f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung mUninstallQueue.add(info); 59f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } else { 60f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung processUninstallShortcut(context, info); 61f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 62f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 63f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 64f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung static void enableUninstallQueue() { 65f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung mUseUninstallQueue = true; 66f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 67f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 68f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung static void disableAndFlushUninstallQueue(Context context) { 69f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung mUseUninstallQueue = false; 70f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator(); 71f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung while (iter.hasNext()) { 72f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung processUninstallShortcut(context, iter.next()); 73f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung iter.remove(); 74f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 75f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung } 76f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 77f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung private static void processUninstallShortcut(Context context, 78f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung PendingUninstallShortcutInfo pendingInfo) { 79f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung final Intent data = pendingInfo.data; 80f561bdf68dd304e1d7c3f7796621a4cc39ca15f2Winson Chung 81c88dceb0b567ab96418e73cf2f6b197ba2646cb3Winson Chung LauncherAppState.setApplicationContext(context.getApplicationContext()); 82cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler LauncherAppState app = LauncherAppState.getInstance(); 83e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler synchronized (app) { // TODO: make removeShortcut internally threadsafe 84997a92348a6d6e061737399321393449c16cd4d8Winson Chung removeShortcut(context, data); 85a2413751e3a698aef9c87411a639637883856939Winson Chung } 86a2413751e3a698aef9c87411a639637883856939Winson Chung } 87a2413751e3a698aef9c87411a639637883856939Winson Chung 88997a92348a6d6e061737399321393449c16cd4d8Winson Chung private static void removeShortcut(Context context, Intent data) { 8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); 9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); 9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true); 9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (intent != null && name != null) { 9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final ContentResolver cr = context.getContentResolver(); 9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, 9673b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy new String[] { LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT }, 9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project LauncherSettings.Favorites.TITLE + "=?", new String[] { name }, null); 9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); 10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID); 10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project boolean changed = false; 10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project while (c.moveToNext()) { 10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 1071ce1a24cba4dc41bccfeab6fccb2f3355423841aRomain Guy if (intent.filterEquals(Intent.parseUri(c.getString(intentIndex), 0))) { 10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final long id = c.getLong(idIndex); 10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final Uri uri = LauncherSettings.Favorites.getContentUri(id, false); 11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project cr.delete(uri, null, null); 11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project changed = true; 11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!duplicate) { 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project break; 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (URISyntaxException e) { 11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Ignore 11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project c.close(); 12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 124d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guy if (changed) { 125d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guy cr.notifyChange(LauncherSettings.Favorites.CONTENT_URI, null); 126d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guy Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name), 127d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guy Toast.LENGTH_SHORT).show(); 128d93a7d1716b06cd65f45dfc16232277d0d57c04dRomain Guy } 12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 132