blob: cefb99e97bbae2bf614d5bfb4da8d74398d4c067 [file] [log] [blame]
package org.robolectric.shadows;
import static org.robolectric.shadow.api.Shadow.newInstanceOf;
import android.app.ActivityThread;
import android.app.Application;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.view.LayoutInflater;
import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.robolectric.RoboSettings;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.Scheduler;
@Implements(Application.class)
public class ShadowApplication extends ShadowContextWrapper {
@RealObject private Application realApplication;
private Scheduler backgroundScheduler = RoboSettings.isUseGlobalScheduler()
? getForegroundThreadScheduler()
: new Scheduler();
private List<android.widget.Toast> shownToasts = new ArrayList<>();
private PowerManager.WakeLock latestWakeLock;
private ShadowAlertDialog latestAlertDialog;
private ShadowDialog latestDialog;
private ShadowPopupMenu latestPopupMenu;
private Object bluetoothAdapter = newInstanceOf("android.bluetooth.BluetoothAdapter");
// these are managed by the AppSingletonizer... kinda gross, sorry [xw]
LayoutInflater layoutInflater;
AppWidgetManager appWidgetManager;
private PopupWindow latestPopupWindow;
private ListPopupWindow latestListPopupWindow;
/**
* @deprecated Use
* `shadowOf({@link androidx.test.core.app.ApplicationProvider#getApplicationContext})`
* instead.
*/
@Deprecated
public static ShadowApplication getInstance() {
return RuntimeEnvironment.application == null
? null
: Shadow.extract(RuntimeEnvironment.application);
}
/**
* Runs any background tasks previously queued by {@link android.os.AsyncTask#execute(Object[])}.
*
* Note: calling this method does not pause or un-pause the scheduler.
*/
public static void runBackgroundTasks() {
getInstance().getBackgroundThreadScheduler().advanceBy(0);
}
/**
* Attaches an application to a base context.
*
* @param context The context with which to initialize the application, whose base context will
* be attached to the application
*/
public void callAttach(Context context) {
ReflectionHelpers.callInstanceMethod(Application.class, realApplication, "attach",
ReflectionHelpers.ClassParameter.from(Context.class, context));
}
public List<Toast> getShownToasts() {
return shownToasts;
}
/**
* Return the foreground scheduler.
*
* @return Foreground scheduler.
*/
public Scheduler getForegroundThreadScheduler() {
return RuntimeEnvironment.getMasterScheduler();
}
/**
* Return the background scheduler.
*
* @return Background scheduler.
*/
public Scheduler getBackgroundThreadScheduler() {
return backgroundScheduler;
}
/** @deprecated Use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)} instead. */
@Deprecated
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return realApplication.registerReceiver(receiver, filter);
}
/**
* @deprecated Use {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String,
* Handler)} instead.
*/
@Deprecated
public Intent registerReceiver(
BroadcastReceiver receiver,
IntentFilter filter,
String broadcastPermission,
Handler scheduler) {
return realApplication.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
/** @deprecated Use {@link Context#sendBroadcast(Intent)} instead. */
@Deprecated
public void sendBroadcast(Intent intent) {
realApplication.sendBroadcast(intent);
}
/** @deprecated Use {@link Context#sendBroadcast(Intent, String)} instead. */
@Deprecated
public void sendBroadcast(Intent intent, String receiverPermission) {
realApplication.sendBroadcast(intent, receiverPermission);
}
/** @deprecated Use {@link Context#sendOrderedBroadcast(Intent, String)} instead. */
@Deprecated
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
realApplication.sendOrderedBroadcast(intent, receiverPermission);
}
/** @deprecated Use {@link Context#sendStickyBroadcast(Intent)} instead. */
@Deprecated
public void sendStickyBroadcast(Intent intent) {
realApplication.sendStickyBroadcast(intent);
}
/** @deprecated Use {@link Context#sendOrderedBroadcast} instead. */
@Deprecated
public void sendOrderedBroadcast(Intent intent, String receiverPermission,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
realApplication.sendOrderedBroadcast(
intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData,
initialExtras);
}
/** @deprecated Use {@link Context#startService(Intent)} instead. */
@Deprecated
public ComponentName startService(Intent intent) {
return realApplication.startService(intent);
}
/** @deprecated Use {@link Context#stopService(Intent)} instead. */
@Deprecated
public void stopService(Intent intent) {
realApplication.stopService(intent);
}
/** @deprecated Use {@link Context#bindService(Intent, ServiceConnection, int)} instead. */
@Deprecated
public boolean bindService(
final Intent intent, final ServiceConnection serviceConnection, int i) {
return realApplication.bindService(intent, serviceConnection, i);
}
/** @deprecated Use {@link Context#unbindService(ServiceConnection)} instead. */
@Deprecated
public void unbindService(final ServiceConnection serviceConnection) {
realApplication.unbindService(serviceConnection);
}
public void setComponentNameAndServiceForBindService(ComponentName name, IBinder service) {
getShadowInstrumentation().setComponentNameAndServiceForBindService(name, service);
}
public void setComponentNameAndServiceForBindServiceForIntent(
Intent intent, ComponentName name, IBinder service) {
getShadowInstrumentation()
.setComponentNameAndServiceForBindServiceForIntent(intent, name, service);
}
public void assertNoBroadcastListenersOfActionRegistered(ContextWrapper context, String action) {
getShadowInstrumentation().assertNoBroadcastListenersOfActionRegistered(context, action);
}
public List<ServiceConnection> getBoundServiceConnections() {
return getShadowInstrumentation().getBoundServiceConnections();
}
public void setUnbindServiceShouldThrowIllegalArgument(boolean flag) {
getShadowInstrumentation().setUnbindServiceShouldThrowIllegalArgument(flag);
}
public List<ServiceConnection> getUnboundServiceConnections() {
return getShadowInstrumentation().getUnboundServiceConnections();
}
/** @deprecated use PackageManager.queryBroadcastReceivers instead */
@Deprecated
public boolean hasReceiverForIntent(Intent intent) {
return getShadowInstrumentation().hasReceiverForIntent(intent);
}
/** @deprecated use PackageManager.queryBroadcastReceivers instead */
@Deprecated
public List<BroadcastReceiver> getReceiversForIntent(Intent intent) {
return getShadowInstrumentation().getReceiversForIntent(intent);
}
/**
* @return list of {@link Wrapper}s for registered receivers
*/
public List<Wrapper> getRegisteredReceivers() {
return getShadowInstrumentation().getRegisteredReceivers();
}
/**
* @return the layout inflater used by this {@code Application}
*/
public LayoutInflater getLayoutInflater() {
return layoutInflater;
}
/**
* @return the app widget manager used by this {@code Application}
*/
public AppWidgetManager getAppWidgetManager() {
return appWidgetManager;
}
/**
* @deprecated Use {@link ShadowAlertDialog#getLatestAlertDialog()} instead.
*/
@Deprecated
public ShadowAlertDialog getLatestAlertDialog() {
return latestAlertDialog;
}
public void setLatestAlertDialog(ShadowAlertDialog latestAlertDialog) {
this.latestAlertDialog = latestAlertDialog;
}
/**
* @deprecated Use {@link ShadowDialog#getLatestDialog()} instead.
*/
@Deprecated
public ShadowDialog getLatestDialog() {
return latestDialog;
}
public void setLatestDialog(ShadowDialog latestDialog) {
this.latestDialog = latestDialog;
}
public Object getBluetoothAdapter() {
return bluetoothAdapter;
}
public void declareActionUnbindable(String action) {
getShadowInstrumentation().declareActionUnbindable(action);
}
public PowerManager.WakeLock getLatestWakeLock() {
return latestWakeLock;
}
public void addWakeLock( PowerManager.WakeLock wl ) {
latestWakeLock = wl;
}
public void clearWakeLocks() {
latestWakeLock = null;
}
private final Map<String, Object> singletons = new HashMap<>();
public <T> T getSingleton(Class<T> clazz, Provider<T> provider) {
synchronized (singletons) {
//noinspection unchecked
T item = (T) singletons.get(clazz.getName());
if (item == null) {
singletons.put(clazz.getName(), item = provider.get());
}
return item;
}
}
/**
* Set to true if you'd like Robolectric to strictly simulate the real Android behavior when
* calling {@link Context#startActivity(android.content.Intent)}. Real Android throws a
* {@link android.content.ActivityNotFoundException} if given
* an {@link Intent} that is not known to the {@link android.content.pm.PackageManager}
*
* By default, this behavior is off (false).
*
* @param checkActivities True to validate activities.
*/
public void checkActivities(boolean checkActivities) {
ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
ShadowInstrumentation shadowInstrumentation =
Shadow.extract(activityThread.getInstrumentation());
shadowInstrumentation.checkActivities(checkActivities);
}
public ShadowPopupMenu getLatestPopupMenu() {
return latestPopupMenu;
}
public void setLatestPopupMenu(ShadowPopupMenu latestPopupMenu) {
this.latestPopupMenu = latestPopupMenu;
}
public PopupWindow getLatestPopupWindow() {
return latestPopupWindow;
}
public void setLatestPopupWindow(PopupWindow latestPopupWindow) {
this.latestPopupWindow = latestPopupWindow;
}
public ListPopupWindow getLatestListPopupWindow() {
return latestListPopupWindow;
}
public void setLatestListPopupWindow(ListPopupWindow latestListPopupWindow) {
this.latestListPopupWindow = latestListPopupWindow;
}
public static class Wrapper {
public BroadcastReceiver broadcastReceiver;
public IntentFilter intentFilter;
public Context context;
public Throwable exception;
public String broadcastPermission;
public Handler scheduler;
public Wrapper(
BroadcastReceiver broadcastReceiver,
IntentFilter intentFilter,
Context context,
String broadcastPermission,
Handler scheduler) {
this.broadcastReceiver = broadcastReceiver;
this.intentFilter = intentFilter;
this.context = context;
this.broadcastPermission = broadcastPermission;
this.scheduler = scheduler;
exception = new Throwable();
}
public BroadcastReceiver getBroadcastReceiver() {
return broadcastReceiver;
}
public IntentFilter getIntentFilter() {
return intentFilter;
}
public Context getContext() {
return context;
}
}
/**
* @deprecated Do not depend on this method to override services as it will be removed in a future
* update. The preferered method is use the shadow of the corresponding service.
*/
@Deprecated
public void setSystemService(String key, Object service) {
ShadowContextImpl shadowContext = Shadow.extract(realApplication.getBaseContext());
shadowContext.setSystemService(key, service);
}
}