Handle controller actions

At the system level, Android reports input event codes from game controllers
as Android key codes and axis values. In your game, you can receive these codes
and values and convert them to specific in-game actions.

When players physically connect or wirelessly pair a game controller to
their Android-powered devices, the system auto-detects the controller
as an input device and starts reporting its input events. Your game can receive
these input events by implementing the following callback methods in your active
Activity or focused View (you should
implement the callbacks for either the Activity or
View, but not both):

Called to process a release of a physical key such as a gamepad or
D-pad button.

The recommended approach is to capture the events from the
specific View object that the user interacts with.
Inspect the following objects provided by the callbacks to get information
about the type of input event received:

An object that describes directional
pad (D-pad) and gamepad button events. Key events are accompanied by a
key code that indicates the specific button triggered, such as
DPAD_DOWN
or BUTTON_A. You can obtain the
key code by calling getKeyCode() or from key
event callbacks such as
onKeyDown().

An object that describes input from joystick and shoulder trigger
movements. Motion events are accompanied by an action code and a set of
axis values. The action code specifies the state change that occurred
such as a joystick being moved. The axis values describe the position and other
movement properties for a specific physical control, such as
AXIS_X or
AXIS_RTRIGGER. You can obtain the action code
by calling getAction() and the axis value by
calling getAxisValue().

This lesson focuses on how you can handle input from the most common types of
physical controls (gamepad buttons, directional pads, and
joysticks) in a game screen by implementing the above-mentioned
View callback methods and processing
KeyEvent and MotionEvent objects.

Verify a game controller is connected

When reporting input events, Android does not distinguish
between events that came from a non-game controller device and events that came
from a game controller. For example, a touch screen action generates an
AXIS_X event that represents the X
coordinate of the touch surface, but a joystick generates an
AXIS_X event that represents the X position of the joystick. If
your game cares about handling game-controller input, you should first check
that the input event comes from a relevant source type.

To verify that a connected input device is a game controller, call
getSources() to obtain a combined bit field of
input source types supported on that device. You can then test to see if
the following fields are set:

A source type of SOURCE_GAMEPAD indicates
that the input device has gamepad buttons (for example,
BUTTON_A). Note that this source
type does not strictly indicate if the game controller has D-pad buttons,
although most gamepads typically have directional controls.

A source type of SOURCE_DPAD indicates that
the input device has D-pad buttons (for example,
DPAD_UP).

A source type of SOURCE_JOYSTICK
indicates that the input device has analog control sticks (for example, a
joystick that records movements along AXIS_X
and AXIS_Y).

The following code snippet shows a helper method that lets you check whether
the connected input devices are game controllers. If so, the method retrieves
the device IDs for the game controllers. You can then associate each device
ID with a player in your game, and process game actions for each connected
player separately. To learn more about supporting multiple game controllers
that are simultaneously connected on the same Android device, see
Support multiple game controllers.

Additionally, you might want to check for individual input capabilities
supported by a connected game controller. This might be useful, for example, if
you want your game to use only input from the set of physical controls it
understands.

To detect if a specific key code or axis code is supported by a connected
game controller, use these techniques:

In Android 4.4 (API level 19) or higher, you can determine if a key code is
supported on a connected game controller by calling
hasKeys(int...).

Common key codes generated by gamepad button presses include
BUTTON_A,
BUTTON_B,
BUTTON_SELECT,
and BUTTON_START. Some game
controllers also trigger the DPAD_CENTER key code when the center of the D-pad crossbar is pressed. Your
game can inspect the key code by calling getKeyCode()
or from key event callbacks such as
onKeyDown(),
and if it represents an event that is relevant to your game, process it as a
game action. Table 1 lists the recommended game actions for the most common
gamepad buttons.

Note: On Android 4.2 (API
level 17) and lower, the system treats
BUTTON_A as the Android
Back key by default. If your app supports these Android
versions, make sure to treat
BUTTON_A as the primary game
action. To determine the current Android SDK
version on the device, refer to the
Build.VERSION.SDK_INT value.

Process directional pad input

The 4-way directional pad (D-pad) is a common physical control in many game
controllers. Android reports D-pad UP and DOWN presses as
AXIS_HAT_Y events with a range
from -1.0 (up) to 1.0 (down), and D-pad LEFT or RIGHT presses as
AXIS_HAT_X events with a range from -1.0
(left) to 1.0 (right).

Some controllers instead report D-pad presses with a key code. If your game
cares about D-pad presses, you should treat the hat axis events and the D-pad
key codes as the same input events, as recommended in table 2.

Process joystick movements

When players move a joystick on their game controllers, Android reports a
MotionEvent that contains the
ACTION_MOVE action code and the updated
positions of the joystick's axes. Your game can use the data provided by
the MotionEvent to determine if a joystick movement it
cares about happened.

Note that joystick motion events may batch multiple movement samples together
within a single object. The MotionEvent object contains
the current position for each joystick axis as well as multiple historical
positions for each axis. When reporting motion events with action code ACTION_MOVE (such as joystick movements), Android batches up the
axis values for efficiency. The historical values for an axis consists of the
set of distinct values older than the current axis value, and more recent than
values reported in any previous motion events. See the
MotionEvent reference for details.

You can use the historical information to more accurately render a game
object's movement based on the joystick input. To
retrieve the current and historical values, call
getAxisValue() or getHistoricalAxisValue(). You can also find the number of historical
points in the joystick event by calling
getHistorySize().

The following snippet shows how you might override the
onGenericMotionEvent() callback to process joystick input. You should first
process the historical values for an axis, then process its current position.

Before using joystick input, you need to determine if the joystick is
centered, then calculate its axis movements accordingly. Joysticks typically
have a flat area, that is, a range of values near the (0,0) coordinate
at which the axis is considered to be centered. If the axis value reported by
Android falls within the flat area, you should treat the controller to be at
rest (that is, motionless along both axes).

The snippet below shows a helper method that calculates the movement along
each axis. You invoke this helper in the processJoystickInput() method
described further below.

To support game controllers that have more sophisticated
features beyond a single joystick, follow these best practices:

Handle dual controller sticks. Many game controllers have
both a left and right joystick. For the left stick, Android
reports horizontal movements as AXIS_X events
and vertical movements as AXIS_Y events.
For the right stick, Android reports horizontal movements as
AXIS_Z events and vertical movements as
AXIS_RZ events. Make sure to handle
both controller sticks in your code.

Handle shoulder trigger presses (but provide alternative input
methods). Some controllers have left and right shoulder
triggers. If these triggers are present, Android reports a left trigger press
as an AXIS_LTRIGGER event and a
right trigger press as an
AXIS_RTRIGGER event. On Android
4.3 (API level 18), a controller that produces a
AXIS_LTRIGGER also reports an
identical value for the AXIS_BRAKE axis. The
same is true for AXIS_RTRIGGER and
AXIS_GAS. Android reports all analog trigger
presses with a normalized value from 0.0 (released) to 1.0 (fully pressed). Not
all controllers have triggers, so consider allowing players to perform those
game actions with other buttons.