Get started with the Input SDK

This topic describes how to set up and display the Input SDK overlay in games that support Google Play Games. The tasks including adding the SDK to your game and generating an input map, which contains the game action to user input assignments. For games that support key binding changes, you must also track and synchronize the changes with the SDK.

Before you get started

Before you add the Input SDK to your game, you must add keyboard and mouse support.

Add the SDK

Get the Input SDK for Java or Kotlin by adding a dependency to your module level build.gradle file (this will likely be in your app directory):

dependencies {
  implementation 'com.google.android.libraries.play.games:inputmapping:1.0.0-beta'
  ...
}

The Input SDK for Unity is available for download in here.

Generate input mapping

Input mapping represents game actions to user input assignments to display in the Input SDK overlay. To generate input mapping, you must build an InputMap and then return it with an InputMappingProvider.

Here's an example outline of an InputMappingProvider:

Kotlin

class MyInputMapProvider : InputMappingProvider {
    override fun onProvideInputMap(): InputMap {
        TODO("Not yet implemented")
    }
}

Java

public class MyInputMapProvider implements InputMappingProvider {
    @NonNull
    @Override
    public InputMap onProvideInputMap() {
        // TODO: return an InputMap
    }
}

C#

private class MyInputMappingProvider : PlayInputMappingProvider
{
    public PlayInputMap OnProvideInputMap()
    {
        // TODO("Not yet implemented")
    }
}

The next sections describe how to create an InputMap to return from your InputMappingProvider.

Define an input action

The InputAction class is used to map a key or key combination to a game action.

This example maps the space key to the jump action:

Kotlin

val jumpInputAction = InputAction.create(
    "Jump",
    InputEventIds.JUMP.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SPACE),
        emptyList()
    )
)

Java

InputAction jumpInputAction = InputAction.create(
        "Jump",
        InputEventIds.JUMP.ordinal(),
        InputControls.create(
                Collections.singletonList(KeyEvent.KEYCODE_SPACE),
                Collections.emptyList()
        )
);

C#

var jumpInputAction = PlayInputAction.Create(
    "Jump",
    (int)InputEventIds.Jump,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SPACE
        },
        null
    )
);

Screenshot of the input overlay that indicates the jump action is bound to the
Space key.

Actions can represent mouse inputs as well. This example sets right click to the move action:

Kotlin

val cmbMove = InputAction.create(
    "Move",
    InputEventIds.CMB_MOVE.id,
    InputControls.create(
        emptyList(),
        listOf(InputControls.MOUSE_RIGHT_CLICK)
    )
)

Java

InputAction cmbMove = InputAction.create(
        "Move",
        InputEventIds.CMB_MOVE.ordinal(),
        InputControls.create(
                Collections.emptyList(),
                Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
        )
);

C#

var cmbMove = PlayInputAction.Create(
    "Move",
    (int)InputEventIds.CmbMove,
    PlayInputControls.Create(
        null,
        new[]
        {
            PlayMouseAction.MouseRightClick
        }
    )
);

Screenshot of the input overlay where the move action is bound to
right-click.

Key combinations are specified by passing multiple key codes to your InputAction. In this example, Space+Shift is mapped to the dash action, which works even when the Space key is mapped to jump.

Kotlin

val cmbDash = InputAction.create(
    "Dash",
    InputEventIds.CMB_DASH.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_SHIFT_LEFT),
        emptyList()
    )
)

Java

InputAction cmbDash = InputAction.create(
        "Dash",
        InputEventIds.CMB_DASH.ordinal(),
        InputControls.create(
                Arrays.asList(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE),
                Collections.emptyList()
        )
);

C#

var cmbDash = PlayInputAction.Create(
    "Dash",
    (int)InputEventIds.CmbDash,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SPACE, AndroidKeyCode.KEYCODE_SHIFT_LEFT
        }, null
    )
);

Screenshot from the input overlay where Shift+Space is bound to
the dash action.

The Input SDK lets you mix mouse and key buttons together for a single command. This example indicates that shift and right-click pressed together adds a waypoint in this game:

Kotlin

val cmbWaypoint = InputAction.create(
    "Add Waypoint",
    InputEventIds.CMB_WAYPOINT.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SHIFT_LEFT),
        listOf(InputControls.MOUSE_RIGHT_CLICK)
    )
)

Java

InputAction cmbWaypoint = InputAction.create(
        "Add Waypoint",
        InputEventIds.CMB_WAYPOINT.ordinal(),
        InputControls.create(
                Collections.singletonList(KeyEvent.KEYCODE_SHIFT_LEFT),
                Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
        )
);

C#

