skip to content

Launch and Background

Starting, backgrounding, restoring and terminating the app under test and asking the driver what state it is in: a launch call on Apple platforms, an activity start on Android, shared state queries.

on this pageshow

explore

questions

5

In Appium, which commands foreground, background and terminate the app under test on Android and Apple platforms?

level: juniorimportance: must knowfreq 74%

answer

  1. four verbs, two platforms
  2. activate, background, terminate, query
  3. Android alone starts a component
  4. Apple adds launchApp and killApp
  5. app identity, never an element

basics

~20 s

Both sides share mobile: activateApp to foreground an app, mobile: backgroundApp to suspend it, mobile: terminateApp to stop it and mobile: queryAppState to check it. Android adds mobile: startActivity; Apple platforms add mobile: launchApp and mobile: killApp.

solid answer

~40 s

Four lifecycle commands exist on both the Android drivers and the XCUITest driver, each sent as a `mobile:` name plus one parameter map through `POST /session/:sessionId/execute/sync`: `mobile: activateApp` foregrounds the app (starting it if needed), `mobile: backgroundApp` pushes it out of the foreground for a number of `seconds`, `mobile: terminateApp` stops it, and `mobile: queryAppState` reports what state it is in. All four take the app identity — the package name on Android, the bundle identifier on Apple platforms. The extras diverge: Android adds `mobile: startActivity` for starting one named component, and the XCUITest driver adds `mobile: launchApp` for a cold start and `mobile: killApp` for a blunt process stop. On Android these live in `appium-android-driver`, the base that both the UiAutomator2 and Espresso drivers extend.

code

java · 14 lines
java
MutableCapabilities caps = new MutableCapabilities();
caps.setCapability("platformName", "Android");
caps.setCapability("appium:automationName", "UiAutomator2");
caps.setCapability("appium:appPackage", "com.schooldistrict.bustracker");
caps.setCapability("appium:appActivity", ".route.RouteMapActivity");

AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723"), caps);
String appId = "com.schooldistrict.bustracker";

driver.executeScript("mobile: terminateApp", Map.of("appId", appId));
driver.executeScript("mobile: activateApp", Map.of("appId", appId));
driver.executeScript("mobile: backgroundApp", Map.of("seconds", 5));
Object state = driver.executeScript("mobile: queryAppState", Map.of("appId", appId));
System.out.println(state);

go deeper

for a junior

Memorise the four shared names and what each one does, and be able to say which extras belong to Android and which to Apple platforms. Interviewers screen on exactly this map.

for a middle

Explain that these are driver execute methods carried over one execute endpoint, that they take app identity rather than an element, and that the Android set is inherited from the shared Android base driver.

for a senior

Show how you sequence them in a real suite: stop, start, interrupt, then confirm state before the first find, with the platform branch isolated to the one step that needs it.

for a principal

Own the argument for keeping the shared four as the portable spine of a suite and treating the platform-only commands as explicit, named exceptions rather than hiding them behind a fake common interface.

