【问题】
使用代码://Method2: detect supported usb serial from android usb serial driver
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbSerialDriver mSerialDevice = UsbSerialProber.acquire(mUsbManager);
去检测usb设备,结果出错:11-07 11:09:32.734: D/com.xxxxx.common.Log(4294): Begin check usb action
11-07 11:09:32.742: E/UsbManager(4294): exception in UsbManager.openDevice
11-07 11:09:32.742: E/UsbManager(4294): java.lang.SecurityException: User has not given permission to device UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1027,mProductId=24577,mClass=0,mSubclass=0,mProtocol=0,mInterfaces=[Landroid.hardware.usb.UsbInterface;@428d03e0]
11-07 11:09:32.742: E/UsbManager(4294): at android.os.Parcel.readException(Parcel.java:1425)
11-07 11:09:32.742: E/UsbManager(4294): at android.os.Parcel.readException(Parcel.java:1379)
11-07 11:09:32.742: E/UsbManager(4294): at android.hardware.usb.IUsbManager$Stub$Proxy.openDevice(IUsbManager.java:374)
11-07 11:09:32.742: E/UsbManager(4294): at android.hardware.usb.UsbManager.openDevice(UsbManager.java:267)
11-07 11:09:32.742: E/UsbManager(4294): at com.hoho.android.usbserial.driver.UsbSerialProber$1.getDevice(UsbSerialProber.java:50)
11-07 11:09:32.742: E/UsbManager(4294): at com.hoho.android.usbserial.driver.UsbSerialProber.acquire(UsbSerialProber.java:115)
11-07 11:09:32.742: E/UsbManager(4294): at com.hoho.android.usbserial.driver.UsbSerialProber.acquire(UsbSerialProber.java:95)
11-07 11:09:32.742: E/UsbManager(4294): at com.xxxxx.activities.DeviceListActivity.foundSupportedUsb(DeviceListActivity.java:284)
11-07 11:09:32.742: E/UsbManager(4294): at com.xxxxx.activities.DeviceListActivity.access$3(DeviceListActivity.java:244)
11-07 11:09:32.742: E/UsbManager(4294): at com.xxxxx.activities.DeviceListActivity$3.run(DeviceListActivity.java:456)
11-07 11:09:32.742: E/UsbManager(4294): at java.util.Timer$TimerImpl.run(Timer.java:284)
11-07 11:09:32.750: D/com.xxxxx.common.Log(4294): Not Found supported USB serial device
如图:
即:
缺少了USB的操作权限。
【解决过程】
1.后来猜想:
估计是:
如之前:
所述,
之前是通过在AndroidManifest.xml中加入intent-filter的action,支持检测:
android.hardware.usb.action.USB_DEVICE_ATTACHED
(同时加上对应的meta-data,可对应的res/xml中加上usb的过滤配置文件)
的,而这种方式:
在app没运行时,对于插入USB设备
系统可以检测到USB插入的事件
然后弹出对话框问程序是否打开
如果打开,此时:
系统会自动给app授予usb的操作权限
使得:
后续去open对应的usb的device,而就已有了对应的权限。
2.而此处:
当前不是通过intent-filter的action的静态方式
而是代码中通过UsbManager动态检测对应的USB设备的。
结果是:
其中内部此处调用的UsbSerialDriver中,没有获得对应的权限,而导致上述的报错的。
所以需要去添加对应的权限。
3.参考:
发现:
好麻烦啊。
还需要用户点击运行操作此device才行。
而我希望的是:
自动获得操作usb设备的权限,无需系统弹出对话框问是否允许,
不希望用户操心这些事情。
所以,再去找:
4.上面没法方便的绕开usb权限的事情。
所以只能再通过加代码,弹出对话框来获得权限了。。。
还是参考:
去写代码吧。。。
最终,添加相关代码,实现了获得权限:import android.widget.Toast;
import android.content.Intent;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
public class SomeActivity extends BaseActivity {
private static UsbManager mUsbManager;
private void openUsbDevice(){
//before open usb device
//should try to get usb permission
tryGetUsbPermission();
}
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private void tryGetUsbPermission(){
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbPermissionActionReceiver, filter);
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
//here do emulation to ask all connected usb device for permission
for (final UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
//add some conditional check if necessary
//if(isWeCaredUsbDevice(usbDevice)){
if(mUsbManager.hasPermission(usbDevice)){
//if has already got permission, just goto connect it
//that means: user has choose yes for your previously popup window asking for grant perssion for this usb device
//and also choose option: not ask again
afterGetUsbPermission(usbDevice);
}else{
//this line will let android popup window, ask user whether to allow this app to have permission to operate this usb device
mUsbManager.requestPermission(usbDevice, mPermissionIntent);
}
//}
}
}
private void afterGetUsbPermission(UsbDevice usbDevice){
//call method to set up device communication
Toast.makeText(context, String.valueOf("Got permission for usb device: " + usbDevice), Toast.LENGTH_LONG).show();
Toast.makeText(context, String.valueOf("Found USB device: VID=" + usbDevice.getVendorId() + " PID=" + usbDevice.getProductId()), Toast.LENGTH_LONG).show();
doYourOpenUsbDevice(usbDevice);
}
private void doYourOpenUsbDevice(UsbDevice usbDevice){
//now follow line will NOT show: User has not given permission to device UsbDevice
UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice);
//add your operation code here
}
private final BroadcastReceiver mUsbPermissionActionReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
//user choose YES for your previously popup window asking for grant perssion for this usb device
if(null != usbDevice){
afterGetUsbPermission(usbDevice);
}
}
else {
//user choose NO for your previously popup window asking for grant perssion for this usb device
Toast.makeText(context, String.valueOf("Permission denied for device" + usbDevice), Toast.LENGTH_LONG).show();
}
}
}
}
};
}
【总结】
如此,就可以实现了:
代码中,动态的通过
mUsbManager.requestPermission
去让android弹出对话框
问用户是否给予此app操作USB设备的权限如果用户选择是:
则接下来,就有权限操作usb设备了
再去mUsbManager.openDevice(usbDevice)就不会出现权限错误了
并且,如果用户同时选择了,记住本次选择
那么上述代码,后续再执行时,mUsbManager.hasPermission(usbDevice),就为真
就可以直接去执行afterGetUsbPermission(usbDevice)
而无需再去调用mUsbManager.requestPermission再去获得权限了
如果用户选择否:代码就会执行到“Permission denied for device”的部分了。
注:
目前的现象,貌似是:
虽然之前已经选中了:默认使用该USB设备
但是USB设备拔掉再插入,貌似再去检测是否有权限,则还是会弹出对话框的。
而:
如果在点击了“默认使用该USB设备”,已经获得了权限后,只要USB设备不拔掉,则再去用
mUsbManager.hasPermission(usbDevice),
判断的话,的确是:
已经获得了USB设备操作权限,无需再弹出对话框去问用户要权限的。