In Appium, which execute method presses a hardware key on Android, and which one on iOS?
answer
- the two platforms share no call
- one takes a number, one a name
- Android KeyEvent keycode, Apple button label
- UiAutomator2 declares one, XCUITest the other
basics
~10 sOn Android, UiAutomator2 exposes mobile: pressKey, taking a numeric Android KeyEvent keycode. On Apple platforms, XCUITest exposes mobile: pressButton, taking a named button such as volumeup. Neither call exists on the other platform.
solid answer
~40 sHardware keys are one of the places Appium does not paper over the platforms. On Android, the UiAutomator2 driver's `mobile: pressKey` takes a **numeric** Android `KeyEvent` keycode — `4` for back, `24` for volume up — plus optional `metastate` and `isLongPress`. On Apple platforms, the XCUITest driver's `mobile: pressButton` takes a **name** from a short, closed set of physical buttons, such as `home`, `volumeup` or `volumedown`; there is no keycode and no long-press flag. Both travel as ordinary `mobile:` execute methods over `POST /session/:sessionId/execute/sync`. Appium 3's migration guide points the old `POST /appium/device/press_keycode` route at `mobile: pressKey` on Android and at XCUITest's `mobile: keys` on iPadOS. A cross-platform suite branches on `platformName`; it cannot share one call.
code
java · 22 linesimport io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import java.util.Map;
public final class KayakRentalHardwareKeys {
private KayakRentalHardwareKeys() {
}
// Android, UiAutomator2 driver: a numeric KeyEvent keycode (24 = volume up).
public static void volumeUpOnAndroid(AndroidDriver driver) {
driver.executeScript("mobile: pressKey", Map.of(
"keycode", 24,
"isLongPress", false));
}
// Apple platforms, XCUITest driver: a named chassis button, never a number.
public static void volumeUpOnApple(IOSDriver driver) {
driver.executeScript("mobile: pressButton", Map.of(
"name", "volumeup"));
}
}go deeper
Be ready to name the two calls and say which driver owns each. Android takes a number and Apple platforms take a button name is an acceptable summary, as long as you attach each half to its platform.
Explain the shape of each parameter map, and why one platform can accept an open integer space while the other accepts only a fixed list of chassis button names.
Show that you know a hardware key is a device-level action with no element target, and describe how you confirm what actually had focus when a press produced nothing.
Own the decision about whether a suite exposes a shared hardware-key abstraction at all, given that the two vocabularies do not map onto each other one for one.
## The problem hardware keys create A hardware key event is an input the application under test does not own. Tap a button inside the kayak-rental app and the tap is delivered to a view the app itself rendered; press volume-up while its booking calendar is on screen and the operating system, not the app, receives the event and decides who gets it. Appium therefore cannot express a hardware key as an element interaction — there is no element to send it to — and exposes it as a driver-level execute method instead. Because the two operating systems model that layer differently, the drivers model it differently too. This is one of the cases where the divergence **is** the content: there is no portable call, and a suite that pretends otherwise is hiding a branch it will have to write anyway. ## Android: `mobile: pressKey` on the UiAutomator2 driver The UiAutomator2 driver declares `mobile: pressKey` in its own execute-method map, next to its gesture and window commands. The parameter map is small: - `keycode` — a **number**, one of the Android platform's `KeyEvent` constants. `4` is back, `24` is volume up, `25` is volume down, `66` is enter. - `metastate` — an optional modifier bitmask, which is how Android says *this key was pressed while shift or control was held*. - `isLongPress` — an optional flag. Android models a long key press as a distinct kind of event rather than as a duration the caller times. The vocabulary is open-ended in the sense that matters: anything the platform can deliver as a key event has a number, and if you know the number you can send it. Nothing in the call names the kayak-rental app — the driver injects the event and the system routes it. ## Apple platforms: `mobile: pressButton` on the XCUITest driver The XCUITest driver declares `mobile: pressButton`, and its parameter is a **name**, not a number — `home`, `volumeup`, `volumedown`, and the remote-control buttons on tvOS. The set is short and closed because it describes the physical buttons on the device chassis, and a chassis button has no modifier state and no separate long-press event to flag. XCUITest also declares `mobile: keys`, which sends a sequence of keys to whatever the application currently has focused. That is the method for keyboard keys — Enter, Tab, Escape — as opposed to buttons on the case. Appium 3's migration guide makes the split explicit: it points the old `POST /appium/device/press_keycode` route at `mobile: pressKey` on Android and at `mobile: keys` on iPadOS. ## The two side by side | | Android (UiAutomator2) | Apple platforms (XCUITest) | |---|---|---| | Method | `mobile: pressKey` | `mobile: pressButton` | | Key identified by | numeric `KeyEvent` keycode | button name such as `volumeup` | | Modifiers | `metastate` bitmask | none on this method | | Long press | `isLongPress` flag | none on this method | | Keyboard keys | same method, different keycode | separate method, `mobile: keys` | Every row of that table is a place a cross-platform helper has to branch rather than translate. ## How the call reaches the driver Both are `mobile:` execute methods, which is Appium's general mechanism for anything outside the W3C WebDriver command set. The client posts to `POST /session/:sessionId/execute/sync` with the method name as the script and exactly one parameter map as the argument; a language client such as java-client wraps that in `executeScript("mobile: pressKey", Map.of(...))` and adds nothing of its own. Three consequences follow: 1. The method belongs to the **driver**, not to the Appium server, so it exists only in a session whose `appium:automationName` selected that driver. 2. Sending `mobile: pressButton` to a UiAutomator2 session, or `mobile: pressKey` to an XCUITest session, fails as an unknown method — there is no fallback and no translation. 3. Neither call takes an element parameter, so neither can be scoped to a view of the kayak-rental app. ## The attribution trap `mobile: pressKey` is not *Appium's* key command — it is the **UiAutomator2 driver's**, and naming it without the driver is the mistake that makes an answer sound right and be wrong. The same holds for `mobile: pressButton` on the XCUITest side. Mobile interviewers notice, because a candidate who names the driver has read a driver's own documentation rather than a post that flattened both platforms into one API. ## What a suite does with this - Branch on `platformName` at the point of the call, and keep the branch visible rather than buried in a helper that silently does nothing on one platform. - Do not build a translation table that maps a keycode onto a button name as though the two were the same alphabet; only a handful of keys exist on both sides at all. - Remember that some keys have no counterpart in either direction: Android's back key has no Apple chassis equivalent, and Apple's key-sequence method has no single Android twin.
- Where does either of those hardware-key calls actually go over HTTP?Both are `mobile:` execute methods, so the client posts them to `POST /session/:sessionId/execute/sync` with the method name as the script and a single parameter map as the argument. Appium 3's migration guide points the old `POST /appium/device/press_keycode` route at `mobile: pressKey` on Android and at XCUITest's `mobile: keys` on iPadOS.
- If a kayak-rental test needs a keyboard key rather than a chassis button on an Apple platform, what does XCUITest offer?`mobile: keys`, which sends a sequence of keys to whatever the application currently has focused. `mobile: pressButton` is for the physical buttons on the device case and its accepted names are a closed list, so Enter or Tab is simply not in its vocabulary.
saying these in an interview costs you the question
- Claiming one Appium call presses hardware keys on both platforms
- Passing a numeric keycode to the Apple driver's button method
- Passing a button name such as volumeup to the Android key method
- Believing Appium translates Android keycodes into Apple button names
- Assuming the press targets a located element rather than the device
- Naming the method without naming the driver that declares it