skip to content

In Appium, why does Android's mobile: pressKey take a number where iOS pressButton takes a name?

level: middleimportance: should knowfreq 52%

answer

  1. open numbered space versus short named list
  2. modifiers only make sense on one side
  3. long press is its own Android event
  4. chassis buttons have no keycode

basics

~20 s

Android exposes the platform's whole KeyEvent space, so UiAutomator2's mobile: pressKey identifies a key by its integer constant. XCUITest's mobile: pressButton drives a short, fixed set of physical device buttons, which a name identifies exactly.

solid answer

~50 s

The two parameters describe two different populations. Android's key events are a large, open, numbered vocabulary — the platform's `KeyEvent` constants — and UiAutomator2's `mobile: pressKey` takes one of those integers, so anything the system can deliver as a key is reachable: `4` for back, `24` for volume up, `66` for enter. It also carries `metastate`, the modifier bitmask meaning the key was pressed with shift or control held, and `isLongPress`, because Android models a long press as its own kind of event rather than as a duration the caller times. XCUITest's `mobile: pressButton` addresses something much smaller: the buttons on the device chassis, such as `home`, `volumeup` and `volumedown`. There is no integer space to index into and no modifier bitmask, because a chassis button has no modifiers. For keyboard keys on an Apple platform you reach for `mobile: keys` instead.

go deeper

for a junior

Recall the shape of each parameter: a number on Android, a button name on Apple platforms. Do not try to hand one form to the other driver.

for a middle

Explain why the shapes differ — an open integer vocabulary covering every key the system can report, against a short list naming the buttons on the device case.

for a senior

Show judgment about which keycodes a suite hard-codes and how the numbers stay readable, because a bare integer in a step tells the next maintainer nothing.

for a principal

Decide whether the suite carries its own named constants over the Android integers at all, and who owns that list when a new key is needed.

## Two parameters, two different populations The shape of an API parameter usually tells you what it is addressing. Android's `mobile: pressKey` takes a **number** and Apple's `mobile: pressButton` takes a **name**, and that is not a stylistic difference between two teams — it is the two platforms describing two different things. When the kayak-rental app is on screen and a tester presses a key, Android has to answer the question *which of every key this device could possibly report?* Apple's chassis-button method has to answer a much narrower one: *which of the few buttons on the outside of this device?* An integer suits the first question and a name suits the second. ## The Android side is an open numbered space The UiAutomator2 driver's `mobile: pressKey` identifies a key by an integer drawn from the platform's `KeyEvent` constants. That single channel carries keys from many sources — the buttons on the case, an attached hardware keyboard, an input method, a game controller — and each key has a number. The parameter map is therefore: - `keycode` — the integer. `4` back, `24` volume up, `25` volume down, `61` tab, `66` enter. - `metastate` — an optional bitmask of modifiers held at the moment of the press. It is a property **of this press**, not a device mode you switch on beforehand. - `isLongPress` — an optional boolean. Android distinguishes a long key press from a short one at the event level, so you set a flag rather than timing two calls. The practical consequence of an open numeric space is reach: a key nobody anticipated is still addressable, provided the caller knows its number. The practical cost is readability — `driver.executeScript("mobile: pressKey", Map.of("keycode", 66))` says nothing to the next reader of the kayak-rental suite unless the number is behind a named constant. ## The Apple side is a short closed list XCUITest's `mobile: pressButton` takes a `name`, and the accepted names describe the physical buttons of the hardware: `home`, `volumeup`, `volumedown`, and the remote-control buttons when the target is tvOS. There is no numeric space behind it and nothing to index into. There is also: - **No modifier parameter.** A volume button cannot be pressed *with shift held*, so there is nothing for a `metastate` equivalent to express. - **No long-press flag.** The method exposes a press of a chassis button, not an event whose duration is part of its identity. - **A separate method for keyboard keys.** `mobile: keys` sends a sequence of keys to whatever the application currently has focused; Enter and Tab live there, not in the button vocabulary. ## Side by side | | Android, UiAutomator2 | Apple platforms, XCUITest | |---|---|---| | Method | `mobile: pressKey` | `mobile: pressButton` | | Key argument | integer `KeyEvent` keycode | name string such as `volumeup` | | Size of vocabulary | open — every key the system reports | closed — the buttons on the case | | Modifiers | `metastate` bitmask | not expressible on this method | | Long press | `isLongPress` flag | not expressible on this method | | Keyboard keys | another keycode on the same method | `mobile: keys`, a different method | ## Why the mismatch matters in practice The two parameter maps are not two spellings of one idea, and three things follow for a kayak-rental suite that runs on both: 1. **You cannot write a converter.** Only a handful of intents — volume up, volume down, home — exist on both sides at all, so a keycode-to-name table would be three rows long and would imply a generality that is not there. 2. **Two Android parameters have no Apple counterpart.** Anything a test expresses through `metastate` or `isLongPress` is Android-only content, and a shared helper that accepts those arguments is lying about the other platform. 3. **The Apple split is by target, not by key.** Choosing between `mobile: pressButton` and `mobile: keys` is a question about *what you are pressing* — the case, or the keyboard — and getting it wrong produces a call that succeeds quietly. ## Keeping the Android numbers honest A bare integer in a test step is the readability tax of the open vocabulary, and it is worth paying deliberately: - Give the numbers names in one place, so a step reads as volume up rather than as `24`. - Keep the modifier in the same call as the key it modifies; a separate press of a modifier key does not leave the device in a held state that the next call inherits. - Set `isLongPress` rather than issuing a press and waiting, because the flag is what makes the platform emit a long-press event at all. The summary an interviewer is listening for: the number is an address into everything Android can report as a key, the name is a label on one of a handful of physical buttons, and no amount of wrapper code makes them the same alphabet.

  • What does metastate carry, and why does the Apple button method have no equivalent?
    `metastate` is an Android modifier bitmask saying the key was pressed while shift, control or a similar modifier was held, and it travels on the same `mobile: pressKey` call as the key itself. XCUITest's `mobile: pressButton` presses a button on the device case, and a chassis button has no modifier state to express.
  • Why can the Android method reach far more keys than the Apple button method can?
    Because the Android parameter is an integer drawn from the platform's `KeyEvent` constants, so any key the system can report is addressable once you know its number. `mobile: pressButton` takes a name from a short, closed list describing the physical buttons on the device case, and there is no numeric space behind it.

Android's keycode is like an extension number: any handset in the building is reachable if you know the digits. Apple's button name is one of the few labelled buttons beside the front door — a short list, and the label is the whole address.

saying these in an interview costs you the question

  • Believing metastate is a duration rather than a modifier bitmask
  • Timing a long press by hand instead of setting isLongPress
  • Expecting the Apple button method to accept an arbitrary keycode
  • Assuming the two parameter maps are interchangeable across drivers
  • Treating volume buttons as keyboard keys on Apple platforms