Android Question Retrieving InputDevice Info

wonder

Expert
Licensed User
Longtime User
Hi [B]Erel[/B] and B4A/Java gurus,

Regarding my B4A Generic GamePad Support, I realized that I'm only able to retrieve my controller's device info after the OnGenericMotionEvent has fired.

Since the gamepad controller is already plugged-in and recognized by the Android OS before starting my app, how can I retrieve this info without the need of the event being fired?
B4X:
Sub Activity_OnGenericMotionEvent(event As Object)
        Controller.Input = event 'Controller.Input is a JavaObject
        If Controller.Device_Name = "" Then Controller.Device_Name = getDevice(False)
        If Controller.Device_Info = "" Then Controller.Device_Info = getDevice(True)
End Sub

B4X:
Sub getDevice(Full_Info As Boolean) As String
    Dim full_description = Controller.Input.RuNMethod("getDevice", Null) As String
    If full_description <> "null" Then
        If Full_Info = True Then
            Return full_description
        Else
            For i = 0 To (full_description.Length - 1)
                If full_description.SubString2(i, i + 2) = ": " Then
                    Dim device_name As String
                    For j = i + 2 To (full_description.Length - 1)
                        If full_description.SubString2(j, j + 11) = "Descriptor:" Then
                            Exit
                        Else
                            device_name = device_name & full_description.CharAt(j)
                        End If
                    Next
                End If
                If device_name <> "" Then Exit
            Next
            Return device_name
        End If
    Else
        Return "No controller detected."
    End If
End Sub
 

wonder

Expert
Licensed User
Longtime User
Thank you for you quick reply, @thedesolatesoul! I've been on that page before.
How can I access the InputDevice? Through a RunMethod? My experience with JavaObject / Reflector libs is piratically non-existent.

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.
B4X:
public ArrayList getGameControllerIds() {
    ArrayList gameControllerDeviceIds = new ArrayList();
    int[] deviceIds = InputDevice.getDeviceIds();
    for (int deviceId : deviceIds) {
        InputDevice dev = InputDevice.getDevice(deviceId);
        int sources = dev.getSources();

        // 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);
            }
        }
    }
    return gameControllerDeviceIds;
}

A little help, perhaps? :)
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
It is a Final class so i am guessing:
B4X:
Dim jo as JavaObject
jo.InitializeStatic("android.view.InputDevice")
Dim DeviceIds() as Int = jo.RunMethod("getDeviceIds", Null)
for i = 0 to DeviceIds.Length-1
  Dim joDevice as JavaObject = jo.RunMethodJO("getDevice", Array as Object(DeviceIds(i))) 'Or dont wrap as array??
  Dim sources as Int = joDevice.RunMethod("getSources",null)
  Log(sources)
  If Bit.And(sources, 1025) = 1025 Or Bit.And(sources, 16777232) = 16777232 Then
     Log("This is a Gamepad or Joystick")
     Dim Name as String = joDevice.RunMethod("getName"),null)
     Dim Descriptor as String = joDevice.RunMethod("getDescriptor"),null)
     Log("Name: " & Name & " Descriptor: " & Descriptor)
  End If
Next
but JO/Reflection really frustrates me, im not sure how to put stuff in an array.
 
Last edited:
Upvote 0

wonder

Expert
Licensed User
Longtime User
Awesome!! It works!! Thank you so much!! :D :D :D

Now... How can I get only the controller name?

For example, in my case, I have a PS3 Controller.
What I'm aiming for is upon starting the app, seeing the following message:
Sony PLAYSTATION(R)3 Controller detected.
Something like: Label1.Text = getDeviceName & " detected."

Output for Log(sources):
B4X:
Installing file.
PackageAdded: package:com.ninjadynamics.gamepad
** Activity (main) Create, isFirst = true **
769
769
4098
257
4098
16778513
This is a Gamepad or Joystick
** Activity (main) Resume **


Output for Log(joDevice):
B4X:
Installing file.
PackageAdded: package:com.ninjadynamics.gamepad
** Activity (main) Create, isFirst = true **
(InputDevice) Input Device -1: Virtual
  Descriptor: a718a782d34bc767f4689c232d64d527998ea7fd
  Generation: 2
  Location: built-in
  Keyboard Type: alphabetic
  Has Vibrator: false
  Sources: 0x301 ( keyboard dpad )
(InputDevice) Input Device 1: mtk-kpd
  Descriptor: 4c25a46f06f071ad0d152d0653af8ffc1dfa741d
  Generation: 8
  Location: built-in
  Keyboard Type: non-alphabetic
  Has Vibrator: false
  Sources: 0x301 ( keyboard dpad )
(InputDevice) Input Device 2: mtk-tpd
  Descriptor: 84931e976ab60191371c1c95baf408538ca4c4c5
  Generation: 13
  Location: built-in
  Keyboard Type: none
  Has Vibrator: false
  Sources: 0x1002 ( touchscreen )
    AXIS_X: source=0x1002 min=0.0 max=1279.0 flat=0.0 fuzz=0.99921936
    AXIS_Y: source=0x1002 min=0.0 max=799.0 flat=0.0 fuzz=0.9987516
    AXIS_PRESSURE: source=0x1002 min=0.0 max=1.0 flat=0.0 fuzz=0.0
    AXIS_SIZE: source=0x1002 min=0.0 max=1.0 flat=0.0 fuzz=0.0
    AXIS_TOUCH_MAJOR: source=0x1002 min=0.0 max=1509.437 flat=0.0 fuzz=0.0
    AXIS_TOUCH_MINOR: source=0x1002 min=0.0 max=1509.437 flat=0.0 fuzz=0.0
    AXIS_TOOL_MAJOR: source=0x1002 min=0.0 max=1509.437 flat=0.0 fuzz=0.0
    AXIS_TOOL_MINOR: source=0x1002 min=0.0 max=1509.437 flat=0.0 fuzz=0.0
