Android 9下使用usb-serial-for-android库的USB权限问题求助
在运行Android 9系统的Odroid N2开发板上,我通过RS485端口与设备交互时遇到权限问题:使用USB/RS485适配器+usb-serial-for-android库,基于Modbus RTU协议通信,Unity应用请求USB权限时弹窗不出现,连接设备时收到错误USB_PERMISSION denied,异常信息为java.lang.SecurityException: User has not given permission to the device.
我已尝试以下操作:
- 修改Manifest并添加相关配置(代码如下)
- 确保应用拥有Superuser权限
- 开发者选项中启用USB调试模式
- 调整设备读写权限
- 集成usb-serial-for-android库及对应Java插件
我的Manifest代码:
<?xml version="1.0" encoding="utf-8"?> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true"/> <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name"> <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" /> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity> </application>
请问如何解决此问题,让Unity应用在Android 9上获取与USB设备交互的必要权限?
1. 补全Manifest的USB相关配置
你的Manifest缺少核心的USB权限声明和设备过滤规则,这是系统触发权限弹窗的前提:
- 在
<manifest>根节点下添加权限和功能声明(不要放在<application>内部):
<uses-feature android:name="android.hardware.usb.host" /> <uses-permission android:name="android.permission.USB_PERMISSION" />
- 在
<activity>标签内新增设备关联的元数据:
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
然后在项目的res/xml目录下创建device_filter.xml,填入你的USB/RS485适配器的实际Vendor ID和Product ID:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="替换为你的设备VID" product-id="替换为你的设备PID" /> </resources>
2. 修正权限请求的逻辑流程
必须通过系统标准的UsbManager.requestPermission()方法触发权限弹窗,不能直接尝试连接设备。确保你的Java插件包含以下逻辑:
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); UsbDevice targetDevice = ...; // 遍历USB设备列表找到目标适配器 PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent("YOUR_USB_PERMISSION_ACTION"), 0); usbManager.requestPermission(targetDevice, permissionIntent);
同时要注册广播接收器,监听权限请求的结果,只有在用户授权后再执行设备连接操作。
3. 规避Unity Activity的广播拦截问题
Unity默认的UnityPlayerActivity可能会拦截系统广播,建议自定义一个继承自UnityPlayerActivity的Activity,在自定义Activity中处理USB权限请求和广播接收,避免权限逻辑被Unity的生命周期覆盖。
4. 适配Android 9的USB限制
Android 9对USB主机模式的权限验证更严格,需要额外检查:
- 通过开发板的终端执行
dmesg命令,确认USB适配器被正确识别为USB主机设备 - 把应用加入电池优化白名单,避免系统阻塞权限请求弹窗
- Superuser权限无法替代USB设备的授权流程,必须走系统的权限申请弹窗
内容的提问来源于stack exchange,提问作者Normandy

