skip to content

Modal Interruptions

System dialogs your app never drew: how the Android and iOS drivers accept or dismiss one, how to make that automatic, and why such a dialog is not simply another element in your own app's tree.

on this pageshow

explore

questions

4

In Appium, which command accepts a system alert on Android, and which one on iOS?

level: juniorimportance: must knowfreq 66%

answer

  1. One job, two different command names
  2. Android names the verb in the method
  3. iOS puts the verb in the parameters
  4. Only iOS has a session capability

basics

~10 s

On Android the UiAutomator2 driver exposes mobile: acceptAlert and mobile: dismissAlert; on iOS the XCUITest driver exposes mobile: alert, and only iOS also has the appium:autoAcceptAlerts capability that handles alerts without a call.

solid answer

~40 s

Both platforms drive a system dialog through an execute method posted to `POST /session/:sessionId/execute/sync`, but the method names differ. On **Android**, the UiAutomator2 driver declares `mobile: acceptAlert` and `mobile: dismissAlert` in its own execute-method map. On **iOS**, the XCUITest driver declares a single `mobile: alert` method and carries the action in its parameter map instead of in the name. The bigger divergence is what happens with no call at all: iOS accepts a session capability, `appium:autoAcceptAlerts`, so the driver deals with dialogs as they appear, and XCUITest adds settings — `acceptAlertButtonSelector`, `dismissAlertButtonSelector`, `autoClickAlertSelector` — that steer it. Android has no such capability. There you issue the command while the dialog is on screen, or it stays there.

code

json · 10 lines
json
{
  "capabilities": {
    "alwaysMatch": {
      "platformName": "iOS",
      "appium:automationName": "XCUITest",
      "appium:autoAcceptAlerts": true
    },
    "firstMatch": [{}]
  }
}

go deeper

for a junior

Be ready to name the command per platform without hedging: UiAutomator2's mobile: acceptAlert and mobile: dismissAlert on Android, XCUITest's mobile: alert on iOS. Saying Appium handles alerts, without naming a driver, reads as never having written the call.

for a middle

Explain the mechanism, not just the names: these are execute methods sent to POST /session/:sessionId/execute/sync, and iOS additionally accepts a session capability that Android has no twin for. Say why that asymmetry exists at the driver layer.

for a senior

Show that you know the failure mode in a real run. On Android the command is timed and does nothing when no dialog is up; on iOS the capability acts without leaving a seam in your code. Say how you would make either observable.

for a principal

Own the decision of where alert handling lives in a cross-platform suite. Argue for one mechanism both platforms genuinely share, and be explicit about what a capability-only policy costs you in behavioural parity between the two legs.

