blob: 64ac51e6a59ba63fb87550f781b94ab9a0eb93e6 [file] [log] [blame]
package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.JELLY_BEAN;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.M;
import static org.robolectric.shadow.api.Shadow.directlyOn;
import android.R;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.Application;
import android.app.Dialog;
import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.Window;
import com.android.internal.app.IVoiceInteractor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.HiddenApi;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.fakes.RoboMenuItem;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
@Implements(Activity.class)
public class ShadowActivity extends ShadowContextThemeWrapper {
@RealObject
protected Activity realActivity;
private int resultCode;
private Intent resultIntent;
private Activity parent;
private int requestedOrientation = -1;
private View currentFocus;
private Integer lastShownDialogId = null;
private int pendingTransitionEnterAnimResId = -1;
private int pendingTransitionExitAnimResId = -1;
private Object lastNonConfigurationInstance;
private Map<Integer, Dialog> dialogForId = new HashMap<>();
private ArrayList<Cursor> managedCursors = new ArrayList<>();
private int mDefaultKeyMode = Activity.DEFAULT_KEYS_DISABLE;
private SpannableStringBuilder mDefaultKeySsb = null;
private int streamType = -1;
private boolean mIsTaskRoot = true;
private Menu optionsMenu;
private ComponentName callingActivity;
private String callingPackage;
private boolean isLockTask;
private PermissionsRequest lastRequestedPermission;
public void setApplication(Application application) {
ReflectionHelpers.setField(realActivity, "mApplication", application);
}
public void callAttach(Intent intent) {
int apiLevel = RuntimeEnvironment.getApiLevel();
Application application = RuntimeEnvironment.application;
Context baseContext = RuntimeEnvironment.application.getBaseContext();
Class<?> nonConfigurationInstancesClass = getNonConfigurationClass();
ActivityInfo activityInfo;
try {
activityInfo = application.getPackageManager().getActivityInfo(new ComponentName(application.getPackageName(), realActivity.getClass().getName()), PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
} catch (NameNotFoundException e) {
throw new RuntimeException();
}
CharSequence activityTitle = activityInfo.loadLabel(baseContext.getPackageManager());
Instrumentation instrumentation =
((ActivityThread) RuntimeEnvironment.getActivityThread()).getInstrumentation();
if (apiLevel <= Build.VERSION_CODES.KITKAT) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()));
} else if (apiLevel <= Build.VERSION_CODES.LOLLIPOP) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()),
ReflectionHelpers.ClassParameter.from(IVoiceInteractor.class, null)); // ADDED
} else if (apiLevel <= Build.VERSION_CODES.M) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()),
ReflectionHelpers.ClassParameter.from(String.class, "referrer"),
ReflectionHelpers.ClassParameter.from(
IVoiceInteractor.class, null)); // SAME AS LOLLIPOP ---------------------------
} else if (apiLevel <= Build.VERSION_CODES.N_MR1) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()),
ReflectionHelpers.ClassParameter.from(String.class, "referrer"),
ReflectionHelpers.ClassParameter.from(IVoiceInteractor.class, null),
ReflectionHelpers.ClassParameter.from(Window.class, null) // ADDED
);
} else if (apiLevel <= Build.VERSION_CODES.P) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()),
ReflectionHelpers.ClassParameter.from(String.class, "referrer"),
ReflectionHelpers.ClassParameter.from(IVoiceInteractor.class, null),
ReflectionHelpers.ClassParameter.from(Window.class, null),
ReflectionHelpers.ClassParameter.from(
ViewRootImpl.ActivityConfigCallback.class, null) // ADDED
);
} else if (apiLevel >= Build.VERSION_CODES.Q) {
ReflectionHelpers.callInstanceMethod(
Activity.class,
realActivity,
"attach",
ReflectionHelpers.ClassParameter.from(Context.class, baseContext),
ReflectionHelpers.ClassParameter.from(
ActivityThread.class, RuntimeEnvironment.getActivityThread()),
ReflectionHelpers.ClassParameter.from(Instrumentation.class, instrumentation),
ReflectionHelpers.ClassParameter.from(IBinder.class, null),
ReflectionHelpers.ClassParameter.from(int.class, 0),
ReflectionHelpers.ClassParameter.from(Application.class, application),
ReflectionHelpers.ClassParameter.from(Intent.class, intent),
ReflectionHelpers.ClassParameter.from(ActivityInfo.class, activityInfo),
ReflectionHelpers.ClassParameter.from(CharSequence.class, activityTitle),
ReflectionHelpers.ClassParameter.from(Activity.class, null),
ReflectionHelpers.ClassParameter.from(String.class, "id"),
ReflectionHelpers.ClassParameter.from(nonConfigurationInstancesClass, null),
ReflectionHelpers.ClassParameter.from(
Configuration.class, application.getResources().getConfiguration()),
ReflectionHelpers.ClassParameter.from(String.class, "referrer"),
ReflectionHelpers.ClassParameter.from(IVoiceInteractor.class, null),
ReflectionHelpers.ClassParameter.from(Window.class, null),
ReflectionHelpers.ClassParameter.from(
ViewRootImpl.ActivityConfigCallback.class, null),
ReflectionHelpers.ClassParameter.from(IBinder.class, null) // ADDED
);
} else {
throw new RuntimeException("Could not find AndroidRuntimeAdapter for API level: " + apiLevel);
}
int theme = activityInfo.getThemeResource();
if (theme != 0) {
realActivity.setTheme(theme);
}
}
private Class<?> getNonConfigurationClass() {
try {
return getClass().getClassLoader().loadClass("android.app.Activity$NonConfigurationInstances");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public void setCallingActivity(ComponentName activityName) {
callingActivity = activityName;
}
@Implementation
protected ComponentName getCallingActivity() {
return callingActivity;
}
public void setCallingPackage(String packageName) {
callingPackage = packageName;
}
@Implementation
protected String getCallingPackage() {
return callingPackage;
}
@Implementation
protected void setDefaultKeyMode(int keyMode) {
mDefaultKeyMode = keyMode;
// Some modes use a SpannableStringBuilder to track & dispatch input events
// This list must remain in sync with the switch in onKeyDown()
switch (mDefaultKeyMode) {
case Activity.DEFAULT_KEYS_DISABLE:
case Activity.DEFAULT_KEYS_SHORTCUT:
mDefaultKeySsb = null; // not used in these modes
break;
case Activity.DEFAULT_KEYS_DIALER:
case Activity.DEFAULT_KEYS_SEARCH_LOCAL:
case Activity.DEFAULT_KEYS_SEARCH_GLOBAL:
mDefaultKeySsb = new SpannableStringBuilder();
Selection.setSelection(mDefaultKeySsb, 0);
break;
default:
throw new IllegalArgumentException();
}
}
public int getDefaultKeymode() {
return mDefaultKeyMode;
}
@Implementation
protected final void setResult(int resultCode) {
this.resultCode = resultCode;
}
@Implementation
protected final void setResult(int resultCode, Intent data) {
this.resultCode = resultCode;
this.resultIntent = data;
}
@Implementation
protected LayoutInflater getLayoutInflater() {
return LayoutInflater.from(realActivity);
}
@Implementation
protected MenuInflater getMenuInflater() {
return new MenuInflater(realActivity);
}
/**
* Checks to ensure that the{@code contentView} has been set
*
* @param id ID of the view to find
* @return the view
* @throws RuntimeException if the {@code contentView} has not been called first
*/
@Implementation
protected View findViewById(int id) {
return getWindow().findViewById(id);
}
@Implementation
protected final Activity getParent() {
return parent;
}
/**
* Allow setting of Parent fragmentActivity (for unit testing purposes only)
*
* @param parent Parent fragmentActivity to set on this fragmentActivity
*/
@HiddenApi @Implementation
public void setParent(Activity parent) {
this.parent = parent;
}
@Implementation
protected void onBackPressed() {
finish();
}
@Implementation
protected void finish() {
// Sets the mFinished field in the real activity so NoDisplay activities can be tested.
ReflectionHelpers.setField(Activity.class, realActivity, "mFinished", true);
}
@Implementation(minSdk = LOLLIPOP)
protected void finishAndRemoveTask() {
// Sets the mFinished field in the real activity so NoDisplay activities can be tested.
ReflectionHelpers.setField(Activity.class, realActivity, "mFinished", true);
}
@Implementation(minSdk = JELLY_BEAN)
protected void finishAffinity() {
// Sets the mFinished field in the real activity so NoDisplay activities can be tested.
ReflectionHelpers.setField(Activity.class, realActivity, "mFinished", true);
}
public void resetIsFinishing() {
ReflectionHelpers.setField(Activity.class, realActivity, "mFinished", false);
}
/**
* Returns whether {@link #finish()} was called.
*
* @deprecated Use {@link Activity#isFinishing()} instead.
*/
@Deprecated
public boolean isFinishing() {
return directlyOn(realActivity, Activity.class).isFinishing();
}
/**
* Constructs a new Window (a {@link com.android.internal.policy.impl.PhoneWindow}) if no window
* has previously been set.
*
* @return the window associated with this Activity
*/
@Implementation
protected Window getWindow() {
Window window = directlyOn(realActivity, Activity.class).getWindow();
if (window == null) {
try {
window = ShadowWindow.create(realActivity);
setWindow(window);
} catch (Exception e) {
throw new RuntimeException("Window creation failed!", e);
}
}
return window;
}
public void setWindow(Window window) {
ReflectionHelpers.setField(realActivity, "mWindow", window);
}
@Implementation
protected void runOnUiThread(Runnable action) {
ShadowApplication.getInstance().getForegroundThreadScheduler().post(action);
}
@Implementation
protected void setRequestedOrientation(int requestedOrientation) {
if (getParent() != null) {
getParent().setRequestedOrientation(requestedOrientation);
} else {
this.requestedOrientation = requestedOrientation;
}
}
@Implementation
protected int getRequestedOrientation() {
if (getParent() != null) {
return getParent().getRequestedOrientation();
} else {
return this.requestedOrientation;
}
}
@Implementation
protected int getTaskId() {
return 0;
}
/**
* @return the {@code contentView} set by one of the {@code setContentView()} methods
*/
public View getContentView() {
return ((ViewGroup) getWindow().findViewById(R.id.content)).getChildAt(0);
}
/**
* @return the {@code resultCode} set by one of the {@code setResult()} methods
*/
public int getResultCode() {
return resultCode;
}
/**
* @return the {@code Intent} set by {@link #setResult(int, android.content.Intent)}
*/
public Intent getResultIntent() {
return resultIntent;
}
/**
* Consumes and returns the next {@code Intent} on the
* started activities for results stack.
*
* @return the next started {@code Intent} for an activity, wrapped in
* an {@link ShadowActivity.IntentForResult} object
*/
public IntentForResult getNextStartedActivityForResult() {
ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
ShadowInstrumentation shadowInstrumentation = Shadow.extract(activityThread.getInstrumentation());
return shadowInstrumentation.getNextStartedActivityForResult();
}
/**
* Returns the most recent {@code Intent} started by
* {@link Activity#startActivityForResult(Intent, int)} without consuming it.
*
* @return the most recently started {@code Intent}, wrapped in
* an {@link ShadowActivity.IntentForResult} object
*/
public IntentForResult peekNextStartedActivityForResult() {
ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
ShadowInstrumentation shadowInstrumentation = Shadow.extract(activityThread.getInstrumentation());
return shadowInstrumentation.peekNextStartedActivityForResult();
}
@Implementation
protected Object getLastNonConfigurationInstance() {
return lastNonConfigurationInstance;
}
public void setLastNonConfigurationInstance(Object lastNonConfigurationInstance) {
this.lastNonConfigurationInstance = lastNonConfigurationInstance;
}
/**
* @param view View to focus.
*/
public void setCurrentFocus(View view) {
currentFocus = view;
}
@Implementation
protected View getCurrentFocus() {
return currentFocus;
}
public int getPendingTransitionEnterAnimationResourceId() {
return pendingTransitionEnterAnimResId;
}
public int getPendingTransitionExitAnimationResourceId() {
return pendingTransitionExitAnimResId;
}
@Implementation
protected boolean onCreateOptionsMenu(Menu menu) {
optionsMenu = menu;
return directlyOn(realActivity, Activity.class).onCreateOptionsMenu(menu);
}
/**
* Return the options menu.
*
* @return Options menu.
*/
public Menu getOptionsMenu() {
return optionsMenu;
}
/**
* Perform a click on a menu item.
*
* @param menuItemResId Menu item resource ID.
* @return True if the click was handled, false otherwise.
*/
public boolean clickMenuItem(int menuItemResId) {
final RoboMenuItem item = new RoboMenuItem(menuItemResId);
return realActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item);
}
/** For internal use only. Not for public use. */
public void callOnActivityResult(int requestCode, int resultCode, Intent resultData) {
final ActivityInvoker invoker = new ActivityInvoker();
invoker
.call("onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class)
.with(requestCode, resultCode, resultData);
}
/**
* Container object to hold an Intent, together with the requestCode used
* in a call to {@code Activity.startActivityForResult(Intent, int)}
*/
public static class IntentForResult {
public Intent intent;
public int requestCode;
public Bundle options;
public IntentForResult(Intent intent, int requestCode) {
this.intent = intent;
this.requestCode = requestCode;
this.options = null;
}
public IntentForResult(Intent intent, int requestCode, Bundle options) {
this.intent = intent;
this.requestCode = requestCode;
this.options = options;
}
}
public void receiveResult(Intent requestIntent, int resultCode, Intent resultIntent) {
ActivityThread activityThread = (ActivityThread) RuntimeEnvironment.getActivityThread();
ShadowInstrumentation shadowInstrumentation = Shadow.extract(activityThread.getInstrumentation());
int requestCode = shadowInstrumentation.getRequestCodeForIntent(requestIntent);
callOnActivityResult(requestCode, resultCode, resultIntent);
}
@Implementation
protected final void showDialog(int id) {
showDialog(id, null);
}
@Implementation
protected final void dismissDialog(int id) {
final Dialog dialog = dialogForId.get(id);
if (dialog == null) {
throw new IllegalArgumentException();
}
dialog.dismiss();
}
@Implementation
protected final void removeDialog(int id) {
dialogForId.remove(id);
}
@Implementation
protected final boolean showDialog(int id, Bundle bundle) {
this.lastShownDialogId = id;
Dialog dialog = dialogForId.get(id);
if (dialog == null) {
final ActivityInvoker invoker = new ActivityInvoker();
dialog = (Dialog) invoker.call("onCreateDialog", Integer.TYPE).with(id);
if (dialog == null) {
return false;
}
if (bundle == null) {
invoker.call("onPrepareDialog", Integer.TYPE, Dialog.class).with(id, dialog);
} else {
invoker.call("onPrepareDialog", Integer.TYPE, Dialog.class, Bundle.class).with(id, dialog, bundle);
}
dialogForId.put(id, dialog);
}
dialog.show();
return true;
}
public void setIsTaskRoot(boolean isRoot) {
mIsTaskRoot = isRoot;
}
@Implementation
protected final boolean isTaskRoot() {
return mIsTaskRoot;
}
/**
* @return the dialog resource id passed into
* {@code Activity.showDialog(int, Bundle)} or {@code Activity.showDialog(int)}
*/
public Integer getLastShownDialogId() {
return lastShownDialogId;
}
public boolean hasCancelledPendingTransitions() {
return pendingTransitionEnterAnimResId == 0 && pendingTransitionExitAnimResId == 0;
}
@Implementation
protected void overridePendingTransition(int enterAnim, int exitAnim) {
pendingTransitionEnterAnimResId = enterAnim;
pendingTransitionExitAnimResId = exitAnim;
}
public Dialog getDialogById(int dialogId) {
return dialogForId.get(dialogId);
}
@Implementation
protected void recreate() {
Bundle outState = new Bundle();
final ActivityInvoker invoker = new ActivityInvoker();
invoker.call("onSaveInstanceState", Bundle.class).with(outState);
invoker.call("onPause").withNothing();
invoker.call("onStop").withNothing();
Object nonConfigInstance = invoker.call("onRetainNonConfigurationInstance").withNothing();
setLastNonConfigurationInstance(nonConfigInstance);
invoker.call("onDestroy").withNothing();
invoker.call("onCreate", Bundle.class).with(outState);
invoker.call("onStart").withNothing();
invoker.call("onRestoreInstanceState", Bundle.class).with(outState);
invoker.call("onResume").withNothing();
}
@Implementation
protected void startManagingCursor(Cursor c) {
managedCursors.add(c);
}
@Implementation
protected void stopManagingCursor(Cursor c) {
managedCursors.remove(c);
}
public List<Cursor> getManagedCursors() {
return managedCursors;
}
@Implementation
protected final void setVolumeControlStream(int streamType) {
this.streamType = streamType;
}
@Implementation
protected final int getVolumeControlStream() {
return streamType;
}
@Implementation(minSdk = M)
protected final void requestPermissions(String[] permissions, int requestCode) {
lastRequestedPermission = new PermissionsRequest(permissions, requestCode);
}
/**
* Starts a lock task.
*
* <p>The status of the lock task can be verified using {@link #isLockTask} method. Otherwise this
* implementation has no effect.
*/
@Implementation(minSdk = LOLLIPOP)
protected void startLockTask() {
Shadow.<ShadowActivityManager>extract(getActivityManager())
.setLockTaskModeState(ActivityManager.LOCK_TASK_MODE_LOCKED);
}
/**
* Stops a lock task.
*
* <p>The status of the lock task can be verified using {@link #isLockTask} method. Otherwise this
* implementation has no effect.
*/
@Implementation(minSdk = LOLLIPOP)
protected void stopLockTask() {
Shadow.<ShadowActivityManager>extract(getActivityManager())
.setLockTaskModeState(ActivityManager.LOCK_TASK_MODE_NONE);
}
/**
* Returns if the activity is in the lock task mode.
*
* @deprecated Use {@link ActivityManager#getLockTaskModeState} instead.
*/
@Deprecated
public boolean isLockTask() {
return getActivityManager().isInLockTaskMode();
}
private ActivityManager getActivityManager() {
return (ActivityManager) realActivity.getSystemService(Context.ACTIVITY_SERVICE);
}
/**
* Gets the last permission request submitted to this activity.
*
* @return The permission request details.
*/
public PermissionsRequest getLastRequestedPermission() {
return lastRequestedPermission;
}
private final class ActivityInvoker {
private Method method;
public ActivityInvoker call(final String methodName, final Class... argumentClasses) {
try {
method = Activity.class.getDeclaredMethod(methodName, argumentClasses);
method.setAccessible(true);
return this;
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public Object withNothing() {
return with();
}
public Object with(final Object... parameters) {
try {
return method.invoke(realActivity, parameters);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
/** Class to hold a permissions request, including its request code. */
public static class PermissionsRequest {
public final int requestCode;
public final String[] requestedPermissions;
public PermissionsRequest(String[] requestedPermissions, int requestCode) {
this.requestedPermissions = requestedPermissions;
this.requestCode = requestCode;
}
}
}