Используйте следующие функции для добавления поддержки игрового контроллера в вашу игру с помощью библиотеки игровых контроллеров.
Инициализируйте и удалите библиотеку игрового контроллера
 Используйте функцию Paddleboat_init для инициализации библиотеки игрового контроллера.
Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)
 Paddleboat_init принимает два параметра:
-  Указатель на 
JNIEnv, прикрепленный к текущему потоку -  Ссылка на объект JNI 
jobject, производный отContext. Допустим любой объект производного отContextкласса, включая, помимо прочего,Activity,NativeActivityиGameActivity. 
 Paddleboat_init возвращает PADDLEBOAT_NO_ERROR , если инициализация прошла успешно, в противном случае возвращается соответствующий код ошибки.
 Для проверки успешности инициализации библиотеки игрового контроллера можно использовать Paddleboat_isInitialized . Функция возвращает логическое значение. Если значение равно true, API доступен для использования.
bool Paddleboat_isInitialized()
 Перед завершением работы приложения используйте функцию Paddleboat_destroy для завершения работы библиотеки игрового контроллера. Функция принимает один параметр — указатель на JNIEnv , присоединённый к текущему потоку. Paddleboat_init можно вызвать повторно после Paddleboat_destroy .
void Paddleboat_destroy(JNIEnv *env)
Информировать библиотеку о событиях жизненного цикла
 Библиотека игровых контроллеров должна быть проинформирована о событиях onStop и onStart жизненного цикла активности . Вызывайте функции Paddleboat_onStop и Paddleboat_onStart из кода обработки событий остановки и запуска. Обе функции принимают один параметр: указатель на JNIEnv , присоединённый к текущему потоку.
void Paddleboat_onStop(JNIEnv *env)
void Paddleboat_onStart(JNIEnv *env)
Регистрация или удаление обратного вызова статуса контроллера
Библиотека игровых контроллеров использует функцию обратного вызова статуса контроллера для уведомления игры о его подключении или отключении. Она поддерживает только одну функцию обратного вызова статуса контроллера одновременно.
-  Чтобы зарегистрировать обратный вызов состояния контроллера или заменить любой ранее зарегистрированный обратный вызов новой функцией обратного вызова, вызовите функцию 
Paddleboat_setControllerStatusCallback. -  Чтобы удалить любой зарегистрированный обратный вызов, передайте 
NULLилиnullptr. -  Параметр 
userData— это необязательный указатель на пользовательские данные. ПараметрuserDataбудет передан функции обратного вызова. Этот указатель сохраняется внутри системы до тех пор, пока не будет изменён последующим вызовомPaddleboat_setControllerStatusCallback. 
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)
Сигнатура функции обратного вызова:
typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
| Параметр | Описание | 
|---|---|
 controllerIndex |  Индекс контроллера, инициировавшего обратный вызов. Будет иметь значение от 0 доPADDLEBOAT_MAX_CONTROLLERS - 1 | 
 controllerStatus |  Значение перечисления PADDLEBOAT_CONTROLLER_JUST_CONNECTED илиPADDLEBOAT_CONTROLLER_JUST_DISCONNECTED . | 
 userData |  Необязательный указатель (может быть NULL) на определяемые пользователем данные, указанные в последнем вызове Paddleboat_setControllerStatusCallback . | 
Вызов функции обновления библиотеки игрового контроллера
 Функцию обновления библиотеки игровых контроллеров Paddleboat_update следует вызывать один раз за каждый игровой кадр, желательно в начале кадра. Функция принимает один параметр — указатель на JNIEnv , присоединённый к текущему потоку.
void Paddleboat_update(JNIEnv *env)
События процесса
При получении событий ввода ваша игра должна пересылать их в библиотеку игровых контроллеров для проверки. Библиотека игровых контроллеров проверяет, связано ли событие ввода с одним из управляемых устройств. События от управляемых устройств обрабатываются и используются.
 Библиотека игровых контроллеров поддерживает два типа событий ввода: события ввода AInputEvents и события ввода GameActivity .
Обработка событий ввода
 Ваша игра должна пересылать AInputEvents путем вызова Paddleboat_processInputEvent из кода обработки событий.
int32_t Paddleboat_processInputEvent(const AInputEvent *event)
 Paddleboat_processInputEvent вернет 0 если событие было проигнорировано, и 1 , если событие было обработано и использовано библиотекой игрового контроллера.
Обработка событий GameActivity
 Если ваша игра использует GameActivity , пересылайте события GameActivityKeyEvent и GameActivityMotionEvent , вызывая Paddleboat_processGameActivityKeyInputEvent или Paddleboat_processGameActivityMotionInputEvent из кода обработки событий.