## The dialog your team never wrote Picture the regional bus-ticketing app under test. A rider taps **Stops near me**, and before your own screen appears the operating system puts up a dialog of its own. Nobody on your team drew that dialog. Your build attaches no identifier to it, and its button text arrives in whatever language the device is configured for. It is on top of your app, but it is not part of it. Because of that, Appium does not ask you to locate the dialog and tap it. Each mobile driver ships a dedicated command for the job — and the two drivers do not share a name. ## How the command travels (the one thing that is identical) Appium's drivers expose behaviour that has no WebDriver endpoint of its own as **execute methods**: a name beginning with `mobile:` plus one parameter map, sent as `POST /session/:sessionId/execute/sync`. Client bindings such as java-client and the Python client wrap that in an `executeScript` call. Android and iOS use exactly the same transport and the same endpoint spelling. Everything after the method name diverges. ## Android — UiAutomator2's two explicit commands On Android with `appium:automationName` set to UiAutomator2, two execute methods handle a system dialog: - `mobile: acceptAlert` — take the dialog's affirmative action - `mobile: dismissAlert` — take its negative action Both are declared in the **UiAutomator2 driver's own** execute-method map, the short list that also carries its gesture and window commands. That attribution is worth getting right, because most of Android's `mobile:` surface — `mobile: installApp`, `mobile: activateApp`, `mobile: clearApp`, `mobile: setConnectivity` and roughly sixty more — lives in `appium-android-driver`, the base driver that both UiAutomator2 and the Espresso driver extend. The alert pair is UiAutomator2's specifically, so say so when you name it. What Android does **not** have is a capability. There is nothing you can put in the `capabilities` map of `POST /session` that makes the Android driver clear a system dialog on your behalf. The commands are explicit and they are timed: you issue one while the dialog is actually on screen. ## iOS — XCUITest's single method, plus a capability and settings The XCUITest driver takes the opposite shape. It declares **one** method, `mobile: alert`, and carries the verb in the parameter map rather than in the method name. So the tempting cross-platform assumption fails in both directions: `mobile: acceptAlert` is not an XCUITest method, and `mobile: alert` is not a UiAutomator2 one. iOS then adds a surface Android has no counterpart for at all: 1. `appium:autoAcceptAlerts` — a **session capability**. Send it in `POST /session` and the driver deals with alerts as they appear, with no call from your code. 2. `acceptAlertButtonSelector` and `dismissAlertButtonSelector` — **settings** that name which button an accept or a dismiss should press. 3. `autoClickAlertSelector` — a setting for automatically clicking a matching element on an alert. 4. `respectSystemAlerts` — a setting that makes the driver account for a system alert when it works out which application is currently active. ## Side by side | | Android — UiAutomator2 driver | iOS — XCUITest driver | |---|---|---| | Accept | `mobile: acceptAlert` | `mobile: alert`, action in the map | | Dismiss | `mobile: dismissAlert` | `mobile: alert`, action in the map | | Unattended handling | none | `appium:autoAcceptAlerts` | | Button control | none | `acceptAlertButtonSelector`, `dismissAlertButtonSelector` | | Active-app awareness | — | `respectSystemAlerts` | | Transport | `POST /session/:sessionId/execute/sync` | `POST /session/:sessionId/execute/sync` | ## What this means when you write the code - Name the method **with its driver**: UiAutomator2's `mobile: acceptAlert`, XCUITest's `mobile: alert`. A bare `mobile:` name in a shared helper is an invitation to send one platform a command the other owns. - Do not fire the Android pair speculatively at every step. Most of the time there is no dialog to accept. - Do not ship `appium:autoAcceptAlerts` in a shared capability file and assume the Android leg behaves the same way. It will not, and the Android session starts regardless. - Remember that the button labels belong to the operating system and follow the device language — which is exactly why an accept command beats matching visible text. ## Two things this is not A modal your **own** app draws — the refund confirmation your team built into the ticketing flow — is an ordinary element on both platforms, and you locate and tap it the usual way. And a permission prompt, though it is also a system dialog, has its own dedicated per-driver surface rather than being handled through the generic alert commands. Keep the three cases apart whenever someone on the team says the word popup, because the mechanism is different in each.

  • If you send appium:autoAcceptAlerts to an Android UiAutomator2 session, what happens?
    The session starts. There is no Android capability that handles system dialogs unattended, so nothing is configured and no error tells you so. The first system dialog stays on screen until your code calls UiAutomator2's `mobile: acceptAlert` or `mobile: dismissAlert`. A shared capability file that carries the key silently gives the two platforms different behaviour.
  • Which HTTP request carries mobile: acceptAlert to the server?
    `POST /session/:sessionId/execute/sync`, with the method name and one parameter map in the body. Appium's `mobile:` commands are execute methods rather than routes of their own, so they all travel on that single endpoint. Client bindings expose it as `executeScript`. The endpoint spelling is the same on Android and iOS.

saying these in an interview costs you the question

  • Says mobile: acceptAlert works on iOS as well as Android
  • Thinks appium:autoAcceptAlerts has an Android capability equivalent
  • Calls the alert commands Appium's rather than a named driver's
  • Expects a system dialog to be tapped like an ordinary app element
  • Assumes alerts need a different endpoint from other execute methods
open as a page

Why does Appium ship dedicated alert commands on Android and iOS instead of tapping the dialog button?

level: middleimportance: should knowfreq 48%

basics

~20 s

A system dialog is drawn by the operating system, not by your app, so nothing in your build sets its ids or text. Both drivers therefore expose out-of-band alert commands: UiAutomator2's acceptAlert and dismissAlert on Android, XCUITest's alert on iOS.

open as a page

iOS has appium:autoAcceptAlerts and Android has none — how do you build one cross-platform modal-handling layer?

level: principalimportance: should knowfreq 40%

basics

~20 s

Converge on the explicit execute methods both platforms have — UiAutomator2's acceptAlert and dismissAlert on Android, XCUITest's alert on iOS — behind one wrapper, and treat appium:autoAcceptAlerts as an iOS-only safety net rather than as the policy.

open as a page

With appium:autoAcceptAlerts on, an iOS alert takes the wrong button. Which XCUITest settings pin the choice?

level: seniorimportance: nice to knowfreq 32%

basics

~10 s

On iOS, XCUITest's acceptAlertButtonSelector and dismissAlertButtonSelector name which button the accept or dismiss action presses, overriding the driver's default choice; autoClickAlertSelector covers a click on any alert. Android's UiAutomator2 driver has no equivalent setting.

open as a page