19

In my Android app, I read the values from a 3DConnexion SpaceNavigator via USB-OTG to control an AR.Drone.

Now I want to do the same with a mouse. However, Android is grabbing the mouse and presenting a mouse-cursor. When I write a device-filter with the vendor and product ID of the mouse, I do not get it like with the SpaceNavigator (strangely, both are HID -- I get no cursor with the SpaceNavigator).

Is there a way to get the raw mouse data without the cursor?

Would be perfect with stock Android. but I would also consider altering the ROM for that.

Uttam Panchasara
5,8855 gold badges27 silver badges41 bronze badges
asked Nov 8, 2012 at 0:02
3
  • did you find any solution? I still couldnt Commented Jun 21, 2015 at 13:03
  • 1
    It seems to be impossible with stock Android. Here is a tutorial on how to replace the mouse cursor image, so you can replace it with a transparent .PNG. Commented Jun 26, 2015 at 6:59
  • I had the chance to test volzo's solution in an android 8 device and an android 9 device. Both with good results, it works ok. Commented Mar 21, 2019 at 8:04

1 Answer 1

3

As soon as your Application claims the Mouse (as a USB HID device while being Host), Android should hide the cursor and you can read the raw data. This should work on stock android, but your device has to support USB Host mode and a USB OTG cable will be needed to connect the mouse.

Basic procedure:

  • enumerate devices
  • ask for permission to access the USB device
  • claim the device
  • read a data package from the HID endpoint
  • parse the X and Y position, button clicks and scroll wheel rotation from the data package

Example Code that works for me (Android 5.0):

UsbManager usbManager;
UsbDevice usbDevice;
private void connect() {
 this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
 HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
 // just get the first enumerated USB device
 Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
 if (deviceIterator.hasNext()) {
 this.usbDevice = deviceIterator.next();
 }
 if (usbDevice == null) {
 Log.w(TAG, "no USB device found");
 return;
 }
 // ask for permission
 final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
 final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
 public void onReceive(Context context, Intent intent) {
 String action = intent.getAction();
 if (ACTION_USB_PERMISSION.equals(action)) {
 synchronized (this) {
 UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
 if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
 if(device != null){
 // call method to set up device communication
 Log.i(TAG, "permission granted. access mouse.");
 // repeat in a different thread
 transfer(device);
 }
 }
 else {
 Log.d(TAG, "permission denied for device " + device);
 }
 }
 } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
 UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
 if (device != null) {
 // TODO:
 // call your method that cleans up and closes communication with the device
 // usbInterface.releaseInterface();
 // usbDeviceConnection.close();
 }
 }
 }
 };
 PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
 IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
 context.registerReceiver(mUsbReceiver, filter);
 usbManager.requestPermission(usbDevice, mPermissionIntent);
}
private void transfer(UsbDevice device) {
 int TIMEOUT = 0;
 boolean forceClaim = true;
 // just grab the first endpoint
 UsbInterface intf = device.getInterface(0);
 UsbEndpoint endpoint = intf.getEndpoint(0);
 UsbDeviceConnection connection = this.usbManager.openDevice(device);
 connection.claimInterface(intf, forceClaim);
 byte[] bytes = new byte[endpoint.getMaxPacketSize()];
 connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT);
 // depending on mouse firmware and vendor the information you're looking for may
 // be in a different order or position. For some logitech devices the following 
 // is true:
 int x = (int) bytes[1];
 int y = (int) bytes[2];
 int scrollwheel = (int) bytes[3]
 // call a listener, process your data ...
}
answered Oct 13, 2016 at 20:07
Sign up to request clarification or add additional context in comments.

4 Comments

This works but after a while it crashes with filedescripter error
@SuiciDoga just don't call openDevice every time. Move it out of the transfer method
@volzo what permission u need in the manifest to make this work on Android <6? Could you post your manifest in this question?: stackoverflow.com/questions/54497779/usb-permission-android-6
Android should require a granted permission, though I added "<uses-feature android:name="android.hardware.usb.host" />" as explained in the Android USB Host article: developer.android.com/guide/topics/connectivity/usb/host and additionally android may open a dialog to ask for user confirmation once you access the USB device in your app.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.