int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
| Параметр | Описание | 
|---|---|
 event |  Указатель на структуру GameActivityKeyEvent или GameActivityMotionEvent , в зависимости от того, какая функция вызывается. | 
 eventSize |  Размер в байтах структуры события, переданной в параметре event . | 
 Обе функции вернут 0 если событие было проигнорировано, и 1 если событие было обработано и использовано библиотекой игрового контроллера.
 Для GameActivity необходимо указать активную ось движения с помощью функции GameActivityPointerAxes_enableAxis . Вызов Paddleboat_getActiveAxisMask возвращает битовую маску текущей активной оси движения, используемой подключенными контроллерами. 
uint64_t Paddleboat_getActiveAxisMask()
Пример решения этой проблемы можно найти в примере библиотеки Game Controller, использующей GameActivity . Этот пример опрашивает маску активной оси и сообщает GameActivity об использовании новой оси. Это реализовано в функции NativeEngine::CheckForNewAxis() . 
void NativeEngine::CheckForNewAxis() {
    // Tell GameActivity about any new axis ids so it reports
    // their events
    const uint64_t activeAxisIds = Paddleboat_getActiveAxisMask();
    uint64_t newAxisIds = activeAxisIds ^ mActiveAxisIds;
    if (newAxisIds != 0) {
        mActiveAxisIds = activeAxisIds;
        int32_t currentAxisId = 0;
        while(newAxisIds != 0) {
            if ((newAxisIds & 1) != 0) {
                LOGD("Enable Axis: %d", currentAxisId);
                GameActivityPointerAxes_enableAxis(currentAxisId);
            }
            ++currentAxisId;
            newAxisIds >>= 1;
        }
    }
}
Контроллеры чтения
 Библиотека игровых контроллеров использует индексное значение для ссылки на конкретный контроллер. Допустимые значения индекса находятся в диапазоне от 0 до PADDLEBOAT_MAX_CONTROLLERS - 1 Функция Paddleboat_getControllerStatus определяет статус указанного индекса контроллера. 
Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)
Существует три функции считывания информации с подключенного контроллера.
-  Функция 
Paddleboat_getControllerNameизвлекает имя устройства контроллера. -  Функция 
Paddleboat_getControllerInfoизвлекает данные о самом устройстве контроллера. -  Функция 
Paddleboat_getControllerDataизвлекает текущее состояние входов контроллера. 
Имя контроллера
 Paddleboat_getControllerName function принимает два входных параметра: индекс контроллера, размер буфера и указатель на буфер для хранения строки имени контроллера. Строка имени форматируется как строка C в кодировке UTF-8. Имя устройства получается внутренним методом InputDevice.getName() .
 Если Paddleboat_getControllerName успешно извлекает имя, он возвращает PADDLEBOAT_NO_ERROR , в противном случае возвращается соответствующий код ошибки. 
Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
| Параметр | Описание | 
|---|---|
 controllerIndex |  Индекс контроллера, инициировавшего обратный вызов. Будет иметь значение от 0 доPADDLEBOAT_MAX_CONTROLLERS - 1 | 
 bufferSize |  Размер буфера в байтах, переданного controllerName , строка имени будет усечена при необходимости, чтобы поместиться в буфер. | 
 controllerName |  Указатель на буфер размером bufferSize байт для сохранения имени контроллера. Имя будет сохранено как строка C с использованием кодировки UTF-8.  | 
