public List<Joystick> loadJoysticks(int joyId, InputManager inputManager) {
        logger.log(Level.INFO, "loading Joystick devices");
        ArrayList<Joystick> joysticks = new ArrayList<>();
        joysticks.clear();
        joystickIndex.clear();

        ArrayList<Integer> gameControllerDeviceIds = new ArrayList<>();
        int[] deviceIds = InputDevice.getDeviceIds();
        for (int deviceId : deviceIds) {
            InputDevice dev = InputDevice.getDevice(deviceId);
            int sources = dev.getSources();
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, "deviceId[{0}] sources: {1}", new Object[]{deviceId, sources});
            }

            // Verify that the device has gamepad buttons, control sticks, or both.
            if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
                    ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
                // This device is a game controller. Store its device ID.
                if (!gameControllerDeviceIds.contains(deviceId)) {
                    gameControllerDeviceIds.add(deviceId);
                    logger.log(Level.FINE, "Attempting to create joystick for device: {0}", dev);
                    // Create an AndroidJoystick and store the InputDevice, so we
                    // can later convert the input from the InputDevice to the
                    // appropriate jME Joystick event.
                    AndroidJoystick joystick = new AndroidJoystick(inputManager,
                                                                joyInput,
                                                                dev,
                                                                joyId+joysticks.size(),
                                                                dev.getName());
                    joystickIndex.put(deviceId, joystick);
                    joysticks.add(joystick);

                    // Each analog input is reported as a MotionRange
                    // The axis number corresponds to the type of axis
                    // The AndroidJoystick.addAxis(MotionRange) converts the axis
                    // type reported by Android into the jME Joystick axis
                    List<MotionRange> motionRanges = dev.getMotionRanges();
                    for (MotionRange motionRange: motionRanges) {
                        if (logger.isLoggable(Level.INFO)) {
                            logger.log(Level.INFO, "motion range: {0}", motionRange);
                            logger.log(Level.INFO, "axis: {0}", motionRange.getAxis());
                        }
                        JoystickAxis axis = joystick.addAxis(motionRange);
                        if (logger.isLoggable(Level.INFO)) {
                            logger.log(Level.INFO, "added axis: {0}", axis);
                        }
                    }

                    // InputDevice has a method for determining if a keyCode is
                    // supported (InputDevice  public boolean[] hasKeys (int... keys)).
                    // But this method wasn't added until rev 19 (Android 4.4)
                    // Therefore, we only can query the entire device and see if
                    // any InputDevice supports the keyCode.  This may result in
                    // buttons being configured that don't exist on the specific
                    // device, but I haven't found a better way yet.
                    for (int keyCode: AndroidGamepadButtons) {
                        if (logger.isLoggable(Level.INFO)) {
                            logger.log(Level.INFO, "button[{0}]: {1}",
                                    new Object[]{keyCode, KeyCharacterMap.deviceHasKey(keyCode)});
                        }
                        if (KeyCharacterMap.deviceHasKey(keyCode)) {
                            // add button even though we aren't sure if the button
                            // actually exists on this InputDevice
                            logger.log(Level.INFO, "button[{0}] exists somewhere", keyCode);
                            JoystickButton button = joystick.addButton(keyCode);
                            logger.log(Level.INFO, "added button: {0}", button);
                        }
                    }

                }
            }
        }

        return joysticks;
    }
Main class that creates and manages Android inputs for physical gamepads/joysticks.

@author iwgeric
jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java