(InputDevice) Input Device 4: ACCDET
  Descriptor: 1c78f7e0d16d4dbc8d3ab93943523f379203f90b
  Generation: 4
  Location: built-in
  Keyboard Type: non-alphabetic
  Has Vibrator: false
  Sources: 0x101 ( keyboard )
(InputDevice) Input Device 5: sixaxis_touchscreen
  Descriptor: 485d69228e24f5e46da1598745890b214130dbc4
  Generation: 15
  Location: built-in
  Keyboard Type: none
  Has Vibrator: false
  Sources: 0x1002 ( touchscreen )
    AXIS_X: source=0x1002 min=0.0 max=1279.0 flat=0.0 fuzz=0.31242374
    AXIS_Y: source=0x1002 min=0.0 max=799.0 flat=0.0 fuzz=0.19526483
    AXIS_PRESSURE: source=0x1002 min=0.0 max=1.0 flat=0.0 fuzz=0.0
(InputDevice) Input Device 23: Sony PLAYSTATION(R)3 Controller
  Descriptor: a604f897f8e4cc8e80cbc672b77a7a5b4e7c6b6d
  Generation: 68
  Location: external
  Keyboard Type: non-alphabetic
  Has Vibrator: false
  Sources: 0x1000511 ( keyboard joystick gamepad )
    AXIS_X: source=0x1000010 min=-1.0 max=1.0 flat=0.15686275 fuzz=0.015686275
    AXIS_Y: source=0x1000010 min=-1.0 max=1.0 flat=0.15686275 fuzz=0.015686275
    AXIS_Z: source=0x1000010 min=-1.0 max=1.0 flat=0.15686275 fuzz=0.015686275
    AXIS_RZ: source=0x1000010 min=-1.0 max=1.0 flat=0.15686275 fuzz=0.015686275
    AXIS_LTRIGGER: source=0x1000010 min=0.0 max=1.0 flat=0.078431375 fuzz=0.007843138
    AXIS_RTRIGGER: source=0x1000010 min=0.0 max=1.0 flat=0.078431375 fuzz=0.007843138
This is a Gamepad or Joystick
** Activity (main) Resume **
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
Since you are still on mono-player AND your controller is connect via Bluetooth, looking at those strings, I would go through the resulting array and filter the location... once "External" was detected, get the name from that array...
but this is me wild guessing
 
Upvote 0

wonder

Expert
Licensed User
Longtime User
AWESOME!!! Thank you so much!!! :D

B4X:
LogCat connected to: B4A-Bridge: asus ME173X-
--------- beginning of /dev/log/main
Installing file.
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
PackageAdded: package:com.ninjadynamics.gamepad
** Activity (main) Create, isFirst = true **
769
769
4098
257
4098
16778513
This is a Gamepad or Joystick
Name: Sony PLAYSTATION(R)3 Controller Descriptor: a604f897f8e4cc8e80cbc672b77a7a5b4e7c6b6d
** Activity (main) Resume **
 
Upvote 0

wonder

Expert
Licensed User
Longtime User
@thedesolatesoul

I've modified your code in order to detect multiple controllers.
The Generic GamePad Support project was updated as well.
B4X:
Sub getDeviceName(Index As Int, Descriptor As Boolean) As String
    'Original function code by 'thedesolatesoul'
    'https://www.b4x.com/android/forum/members/thedesolatesoul.11412/
    Dim jo As JavaObject
    jo.InitializeStatic("android.view.InputDevice")
    Dim DeviceIds() As Int = jo.RunMethod("getDeviceIds", Null)    
    Dim Name(DeviceIds.Length - 1) As String
    Dim Desc(DeviceIds.Length - 1) As String
    Dim Device_Index = 0 As Int
    For i = 0 To (DeviceIds.Length - 1)
        Dim joDevice As JavaObject = jo.RunMethodJO("getDevice", Array As Object(DeviceIds(i)))
        Dim sources As Int = joDevice.RunMethod("getSources", Null)
        Log(sources)
        If Bit.AND(sources, 1025) = 1025 OR Bit.AND(sources, 16777232) = 16777232 Then
            Name(Device_Index) = joDevice.RunMethod("getName", Null)
            Desc(Device_Index) = joDevice.RunMethod("getDescriptor" ,Null)
            Log("Device Index: " & Device_Index & CRLF & _
                "Name: " & Name(Device_Index) & CRLF & _
                "Descriptor: " & Desc(Device_Index))            
            Device_Index = Device_Index + 1
        End If
    Next
    If Name(Min(Index, Name.Length - 1)) <> "" Then
        If Descriptor = True Then
            Return Desc(Index)
        Else
            Return Name(Index)
        End If
    Else
        Log("No Gamepad or Joystick detected.")
        Return "No Gamepad or Joystick detected."
    End If
End Sub


Usage:
B4X:
Controller_0.Device_Name = getDeviceName(0, False) 'Get Player 1's Controller Name
Controller_1.Device_Name = getDeviceName(1, False) 'Get Player 2's Controller Name
 
Upvote 0
Top