Информация об устройстве контроллера
 Paddleboat_getControllerInfo function принимает два входных параметра: индекс контроллера и указатель на структуру Paddleboat_Controller_Info .
 Если Paddleboat_Controller_Info был успешно заполнен данными, Paddleboat_getControllerInfo возвращает PADDLEBOAT_NO_ERROR , в противном случае возвращается соответствующий код ошибки. 
Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)
Структура Paddleboat_Controller_Info содержит специфичную для устройства информацию о контроллере. 
typedef struct Paddleboat_Controller_Info {
    uint32_t controllerFlags;
    int32_t controllerNumber;
    int32_t vendorId;
    int32_t productId;
    int32_t deviceId;
    Paddleboat_Controller_Thumbstick_Precision leftStickPrecision;
    Paddleboat_Controller_Thumbstick_Precision rightStickPrecision;
} Paddleboat_Controller_Info;
typedef struct Paddleboat_Controller_Thumbstick_Precision {
    float stickFlatX;
    float stickFlatY;
    float stickFuzzX;
    float stickFuzzY;
} Paddleboat_Controller_Thumbstick_Precision;
Несколько членов структуры заполняются значениями, взятыми из InputDevice , связанного с контроллером: 
controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
- Значение 
stickFlatопределяет величину положения центральной плоскости. Это значение в основном полезно для расчета центральной «мёртвой зоны» по умолчанию на самоцентрирующихся устройствах. -  Значение 
stickFuzzотображает допустимую погрешность или то, насколько текущее значение может отклоняться от фактического значения из-за шума и ограничений чувствительности устройства. 
 Оба значения нормализованы к максимальному значению оси 1.0 в каждом измерении.
 Член controllerFlags содержит комбинацию отдельных флагов с битовыми масками и комбинаций многобитовых значений.
 Выполнение логической операции AND между controllerFlags и PADDLEBOAT_CONTROLLER_LAYOUT_MASK приводит к получению значения, которое может быть преобразовано в перечисление Paddleboat_ControllerButtonLayout . Это перечисление определяет иконографию и расположение кнопок, используемых контроллером. 
enum Paddleboat_ControllerButtonLayout {
    //  Y
    // X B
    //  A
    PADDLEBOAT_CONTROLLER_LAYOUT_STANDARD = 0,
    //  △
    // □ ○
    //  x
    PADDLEBOAT_CONTROLLER_LAYOUT_SHAPES = 1,
    //  X
    // Y A
    //  B
    PADDLEBOAT_CONTROLLER_LAYOUT_REVERSE = 2,
    // X Y R1 L1
    // A B R2 L2
    PADDLEBOAT_CONTROLLER_LAYOUT_ARCADE_STICK = 3,
    PADDLEBOAT_CONTROLLER_LAYOUT_MASK = 3
};
Следующие константы определяют биты возможностей. Чтобы определить, поддерживает ли контроллер конкретную возможность, выполните логическую операцию AND соответствующей константы с controllerFlags . Результат, отличный от нуля, означает, что эта возможность поддерживается контроллером.
 PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD
 Если этот флаг установлен, контроллер имеет встроенную сенсорную панель. При нажатии на сенсорную панель контроллер устанавливает бит PADDLEBOAT_BUTTON_TOUCHPAD в поле Paddleboat_Controller_Data.buttonsDown .
 PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE
 Если этот флаг установлен, контроллер эмулирует указательное устройство. Член virtualPointer структуры Paddleboat_Controller_Data заполняется текущими координатами виртуального указателя.
Данные контроллера
 Функция Paddleboat_getControllerData принимает два входных параметра: индекс контроллера и указатель на структуру Paddleboat_Controller_Data . Если Paddleboat_Controller_Data успешно заполнена данными, Paddleboat_getControllerInfo возвращает PADDLEBOAT_NO_ERROR , в противном случае возвращается соответствующий код ошибки. 
Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)
Структура Paddleboat_Controller_Data содержит текущие значения входных управляющих сигналов контроллера. 
typedef struct Paddleboat_Controller_Data {
    uint64_t timestamp;
    uint32_t buttonsDown;
    Paddleboat_Controller_Thumbstick leftStick;
    Paddleboat_Controller_Thumbstick rightStick;
    float triggerL1;
    float triggerL2;
    float triggerR1;
    float triggerR2;
    Paddleboat_Controller_Pointer virtualPointer;
} Paddleboat_Controller_Data;
typedef struct Paddleboat_Controller_Pointer {
    float pointerX;
    float pointerY;
} Paddleboat_Controller_Pointer;
typedef struct Paddleboat_Controller_Thumbstick {
    float stickX;
    float stickY;
} Paddleboat_Controller_Thumbstick;
Диапазоны значений
| Тип ввода | Диапазон значений | 
|---|---|
| Ось джойстика |  -1.0 до 1.0 | 
| Триггеры |  0.0 до 1.0 | 
| Виртуальные указатели |  0.0 — ширина/высота окна (в пикселях) | 
Детали структуры
| Член структуры | Описание | 
|---|---|
 buttonsDown |  Массив битовых полей для каждой кнопки. Константы битовых масок кнопок определены в заголовочном файле paddleboat.h и начинаются с PADDLEBOAT_BUTTON_ . | 
 timestamp. | Временная метка последнего события ввода контроллера. Временная метка указывается в микросекундах с начала отсчёта времени. | 
 virtualPointer |  Местоположение виртуального указателя. Действительно только в том случае, если в controllerFlags установлен флаг PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE , в противном случае — 0.0, 0.0 . |