1 package org.robolectric.shadows; 2 3 import android.content.Intent; 4 import android.content.IntentSender; 5 import android.content.IntentSender.SendIntentException; 6 import android.content.pm.ShortcutInfo; 7 import android.content.pm.ShortcutManager; 8 import android.os.Build; 9 import com.google.common.collect.ImmutableList; 10 import java.util.ArrayList; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.Map; 14 import org.robolectric.RuntimeEnvironment; 15 import org.robolectric.annotation.Implementation; 16 import org.robolectric.annotation.Implements; 17 18 /** */ 19 @Implements(value = ShortcutManager.class, minSdk = Build.VERSION_CODES.N_MR1) 20 public class ShadowShortcutManager { 21 22 private static final int MAX_ICON_DIMENSION = 128; 23 24 private final Map<String, ShortcutInfo> dynamicShortcuts = new HashMap<>(); 25 private final Map<String, ShortcutInfo> activePinnedShortcuts = new HashMap<>(); 26 private final Map<String, ShortcutInfo> disabledPinnedShortcuts = new HashMap<>(); 27 28 private List<ShortcutInfo> manifestShortcuts = ImmutableList.of(); 29 30 private boolean isRequestPinShortcutSupported = true; 31 private int maxShortcutCountPerActivity = 16; 32 33 @Implementation 34 protected boolean addDynamicShortcuts(List<ShortcutInfo> shortcutInfoList) { 35 for (ShortcutInfo shortcutInfo : shortcutInfoList) { 36 if (activePinnedShortcuts.containsKey(shortcutInfo.getId())) { 37 ShortcutInfo previousShortcut = activePinnedShortcuts.get(shortcutInfo.getId()); 38 if (!previousShortcut.isImmutable()) { 39 activePinnedShortcuts.put(shortcutInfo.getId(), shortcutInfo); 40 } 41 } else if (disabledPinnedShortcuts.containsKey(shortcutInfo.getId())) { 42 ShortcutInfo previousShortcut = disabledPinnedShortcuts.get(shortcutInfo.getId()); 43 if (!previousShortcut.isImmutable()) { 44 disabledPinnedShortcuts.put(shortcutInfo.getId(), shortcutInfo); 45 } 46 } else if (dynamicShortcuts.containsKey(shortcutInfo.getId())) { 47 ShortcutInfo previousShortcut = dynamicShortcuts.get(shortcutInfo.getId()); 48 if (!previousShortcut.isImmutable()) { 49 dynamicShortcuts.put(shortcutInfo.getId(), shortcutInfo); 50 } 51 } else { 52 dynamicShortcuts.put(shortcutInfo.getId(), shortcutInfo); 53 } 54 } 55 return true; 56 } 57 58 @Implementation(minSdk = Build.VERSION_CODES.O) 59 protected Intent createShortcutResultIntent(ShortcutInfo shortcut) { 60 if (disabledPinnedShortcuts.containsKey(shortcut.getId())) { 61 throw new IllegalArgumentException(); 62 } 63 return new Intent(); 64 } 65 66 @Implementation 67 protected void disableShortcuts(List<String> shortcutIds) { 68 disableShortcuts(shortcutIds, "Shortcut is disabled."); 69 } 70 71 @Implementation 72 protected void disableShortcuts(List<String> shortcutIds, CharSequence unused) { 73 for (String shortcutId : shortcutIds) { 74 ShortcutInfo shortcut = activePinnedShortcuts.remove(shortcutId); 75 if (shortcut != null) { 76 disabledPinnedShortcuts.put(shortcutId, shortcut); 77 } 78 } 79 } 80 81 @Implementation 82 protected void enableShortcuts(List<String> shortcutIds) { 83 for (String shortcutId : shortcutIds) { 84 ShortcutInfo shortcut = disabledPinnedShortcuts.remove(shortcutId); 85 if (shortcut != null) { 86 activePinnedShortcuts.put(shortcutId, shortcut); 87 } 88 } 89 } 90 91 @Implementation 92 protected List<ShortcutInfo> getDynamicShortcuts() { 93 return ImmutableList.copyOf(dynamicShortcuts.values()); 94 } 95 96 @Implementation 97 protected int getIconMaxHeight() { 98 return MAX_ICON_DIMENSION; 99 } 100 101 @Implementation 102 protected int getIconMaxWidth() { 103 return MAX_ICON_DIMENSION; 104 } 105 106 @Implementation 107 protected List<ShortcutInfo> getManifestShortcuts() { 108 return manifestShortcuts; 109 } 110 111 /** Sets the value returned by {@link #getManifestShortcuts()}. */ 112 public void setManifestShortcuts(List<ShortcutInfo> manifestShortcuts) { 113 this.manifestShortcuts = manifestShortcuts; 114 } 115 116 @Implementation 117 protected int getMaxShortcutCountPerActivity() { 118 return maxShortcutCountPerActivity; 119 } 120 121 /** Sets the value returned by {@link #getMaxShortcutCountPerActivity()} . */ 122 public void setMaxShortcutCountPerActivity(int value) { 123 maxShortcutCountPerActivity = value; 124 } 125 126 @Implementation 127 protected List<ShortcutInfo> getPinnedShortcuts() { 128 ImmutableList.Builder<ShortcutInfo> pinnedShortcuts = ImmutableList.builder(); 129 pinnedShortcuts.addAll(activePinnedShortcuts.values()); 130 pinnedShortcuts.addAll(disabledPinnedShortcuts.values()); 131 return pinnedShortcuts.build(); 132 } 133 134 @Implementation 135 protected boolean isRateLimitingActive() { 136 return false; 137 } 138 139 @Implementation(minSdk = Build.VERSION_CODES.O) 140 protected boolean isRequestPinShortcutSupported() { 141 return isRequestPinShortcutSupported; 142 } 143 144 public void setIsRequestPinShortcutSupported(boolean isRequestPinShortcutSupported) { 145 this.isRequestPinShortcutSupported = isRequestPinShortcutSupported; 146 } 147 148 @Implementation 149 protected void removeAllDynamicShortcuts() { 150 dynamicShortcuts.clear(); 151 } 152 153 @Implementation 154 protected void removeDynamicShortcuts(List<String> shortcutIds) { 155 for (String shortcutId : shortcutIds) { 156 dynamicShortcuts.remove(shortcutId); 157 } 158 } 159 160 @Implementation 161 protected void reportShortcutUsed(String shortcutId) {} 162 163 @Implementation(minSdk = Build.VERSION_CODES.O) 164 protected boolean requestPinShortcut(ShortcutInfo shortcut, IntentSender resultIntent) { 165 if (disabledPinnedShortcuts.containsKey(shortcut.getId())) { 166 throw new IllegalArgumentException( 167 "Shortcut with ID [" + shortcut.getId() + "] already exists and is disabled."); 168 } 169 if (dynamicShortcuts.containsKey(shortcut.getId())) { 170 activePinnedShortcuts.put(shortcut.getId(), dynamicShortcuts.remove(shortcut.getId())); 171 } else { 172 activePinnedShortcuts.put(shortcut.getId(), shortcut); 173 } 174 if (resultIntent != null) { 175 try { 176 resultIntent.sendIntent(RuntimeEnvironment.application, 0, null, null, null); 177 } catch (SendIntentException e) { 178 throw new IllegalStateException(); 179 } 180 } 181 return true; 182 } 183 184 @Implementation 185 protected boolean setDynamicShortcuts(List<ShortcutInfo> shortcutInfoList) { 186 dynamicShortcuts.clear(); 187 return addDynamicShortcuts(shortcutInfoList); 188 } 189 190 @Implementation 191 protected boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) { 192 List<ShortcutInfo> existingShortcutsToUpdate = new ArrayList<>(); 193 for (ShortcutInfo shortcutInfo : shortcutInfoList) { 194 if (dynamicShortcuts.containsKey(shortcutInfo.getId()) 195 || activePinnedShortcuts.containsKey(shortcutInfo.getId()) 196 || disabledPinnedShortcuts.containsKey(shortcutInfo.getId())) { 197 existingShortcutsToUpdate.add(shortcutInfo); 198 } 199 } 200 return addDynamicShortcuts(existingShortcutsToUpdate); 201 } 202 } 203