Android Question Retrieving InputDevice Info

wonder

Expert
Licensed 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
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? :)
 

thedesolatesoul

Expert
Licensed 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:

wonder

Expert
Licensed 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 **
 

Cableguy

Expert
Licensed 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
 

wonder

Expert
Licensed 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 **
 

wonder

Expert
Licensed 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'
    'http://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
 
Top