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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With