var cmbWaypoint = PlayInputAction.Create(
    "Add Waypoint",
    (int)InputEventIds.CmbWaypoint,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SHIFT_LEFT
        },
        new[]
        {
            PlayMouseAction.MouseRightClick
        }
    )
);

Screenshot of the input overlay where the Add Waypoint action is bound to
Shift+right-click.

This section describes the methods called in the code example:

Kotlin

InputAction.create has these parameters:

  • actionLabel is the string displayed in the UI to represent this action. Localization is not done for you, so it’s up to you to perform any localization up front.
  • uniqueId is an integer id to identify this action. Each action must have a consistent unique identifier, so an enumeration is used in this sample. See Tracking Key IDs for more information.
  • inputControls defines the input controls that the action uses. These will map to consistent glyphs in the user interface.

InputControls.create creates the inputs associated with an action. The parameters are:

  • keycodes is a list of integers representing keyboard inputs associated with an action. These are defined in the KeyEvent class.
  • mouseActions is a list of integers representing mouse inputs associated with the action. These are defined in InputControls itself.

Java

InputAction.create has these parameters:

  • actionLabel is the string displayed in the UI to represent this action. Localization is not done for you, so it’s up to you to perform any localization up front.
  • uniqueId is an integer id to identify this action. Each action must have a consistent unique identifier, so an enumeration is used in this sample. See Tracking Key IDs for more information.
  • inputControls defines the input controls that the action uses. These will map to consistent glyphs in the user interface.

InputControls.create creates the inputs associated with an action. The parameters are:

  • keycodes is a list of integers representing keyboard inputs associated with an action. These are defined in the KeyEvent class.
  • mouseActions is a list of integers representing mouse inputs associated with this action. These are defined in InputControls itself.

C#

InputAction has these fields:

  • ActionLabel is the string displayed in the UI to represent this action. Localization is not done for you, so it’s up to you to perform any localization up front.
  • UniqueId is an integer id to identify this action. Each action must have a consistent unique identifier, so an enum is used in this sample. See Tracking Key IDs.
  • InputControls defines the input controls that this action uses. These will map to consistent glyphs in the user interface.

InputControls represents the inputs associated with an action. it has these fields:

  • AndroidKeycodes is a list of integers representing keyboard inputs associated with an action. These are defined in the AndroidKeycode class.
  • MouseActions is a list of MouseAction values representing mouse inputs associated with this action.

Define an input group

An InputGroup is a group of similar InputAction objects. For example:

  • You may specify different sets of inputs for navigating menus vs moving in game.
  • You may specify different sets inputs depending on the mode of locomotion in your game, such as driving vs walking.
  • You may specify different sets of inputs based on the current state of your game, such as navigating an overworld vs playing an individual level.

By organizing your inputs into groups, you make it easier for a player to find the correct key binding for their current situation.

Kotlin

val movementInputGroup = InputGroup.create(
    "Basic Movement",
    listOf(jumpInputAction, leftInputAction, rightInputAction, useInputAction)
)

Java

InputGroup movementInputGroup = InputGroup.create(
        "Basic Movement",
        Arrays.asList(jumpInputAction, leftInputAction, rightInputAction, useInputAction)
);

C#

var movementInputGroup = PlayInputGroup.Create(
    "Basic Movement",
    new[]
    {
        jumpInputAction, leftInputAction, rightInputAction, useInputAction
    }
);

This section describes the method calls used in the code example:

Kotlin

InputGroup.create has these parameters:

  • groupLabel is a string to be displayed in the UI that can be used to logically group a set of actions. This string is not localized for you.
  • inputActions is a list of InputAction objects that you defined in the last step. All of these actions will be visually displayed under this group’s heading.

Java

InputGroup.create has these parameters:

  • groupLabel is a string to be displayed in the UI that can be used to logically group a set of actions. This string is not localized for you.
  • inputActions is a list of InputAction objects that you defined in the last step. All of these actions will be visually displayed under this group’s heading.

C#

InputGroup has these fields:

  • GroupLabel is a string to be displayed in the UI that can be used to logically group a set of actions. This string is not localized for you.
  • InputActions is a list of InputAction objects that you defined in the last step. All of these actions will be visually displayed under this group’s heading.

Build an input map

An InputMap is a collection of all the InputGroup objects available in a game, and therefore all of the InputAction objects a player can expect to perform.

In the following example, MovementInputGroup objects are grouped with MouseSettings objects. The MouseSettings objects indicate that mouse sensitivity can be adjusted and that the mouse is inverted on the y axis:

Kotlin

return InputMap.create(
    listOf(movementInputGroup, specialInputGroup),
    MouseSettings.create(true, true)
)

Java

