最新消息:20210917 已从crifan.com换到crifan.org

【已解决】android程序运行出错:UsbManager(4294): exception in UsbManager.openDevice,java.lang.SecurityException: User has not given permission to device UsbDevice

Android crifan 9195浏览 0评论

【问题】

使用代码:

		//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

如图:

java.lang.SecurityException User has not given permission to device UsbDevice

即:

缺少了USB的操作权限。

【解决过程】

1.后来猜想:

估计是:

如之前:

【已解决】Android设备作为Host希望实现可以检测到USB设备插入

所述,

之前是通过在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.参考:

Android usb enumeration

发现:

好麻烦啊。

还需要用户点击运行操作此device才行。

而我希望的是:

自动获得操作usb设备的权限,无需系统弹出对话框问是否允许,

不希望用户操心这些事情。

所以,再去找:

【记录】android中想办法实现自动获得usb设备的操作权限

4.上面没法方便的绕开usb权限的事情。

所以只能再通过加代码,弹出对话框来获得权限了。。。

还是参考:

http://developer.android.com/guide/topics/connectivity/usb/host.html

去写代码吧。。。

最终,添加相关代码,实现了获得权限:

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设备的权限

  • 如果用户选择是:
    • allow this app access usb device choose yes
    • 则接下来,就有权限操作usb设备了
    • 再去mUsbManager.openDevice(usbDevice)就不会出现权限错误了
    • 并且,如果用户同时选择了,记住本次选择
      • choose yes allow app access usb device also default use this usb
      • 那么上述代码,后续再执行时,mUsbManager.hasPermission(usbDevice),就为真
      • 就可以直接去执行afterGetUsbPermission(usbDevice)
      • 而无需再去调用mUsbManager.requestPermission再去获得权限了
  • 如果用户选择否:
    • 代码就会执行到“Permission denied for device”的部分了。

 

注:

目前的现象,貌似是:

虽然之前已经选中了:默认使用该USB设备

但是USB设备拔掉再插入,貌似再去检测是否有权限,则还是会弹出对话框的。

而:

如果在点击了“默认使用该USB设备”,已经获得了权限后,只要USB设备不拔掉,则再去用

mUsbManager.hasPermission(usbDevice),

判断的话,的确是:

已经获得了USB设备操作权限,无需再弹出对话框去问用户要权限的。

转载请注明:在路上 » 【已解决】android程序运行出错:UsbManager(4294): exception in UsbManager.openDevice,java.lang.SecurityException: User has not given permission to device UsbDevice

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. USB设备拔掉再插入,还是会弹出对话框 不知道这个问题你解决没有,希望可以和你探讨一下
    胡生10年前 (2014-10-13)回复
96 queries in 0.194 seconds, using 23.40MB memory