How to regain Access on a Activity after sending it to background
Asked Answered
D

5

7

With Espresso I try to test sending an Activity to background, with the Home button and then getting it up in the foreground again to make some checks:

@EspressoTest
public void test() {
    onSomeView().check(matches(isDisplayed()));
    getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_HOME);

    Context context = getInstrumentation().getTargetContext();
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);

    onSomeView().check(matches(isDisplayed()));
}

I had to use intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); which was suggested by an exception, but apart of that I also tested, starting it as the Launcher Activity, or using FLAG_ACTIVITY_REORDER_TO_FRONT, but the view is not visible. Even though the test passes.

Depolarize answered 25/4, 2014 at 12:33 Comment(0)
V
10

Please consider this response as it works 100% when you want to goBackgroundByClickingHomeThenGetBackToTheApp.

UiDevice device = UiDevice.getInstance(getInstrumentation());
        device.pressHome();
        device.pressRecentApps();
        device.findObject(new UiSelector().text(getTargetContext().getString(getTargetContext().getApplicationInfo().labelRes)))
                .click();
Vertebra answered 15/2, 2018 at 15:54 Comment(5)
With the new Android test runner in place this answer is more accurate. Thanks.Depolarize
Just to add that calling pressRecentApps() twice will make the app leave the foreground and resume in a slightly shorter timePeltry
@Peltry Nope, in Pixel one with SDK 28, it gives "App is not found" toast :(Sabbatical
I had to add Thread.sleep(1500L) before attempting to resume the app (the last line). Both the answer above and calling pressRecentApps() twice worked with this minor change.Vina
Does not work on 9/28/P. https://mcmap.net/q/1401595/-how-to-regain-access-on-a-activity-after-sending-it-to-background is OS version agnostic AFAIK.Burlington
D
8

Ok I figured it out. First it is necessary to use the Activity Context provided by getActivity, and then I could use intents to send the activity in background and in foreground, using the HOME category and the FLAG_ACTIVITY_REORDER_TO_FRONT:

private void goHome(Activity activity) {
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    activity.startActivity(intent);
}

private void bringToForeground(Activity activity) {
    Intent intent = new Intent(activity, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
    activity.startActivity(intent);
}

@EspressoTest
public void test() {
    //do some ui stuff to ensure the activity is up and running
    goHome(getActivity());
    // eventually sleep, or implement an idling resource
    bringToForeground(getActivity());
    // do some ui tests
}
Depolarize answered 29/4, 2014 at 12:57 Comment(3)
What if I want to do the same with HomeActivity? I have some tests which need to be tested for home activity. Basically the app needs to go to the background and comeback to foreground again to reproduce the case. What do you is this possible?Eba
That concept works for all activities. What do you mean by HomeActivity?Depolarize
I mean the launcher Activity. I achieved to the solution by using UiAutomator from Espresso.Eba
S
4

You can do this using UI Automator (you can use both espresso and UI Automator together).

val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
device.pressHome()
device.pressRecentApps()
val selector = UiSelector()
val recentApp = device.findObject(selector.descriptionContains("App Description"))
recentApp.click()

This backgrounded my app and brought it to the foreground

Selfrespect answered 14/8, 2017 at 20:55 Comment(2)
Yes now you can do that, please consider the above answer as legacy. It would be nice if you could also mention the Testrunner ans android-support-test version you have being using.Depolarize
androidTestCompile('com.android.support.test.uiautomator:uiautomator-v18:2.1.1') and androidTestCompile('com.android.support.test:runner:1.0.0')Selfrespect
T
0

in my use-case I needed to stress-test some activity, running multiple times "go to BG and then to FG and then to BG and to FG ....". ended up using this code:

  @Test
  fun moveAppToBgAndFg_multipleTimes() {
    val instrumentation = InstrumentationRegistry.getInstrumentation()
    val device = UiDevice.getInstance(instrumentation)
    launchActivity<MyActivity>().use {
      // ... prepare the activity if you need...
      // when ready, start to throw the app to BG and FG!
      repeat(100) {
        // throw app to BG
        device.pressHome() // this also adds appropriate "Thread.sleep()" delay

        // show recent apps
        device.pressRecentApps()
        Thread.sleep(1000L) // account for "recent apps" enter-animation

        // click screen's center, my app is the last recent app so it's shown there
        device.click(device.displayWidth / 2, device.displayHeight / 2)
        Thread.sleep(500L) // account for app's enter-animation
      }
    }
  }
Theatheaceous answered 1/6, 2022 at 11:16 Comment(0)
T
0

For me, finding the app by checking the label after sending it to the background was not an option, as not all devices provide this label in the recent apps view, causing the test to fail.

To fix this, I used the following code:

val instrumentation = InstrumentationRegistry.getInstrumentation()
val device = UiDevice.getInstance(instrumentation)
device.pressHome()
device.waitForIdle()
device.pressRecentApps()
device.wait(Until.findObject(By.scrollable(true)), 3000)
device.findObject(UiSelector().index(0)).click()

This ensures that the last used app (the application under test) is always at position 0.

Tetrafluoroethylene answered 18/7, 2024 at 16:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.