## The four commands both platforms share Appium models the lifecycle of the app under test as **driver execute methods**: a `mobile:` command name plus one parameter map, posted to `POST /session/:sessionId/execute/sync`. Four of them exist on both the Android drivers and the XCUITest driver, and together they are the backbone of any suite that has to restart, suspend or interrogate the app it is driving. - `mobile: activateApp` — bring the named app to the foreground, starting it if it is not already running. - `mobile: backgroundApp` — push the app under test out of the foreground for a given number of `seconds`. - `mobile: terminateApp` — stop the named app, reporting back whether there was anything to stop. - `mobile: queryAppState` — ask the driver what state the named app is in, answered as a number. All four are addressed by **app identity**, never by element. On Android that identity is the package name, the same value `appium:appPackage` carries; on Apple platforms it is the bundle identifier that `appium:bundleId` carries. Spell the parameter the way your own driver's execute-method reference spells it: the Android drivers and the XCUITest driver each document their own signatures, and the Android spelling does not automatically travel to Apple. One attribution detail matters more than it looks. The Android implementations are not declared in the UiAutomator2 driver. They live in `appium-android-driver`, the base driver that both the UiAutomator2 driver and the Espresso driver extend, which is why the same four names answer under either Android automation engine. The Apple implementations live in the XCUITest driver — the same driver that also drives iPadOS and tvOS, so *Apple platforms* is often the more honest phrase than *iOS*. ## Where the two platforms stop agreeing | Job | Android drivers | XCUITest driver | | --- | --- | --- | | Foreground the app | `mobile: activateApp` | `mobile: activateApp` | | Send it to the background | `mobile: backgroundApp` | `mobile: backgroundApp` | | Stop it | `mobile: terminateApp` | `mobile: terminateApp` | | Ask what state it is in | `mobile: queryAppState` | `mobile: queryAppState` | | Start one named entry point | `mobile: startActivity` | no equivalent | | Cold-start the whole app | `mobile: activateApp` | `mobile: launchApp` | | Force the process down | no equivalent | `mobile: killApp` | Android adds `mobile: startActivity`, which starts a named component instead of the app's default entry point — the same idea the `appium:appActivity` capability expresses at session start. Apple platforms add two commands with no Android twin: `mobile: launchApp`, which starts the app under XCUITest's control rather than resuming whatever was already there, and `mobile: killApp`, a blunter stop that takes the process down instead of asking the application under test to terminate itself. ## A school bus tracking suite, concretely Take a driver-facing school bus tracking app and a case that has to prove a route in progress survives a trip out of the foreground. The lifecycle calls read almost the same on both platforms: 1. Start from a known place: `mobile: terminateApp` for the app identity, so the case does not inherit whatever the previous case left on screen. 2. Bring it up: `mobile: activateApp` on Android; on Apple platforms either `mobile: activateApp` or `mobile: launchApp`, depending on whether the case wants a resume or a cold start. 3. Interrupt it: `mobile: backgroundApp` with a `seconds` value — the portable way to model the bus driver taking a call at a stop. 4. Confirm where you landed: `mobile: queryAppState` before the first find, rather than assuming the route map came back. Only step 2 needs a platform branch, and that is the shape most cross-platform suites settle into: a shared spine of four commands and a small, explicitly platform-named edge. ## What these commands do not do - They do not touch stored data. Wiping what the app saved is `mobile: clearApp`, a different command with its own platform rules. - They do not install or remove anything; the artifact commands are separate. - They do not guarantee a drawn screen. A foreground reading means the driver believes the app is frontmost, not that the route map has finished rendering. - They do not travel by name alone. An Android package name passed where a bundle identifier belongs simply does not name anything on an Apple device. ## Pitfalls worth naming - Writing `mobile: launchApp` in an Android branch. It is the XCUITest driver's, and the Android drivers will not answer it. - Expecting `mobile: startActivity` on Apple platforms. Entering the app at one inner screen there is a URL-entry problem, not a lifecycle-command one. - Treating `mobile: terminateApp` as a reset. It stops the app; it does not clear what the app stored. - Assuming `mobile: activateApp` is always a cold start. It resumes an existing task when there is one — exactly right for a background-and-restore case, and exactly wrong for a first-run case.

  • On Apple platforms, when would you reach for mobile: launchApp instead of mobile: activateApp?
    `mobile: launchApp` starts the app under XCUITest's control, which is what a case needs when it is about first-run behaviour. `mobile: activateApp` brings an app that may already be running back to the foreground and only starts it if nothing is there, so a suspended school bus tracking app resumes on the screen it left. Choose by whether the case is about a cold start or about restoring.
  • What does mobile: killApp give you on Apple platforms that mobile: terminateApp does not?
    `mobile: terminateApp` is the graceful stop and the default choice on both platforms. `mobile: killApp` is the XCUITest driver's blunt one: it takes the process down instead of asking the application under test to shut itself down, which is the fallback when the target will not stop cleanly. The Android drivers ship no `mobile: killApp` at all.
  • What happens if you call mobile: terminateApp for an app that is already stopped?
    Nothing harmful. The command reports that there was nothing to stop rather than raising, so a teardown helper can call it unconditionally on Android and on Apple platforms. If the case needs to know what the app was actually doing before the stop, read `mobile: queryAppState` first — the stop's own result is a poor record of the prior state.

saying these in an interview costs you the question

  • Claims mobile: launchApp works on the Android drivers too
  • Expects mobile: startActivity to exist on Apple platforms
  • Treats mobile: terminateApp as a way to clear stored data
  • Assumes mobile: activateApp always gives a cold start
  • Passes an Android package name where a bundle identifier belongs
  • Says these commands are declared by the UiAutomator2 driver itself
open as a page

In Appium on Android, when should a test start a named activity instead of activating the whole app?

level: seniorimportance: must knowfreq 56%

basics

~20 s

Use mobile: activateApp when the case wants the app as a whole, resumed or started at its normal entry point. Use Android's mobile: startActivity only when the case must land on one named screen directly, accepting the coupling that creates.

open as a page

How would you design one Appium lifecycle helper when only Android has mobile: startActivity and only Apple has mobile: launchApp?

level: principalimportance: must knowfreq 46%

basics

~10 s

Build the helper on the four commands both platforms answer, and expose the platform-only commands as explicit, platform-named operations. Never let an operation silently do nothing on the platform that cannot perform it.

open as a page

In Appium, what does mobile: queryAppState return, and does it mean the same on Android and Apple platforms?

level: middleimportance: should knowfreq 48%

basics

~20 s

It returns one integer from an ordered ladder: 0 not installed, 1 not running, 2 background suspended, 3 background, 4 foreground. Both the Android drivers and the XCUITest driver answer it, but they derive the value from different evidence.

open as a page

In an Appium session with appium:autoLaunch false, how does the app get started on Android and Apple platforms?

level: seniorimportance: should knowfreq 41%

basics

~10 s

The session is created and the app prepared on the device, but nothing is brought to the foreground. The test starts it: mobile: activateApp or mobile: startActivity on Android, mobile: launchApp on Apple platforms.

open as a page