1 package org.robolectric.shadows; 2 3 import static org.robolectric.shadow.api.Shadow.newInstanceOf; 4 5 import android.app.ActivityThread; 6 import android.app.Application; 7 import android.appwidget.AppWidgetManager; 8 import android.content.BroadcastReceiver; 9 import android.content.ComponentName; 10 import android.content.Context; 11 import android.content.ContextWrapper; 12 import android.content.Intent; 13 import android.content.IntentFilter; 14 import android.content.ServiceConnection; 15 import android.os.Handler; 16 import android.os.IBinder; 17 import android.os.PowerManager; 18 import android.widget.ListPopupWindow; 19 import android.widget.PopupWindow; 20 import android.widget.Toast; 21 import java.util.ArrayList; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 import org.robolectric.RoboSettings; 26 import org.robolectric.RuntimeEnvironment; 27 import org.robolectric.annotation.Implements; 28 import org.robolectric.annotation.RealObject; 29 import org.robolectric.shadow.api.Shadow; 30 import org.robolectric.util.ReflectionHelpers; 31 import org.robolectric.util.Scheduler; 32 33 @Implements(Application.class) 34 public class ShadowApplication extends ShadowContextWrapper { 35 @RealObject private Application realApplication; 36 37 private Scheduler backgroundScheduler = RoboSettings.isUseGlobalScheduler() 38 ? getForegroundThreadScheduler() 39 : new Scheduler(); 40 private List<android.widget.Toast> shownToasts = new ArrayList<>(); 41 private PowerManager.WakeLock latestWakeLock; 42 private ShadowAlertDialog latestAlertDialog; 43 private ShadowDialog latestDialog; 44 private ShadowPopupMenu latestPopupMenu; 45 private Object bluetoothAdapter = newInstanceOf("android.bluetooth.BluetoothAdapter"); 46 private PopupWindow latestPopupWindow; 47 private ListPopupWindow latestListPopupWindow; 48 49 /** 50 * @deprecated Use 51 * `shadowOf({@link androidx.test.core.app.ApplicationProvider#getApplicationContext})` 52 * instead. 53 */ 54 @Deprecated getInstance()55 public static ShadowApplication getInstance() { 56 return RuntimeEnvironment.application == null 57 ? null 58 : Shadow.extract(RuntimeEnvironment.application); 59 } 60 61 /** 62 * Runs any background tasks previously queued by {@link android.os.AsyncTask#execute(Object[])}. 63 * 64 * Note: calling this method does not pause or un-pause the scheduler. 65 */ runBackgroundTasks()66 public static void runBackgroundTasks() { 67 getInstance().getBackgroundThreadScheduler().advanceBy(0); 68 } 69 70 /** 71 * Attaches an application to a base context. 72 * 73 * @param context The context with which to initialize the application, whose base context will 74 * be attached to the application 75 */ callAttach(Context context)76 public void callAttach(Context context) { 77 ReflectionHelpers.callInstanceMethod(Application.class, realApplication, "attach", 78 ReflectionHelpers.ClassParameter.from(Context.class, context)); 79 } 80 getShownToasts()81 public List<Toast> getShownToasts() { 82 return shownToasts; 83 } 84 85 /** 86 * Return the foreground scheduler. 87 * 88 * @return Foreground scheduler. 89 */ getForegroundThreadScheduler()90 public Scheduler getForegroundThreadScheduler() { 91 return RuntimeEnvironment.getMasterScheduler(); 92 } 93 94 /** 95 * Return the background scheduler. 96 * 97 * @return Background scheduler. 98 */ getBackgroundThreadScheduler()99 public Scheduler getBackgroundThreadScheduler() { 100 return backgroundScheduler; 101 } 102 setComponentNameAndServiceForBindService(ComponentName name, IBinder service)103 public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) { 104 getShadowInstrumentation().setComponentNameAndServiceForBindService(name, service); 105 } 106 setComponentNameAndServiceForBindServiceForIntent( Intent intent, ComponentName name, IBinder service)107 public void setComponentNameAndServiceForBindServiceForIntent( 108 Intent intent, ComponentName name, IBinder service) { 109 getShadowInstrumentation() 110 .setComponentNameAndServiceForBindServiceForIntent(intent, name, service); 111 } 112 assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action)113 public void assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action) { 114 getShadowInstrumentation().assertNoBroadcastListenersOfActionRegistered(context, action); 115 } 116 getBoundServiceConnections()117 public List<ServiceConnection> getBoundServiceConnections() { 118 return getShadowInstrumentation().getBoundServiceConnections(); 119 } 120 setUnbindServiceShouldThrowIllegalArgument(boolean flag)121 public void setUnbindServiceShouldThrowIllegalArgument(boolean flag) { 122 getShadowInstrumentation().setUnbindServiceShouldThrowIllegalArgument(flag); 123 } 124 getUnboundServiceConnections()125 public List<ServiceConnection> getUnboundServiceConnections() { 126 return getShadowInstrumentation().getUnboundServiceConnections(); 127 } 128 129 /** @deprecated use PackageManager.queryBroadcastReceivers instead */ 130 @Deprecated hasReceiverForIntent(Intent intent)131 public boolean hasReceiverForIntent(Intent intent) { 132 return getShadowInstrumentation().hasReceiverForIntent(intent); 133 } 134 135 /** @deprecated use PackageManager.queryBroadcastReceivers instead */ 136 @Deprecated getReceiversForIntent(Intent intent)137 public List<BroadcastReceiver> getReceiversForIntent(Intent intent) { 138 return getShadowInstrumentation().getReceiversForIntent(intent); 139 } 140 141 /** 142 * @return list of {@link Wrapper}s for registered receivers 143 */ getRegisteredReceivers()144 public List<Wrapper> getRegisteredReceivers() { 145 return getShadowInstrumentation().getRegisteredReceivers(); 146 } 147 148 /** 149 * @deprecated Please use {@link Context#getSystemService(Context.APPWIDGET_SERVICE)} intstead. 150 */ 151 @Deprecated getAppWidgetManager()152 public AppWidgetManager getAppWidgetManager() { 153 return (AppWidgetManager) realApplication.getSystemService(Context.APPWIDGET_SERVICE); 154 } 155 156 /** 157 * @deprecated Use {@link ShadowAlertDialog#getLatestAlertDialog()} instead. 158 */ 159 @Deprecated getLatestAlertDialog()160 public ShadowAlertDialog getLatestAlertDialog() { 161 return latestAlertDialog; 162 } 163 setLatestAlertDialog(ShadowAlertDialog latestAlertDialog)164 protected void setLatestAlertDialog(ShadowAlertDialog latestAlertDialog) { 165 this.latestAlertDialog = latestAlertDialog; 166 } 167 168 /** 169 * @deprecated Use {@link ShadowDialog#getLatestDialog()} instead. 170 */ 171 @Deprecated getLatestDialog()172 public ShadowDialog getLatestDialog() { 173 return latestDialog; 174 } 175 setLatestDialog(ShadowDialog latestDialog)176 protected void setLatestDialog(ShadowDialog latestDialog) { 177 this.latestDialog = latestDialog; 178 } 179 getBluetoothAdapter()180 public Object getBluetoothAdapter() { 181 return bluetoothAdapter; 182 } 183 declareActionUnbindable(String action)184 public void declareActionUnbindable(String action) { 185 getShadowInstrumentation().declareActionUnbindable(action); 186 } 187 getLatestWakeLock()188 public PowerManager.WakeLock getLatestWakeLock() { 189 return latestWakeLock; 190 } 191 addWakeLock( PowerManager.WakeLock wl )192 public void addWakeLock( PowerManager.WakeLock wl ) { 193 latestWakeLock = wl; 194 } 195 clearWakeLocks()196 public void clearWakeLocks() { 197 latestWakeLock = null; 198 } 199 200 private final Map<String, Object> singletons = new HashMap<>(); 201 getSingleton(Class<T> clazz, Provider<T> provider)202 public <T> T getSingleton(Class<T> clazz, Provider<T> provider) { 203 synchronized (singletons) { 204 //noinspection unchecked 205 T item = (T) singletons.get(clazz.getName()); 206 if (item == null) { 207 singletons.put(clazz.getName(), item = provider.get()); 208 } 209 return item; 210 } 211 } 212 213 /** 214 * Set to true if you'd like Robolectric to strictly simulate the real Android behavior when 215 * calling {@link Context#startActivity(android.content.Intent)}. Real Android throws a 216 * {@link android.content.ActivityNotFoundException} if given 217 * an {@link Intent} that is not known to the {@link android.content.pm.PackageManager} 218 * 219 * By default, this behavior is off (false). 220 * 221 * @param checkActivities True to validate activities. 222 */ checkActivities(boolean checkActivities)223 public void checkActivities(boolean checkActivities) { 224 ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread(); 225 ShadowInstrumentation shadowInstrumentation = 226 Shadow.extract(activityThread.getInstrumentation()); 227 shadowInstrumentation.checkActivities(checkActivities); 228 } 229 230 /** 231 * @deprecated Use {@link ShadowPopupMenu#getLatestPopupMenu()} instead. 232 */ 233 @Deprecated getLatestPopupMenu()234 public ShadowPopupMenu getLatestPopupMenu() { 235 return latestPopupMenu; 236 } 237 setLatestPopupMenu(ShadowPopupMenu latestPopupMenu)238 protected void setLatestPopupMenu(ShadowPopupMenu latestPopupMenu) { 239 this.latestPopupMenu = latestPopupMenu; 240 } 241 getLatestPopupWindow()242 public PopupWindow getLatestPopupWindow() { 243 return latestPopupWindow; 244 } 245 setLatestPopupWindow(PopupWindow latestPopupWindow)246 protected void setLatestPopupWindow(PopupWindow latestPopupWindow) { 247 this.latestPopupWindow = latestPopupWindow; 248 } 249 getLatestListPopupWindow()250 public ListPopupWindow getLatestListPopupWindow() { 251 return latestListPopupWindow; 252 } 253 setLatestListPopupWindow(ListPopupWindow latestListPopupWindow)254 protected void setLatestListPopupWindow(ListPopupWindow latestListPopupWindow) { 255 this.latestListPopupWindow = latestListPopupWindow; 256 } 257 258 public static class Wrapper { 259 public BroadcastReceiver broadcastReceiver; 260 public IntentFilter intentFilter; 261 public Context context; 262 public Throwable exception; 263 public String broadcastPermission; 264 public Handler scheduler; 265 Wrapper( BroadcastReceiver broadcastReceiver, IntentFilter intentFilter, Context context, String broadcastPermission, Handler scheduler)266 public Wrapper( 267 BroadcastReceiver broadcastReceiver, 268 IntentFilter intentFilter, 269 Context context, 270 String broadcastPermission, 271 Handler scheduler) { 272 this.broadcastReceiver = broadcastReceiver; 273 this.intentFilter = intentFilter; 274 this.context = context; 275 this.broadcastPermission = broadcastPermission; 276 this.scheduler = scheduler; 277 exception = new Throwable(); 278 } 279 getBroadcastReceiver()280 public BroadcastReceiver getBroadcastReceiver() { 281 return broadcastReceiver; 282 } 283 getIntentFilter()284 public IntentFilter getIntentFilter() { 285 return intentFilter; 286 } 287 getContext()288 public Context getContext() { 289 return context; 290 } 291 } 292 293 /** 294 * @deprecated Do not depend on this method to override services as it will be removed in a future 295 * update. The preferered method is use the shadow of the corresponding service. 296 */ 297 @Deprecated setSystemService(String key, Object service)298 public void setSystemService(String key, Object service) { 299 ShadowContextImpl shadowContext = Shadow.extract(realApplication.getBaseContext()); 300 shadowContext.setSystemService(key, service); 301 } 302 303 } 304