return InputMap.create(
        Arrays.asList(movementInputGroup, specialInputGroup),
        MouseSettings.create(true, true)
);

C#

return PlayInputMap.Create(
    new[]
    {
        movementInputGroup, specialInputGroup, combinationInputGroup
    },
    PlayMouseSettings.Create(true, false)
);

Submit an input map

Once an InputMapProvider has been been written for a game that returns a valid InputMap, it must be registered with the Input SDK. If a game's inputs never change, this only has to be done once for the lifetime of a game as the InputMapProvider is not affected by Android lifecycle events.

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val inputMappingClient = Input.getInputMappingClient(this)
    inputMappingClient.setInputMappingProvider(MyInputMapProvider())
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
    inputMappingClient.setInputMappingProvider(new MyInputMapProvider());
}

C#

void Start()
{
    _inputMappingProvider = new MyInputMappingProvider();
    PlayInput.GetInputMappingClient().SetInputMappingProvider(_inputMappingProvider);
}

You should unregister your input mapping provider when your game is finished, although the SDK is smart enough to avoid leaking resources if you don't.

Kotlin

override fun onDestroy() {
    val inputMappingClient = Input.getInputMappingClient(this)
    inputMappingClient.clearInputMappingProvider()

    super.onDestroy()
}

Java

@Override
protected void onDestroy() {
    InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
    inputMappingClient.clearInputMappingProvider();

    super.onDestroy();
}

C#

private void OnDestroy()
{
    PlayInput.GetInputMappingClient().ClearInputMappingProvider();
}

Track key IDs

You need to track unique IDs for each InputAction you define. The following enumeration tracks the unique IDs for all the samples in this topic. Since the IDs are used to track key changes, do not use a hash of the localized action name.

Kotlin

enum class InputEventIds(val id: Int) {
    JUMP(0),
    LEFT(1),
    RIGHT(2),
    USE(3),
    SPECIAL_JUMP(4),
    SPECIAL_DUCK(5),
}

Java

public enum InputEventIds {
    JUMP,
    LEFT,
    RIGHT,
    USE,
    SPECIAL_JUMP,
    SPECIAL_DUCK
}

C#

public enum InputEventIds
{
    JUMP,
    LEFT,
    RIGHT,
    USE,
    SPECIAL_JUMP,
    SPECIAL_DUCK
}

Test

There are two ways to test whether the Input SDK has been properly implemented. Either by opening it in the Google Play Games UI to see what a player may see or in the adb shell for automated testing and verification.

User interface

To test in the Google Play Games UI, press Shift+Tab to open the Game Dashboard. Fromm the dashboard, click Controls to view the list of currently bound controls.

An image illustrating the flow described above. Shift+Tab opens the Game Dashboard. Then clicking on

Command line

Inputs can also be verified via adb at the command line, which may help with automated testing of the feature.

To get the current input map, use the following adb shell command (replace MY.PACKAGE.NAME with the name of your game):

adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME

You will see output similar to this if you successfully registered your InputMap:

Getting input map for com.example.inputsample...
Successfully received the following inputmap:
# com.google.android.libraries.play.games.InputMap@d73526e1
input_groups {
  group_label: "Basic Movement"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
    }
    unique_id: 0
  }
  input_actions {
    action_label: "Left"
    input_controls {
      keycodes: 29
      keycodes: 21
    }
    unique_id: 1
  }
  input_actions {
    action_label: "Right"
    input_controls {
      keycodes: 32
      keycodes: 22
    }
    unique_id: 2
  }
  input_actions {
    action_label: "Use"
    input_controls {
      keycodes: 33
      keycodes: 66
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 3
  }
}
input_groups {
  group_label: "Special Input"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
      keycodes: 62
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 4
  }
  input_actions {
    action_label: "Duck"
    input_controls {
      keycodes: 47
      keycodes: 20
      keycodes: 113
      mouse_actions: MOUSE_RIGHT_CLICK
      mouse_actions_value: 1
    }
    unique_id: 5
  }
}
mouse_settings {
  allow_mouse_sensitivity_adjustment: true
  invert_mouse_movement: true
}

Synchronize key binding changes

Many games allow players to customize their key bindings. Therefore, you should ensure that the data you return in InputMapProvider is up to date for the player's current settings. If needed, you can safely call setInputMappingProvider with the latest input map whenever your players finish changing their input scheme.

Localization

The Input SDK does not use Android's localization system. As a result, you must provide localized strings when submitting an InputMap. However, this also allows you to use your game engine's localization system.

What's next

After you integrate the Input SDK into your game, you can continue with any remaining Google Play Games requirements. For more information, see Get started with Google Play Games.