Android usb enumeration

17,318

The crash comes when you are trying to access the device with

connection = mManager.openDevice(device);

It crashes because it is throwing a SecurityException because you haven't obtained permission from the user to use the device. It looks like you tried to obtain permission from the user in the line before this

mManager.requestPermission(device, mPermissionIntent);

But you need to understand that the call to requestPermission() is asynchronous. It doesn't return immediately with the permission. What it does is that it shows the user a dialog and asks the user if he will grant permission to your application. Once the user grants or denies permission the dialog is dismissed and the PendingIntent that you passed to requestPermission() is used to broadcast an Intent indicating the permission was granted (or not). You need to listen for this in a registered BroadcastReceiver and when the onReceive() method is called you can then examine the extras in the received Intent and decide how to proceed. Only if the user grants you permission can you move on to call openDevice().

This sounds kinda complicated, but that's the way it works.

Basically, you need to call

mManager.requestPermission(device, mPermissionIntent);

and then wait until permission has been granted before you try to access the device.

Share:
17,318
Britto
Author by

Britto

google

Updated on June 04, 2022

Comments

  • Britto
    Britto almost 2 years

    I am writing an android USB host application for which I am trying to enumerate the devices connected with tablet. I follow the code in the android USB host documentation in the developer site.

    My code is as follows

    AndroidUSBActivity

    public class AndroidUSBActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        USBClass usb = new USBClass();
        ArrayList<String> deviceList = usb.GetUSBDevices(getBaseContext());
        final CharSequence[] items = deviceList.toArray(new CharSequence[deviceList.size()]);
    
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Select a Reader");
        builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                String selectedDevice = (String) items[item];
                dialog.dismiss();
    
                TextView DeivceName = (TextView)findViewById(R.id.textView1);
                DeivceName.setText(selectedDevice);
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
    }
    }
    

    USBClass

    public class USBClass {
    
    
    private static UsbManager mManager = null;
    private static HashMap<String, UsbDevice> mdevices;
    private static PendingIntent mPermissionIntent;
    private static final String ACTION_USB_PERMISSION =
            "com.android.example.USB_PERMISSION";
    private 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("usb", "permission granted for device " + device);
                        }
                    } 
                    else {
                        Log.i("usb", "permission denied for device " + device);
                    }
                }
            }
        }
    };   
    
    
    public ArrayList<String> GetUSBDevices(Context context){
        mManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        mdevices = new HashMap<String, UsbDevice>();
        ArrayList<String> deviceList = new ArrayList<String>();
        mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("com.android.example.USB_PERMISSION"), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        context.registerReceiver(mUsbReceiver, filter);
    
    
        // check for existing devices
        for (UsbDevice device :  mManager.getDeviceList().values()) {
            String deviceName = null;
            UsbDeviceConnection connection = null;
            if(device.getVendorId() == 0x0123){
                mManager.requestPermission(device, mPermissionIntent);
                connection = mManager.openDevice(device);
                byte rawBuf[] = new byte[255];
                int len = connection.controlTransfer(0x80, 0x06, 0x0302, 0x0409, rawBuf, 0x00FF, 60);
                rawBuf = Arrays.copyOfRange(rawBuf, 2, len);
                deviceName = new String(rawBuf);
                deviceList.add(deviceName);
                mdevices.put(deviceName, device);
            }
    
         }
        context.unregisterReceiver(mUsbReceiver);
        return deviceList;
    }
    }
    

    LOGCAT

    06-13 10:13:54.556: D/dalvikvm(2219): Late-enabling CheckJNI
    06-13 10:13:54.586: I/System.out(2219): Sending WAIT chunk
    06-13 10:13:54.586: W/ActivityThread(2219): Application bri.sample is waiting for the debugger on port 8100...
    06-13 10:13:54.596: I/dalvikvm(2219): Debugger is active
    06-13 10:13:54.786: I/System.out(2219): Debugger has connected
    06-13 10:13:54.786: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:54.986: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:55.186: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:55.406: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:55.596: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:55.796: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:55.996: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:56.206: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:56.406: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:56.645: I/System.out(2219): waiting for debugger to settle...
    06-13 10:13:56.846: I/System.out(2219): debugger has settled (1337)
    06-13 10:13:57.116: E/UsbManager(2219): exception in UsbManager.openDevice
    06-13 10:13:57.116: E/UsbManager(2219): java.lang.SecurityException: User has not given  permission to device   UsbDevice[mName=/dev/bus/usb/001/004,mVendorId=1254,mProductId=20758,mClass=0,mSubclass=0,mProtocol=0,mInterfaces=[Landroid.hardware.usb.UsbInterface;@41679100]
    06-13 10:13:57.116: E/UsbManager(2219):     at android.os.Parcel.readException(Parcel.java:1327)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.os.Parcel.readException(Parcel.java:1281)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.hardware.usb.IUsbManager$Stub$Proxy.openDevice(IUsbManager.java:340)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.hardware.usb.UsbManager.openDevice(UsbManager.java:250)
    06-13 10:13:57.116: E/UsbManager(2219):     at  bri.sample.USBClass.GetUSBDevices(USBClass.java:66)
    06-13 10:13:57.116: E/UsbManager(2219):     at bri.sample.AndroidUSBActivity.onCreate(AndroidUSBActivity.java:19)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.Activity.performCreate(Activity.java:4465)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.os.Handler.dispatchMessage(Handler.java:99)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.os.Looper.loop(Looper.java:137)
    06-13 10:13:57.116: E/UsbManager(2219):     at android.app.ActivityThread.main(ActivityThread.java:4424)
    06-13 10:13:57.116: E/UsbManager(2219):     at java.lang.reflect.Method.invokeNative(Native Method)
    06-13 10:13:57.116: E/UsbManager(2219):     at java.lang.reflect.Method.invoke(Method.java:511)
    06-13 10:13:57.116: E/UsbManager(2219):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    06-13 10:13:57.116: E/UsbManager(2219):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    06-13 10:13:57.116: E/UsbManager(2219):     at dalvik.system.NativeStart.main(Native Method)
    06-13 10:13:57.566: D/dalvikvm(2219): threadid=1: still suspended after undo (sc=1 dc=1)
    06-13 10:14:04.266: D/AndroidRuntime(2219): Shutting down VM
    06-13 10:14:04.266: W/dalvikvm(2219): threadid=1: thread exiting with uncaught exception (group=0x40a531f8)
    06-13 10:14:04.296: E/AndroidRuntime(2219): FATAL EXCEPTION: main
    06-13 10:14:04.296: E/AndroidRuntime(2219): java.lang.RuntimeException: Unable to start activity ComponentInfo{bri.sample/bri.sample.AndroidUSBActivity}: java.lang.NullPointerException
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.os.Handler.dispatchMessage(Handler.java:99)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.os.Looper.loop(Looper.java:137)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread.main(ActivityThread.java:4424)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at java.lang.reflect.Method.invokeNative(Native Method)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at java.lang.reflect.Method.invoke(Method.java:511)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at dalvik.system.NativeStart.main(Native Method)
    06-13 10:14:04.296: E/AndroidRuntime(2219): Caused by: java.lang.NullPointerException
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at bri.sample.USBClass.GetUSBDevices(USBClass.java:68)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at bri.sample.AndroidUSBActivity.onCreate(AndroidUSBActivity.java:19)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.Activity.performCreate(Activity.java:4465)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
    06-13 10:14:04.296: E/AndroidRuntime(2219):     ... 11 more
    

    PROBLEM

    I have the device plugged in and then I install the application. The first time when the application launches, it gets crashed.

  • Britto
    Britto almost 12 years
    Dear David i understand what u say. But what i require is that the usb functions are written as a jar library so that it can be included to build other applications. So an activity uses this usb library and provide calls to the usb apis in the library. Now that request permission being asynchronous i am unable to get the devices connected in the activity.
  • David Wasser
    David Wasser almost 12 years
    Since this works asynchronously, you'll have build your library asynchronously. That means that you'll need to provide an API that the user can register a 'callback listener' on. Then, the user will need to request some access, and then, when the access is available, you'll have to call the user back on his callback listener. I hope that makes sense.
  • Richard Barraclough
    Richard Barraclough almost 4 years
    What is mPermissionIntent? Is it the activity you're in that's making the request? Or is it something else?