Xamarin写入USB存储遇未授权访问异常的解决方法
解决USB存储写入时的未授权访问异常问题
我来帮你搞定这个USB未授权的问题!看起来你已经在尝试处理USB权限的广播请求,但可能有些细节没做到位,导致写入操作时还是触发了权限异常。下面一步步给你梳理解决方案:
1. 先确认基础存储权限(针对OTG U盘这类外部存储)
如果你的USB存储是普通的OTG U盘,除了USB设备权限,还需要申请存储相关的动态权限:
- Android 10及以下:需要
WRITE_EXTERNAL_STORAGE和READ_EXTERNAL_STORAGE权限,记得在Manifest里声明,然后在代码中动态申请。 - Android 11+:如果是写入非媒体文件,可能需要
MANAGE_EXTERNAL_STORAGE权限;如果是媒体文件,用READ_MEDIA_IMAGES/READ_MEDIA_VIDEO等,写入对应媒体类型的话部分场景不需要额外权限,但稳妥起见还是确认权限状态。
2. 修正USB权限请求的关键细节
你的代码里的PendingIntent在Android 12及以上版本存在问题,因为默认的flag设置已经不适用了,需要指定FLAG_IMMUTABLE或者FLAG_MUTABLE(根据你的需求),否则权限请求可能不生效。另外,要确保广播接收器正确处理权限授予结果,只有在权限通过后再执行写入操作。
修正后的代码示例
// 定义权限广播常量 private const string ACTION_USB_PERMISSION = "com.yourpackage.USB_PERMISSION"; private UsbManager usbManager; private UsbDevice device; private PendingIntent mPermissionIntent; // 初始化部分 usbManager = (UsbManager)GetSystemService(Context.UsbService); device = null; // Android 12+ 需要指定PendingIntent的flag if (Build.VERSION.SdkInt >= BuildVersionCodes.S) { mPermissionIntent = PendingIntent.GetBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntentFlags.Immutable); } else { mPermissionIntent = PendingIntent.GetBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); } IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); RegisterReceiver(usbReciever, filter); // 遍历USB设备,找到你要操作的设备 if (usbManager != null) { foreach (var dev in usbManager.DeviceList.Values) { // 根据设备的VendorId、ProductId或者名称匹配目标设备 if (dev.VendorId == YOUR_VENDOR_ID && dev.ProductId == YOUR_PRODUCT_ID) { device = dev; break; } } // 如果找到设备,请求权限 if (device != null) { if (!usbManager.HasPermission(device)) { usbManager.RequestPermission(device, mPermissionIntent); } else { // 已经有权限,直接执行写入操作 WriteByteToUsbDevice(device); } } } // 广播接收器处理权限结果 private class UsbReciever : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { if (ACTION_USB_PERMISSION.Equals(intent.Action)) { lock (this) { UsbDevice device = (UsbDevice)intent.GetParcelableExtra(UsbManager.ExtraDevice); if (intent.GetBooleanExtra(UsbManager.ExtraPermissionGranted, false)) { if (device != null) { // 权限授予成功,执行写入操作 WriteByteToUsbDevice(device); } } else { // 权限被拒绝,处理错误逻辑 Toast.MakeText(context, "USB权限被拒绝,无法写入文件", ToastLength.Short).Show(); } } } } } // 写入字节的方法(确保在权限通过后调用) private void WriteByteToUsbDevice(UsbDevice device) { // 这里实现具体的写入逻辑,比如打开UsbDeviceConnection,获取接口和端点,然后写入字节 UsbDeviceConnection connection = usbManager.OpenDevice(device); if (connection != null) { UsbInterface intf = device.GetInterface(0); if (connection.ClaimInterface(intf, true)) { UsbEndpoint endpoint = intf.GetEndpoint(0); byte[] data = new byte[] { 0x01 }; // 你要写入的字节 int result = connection.BulkTransfer(endpoint, data, data.Length, 1000); if (result >= 0) { Toast.MakeText(this, "字节写入成功", ToastLength.Short).Show(); } else { Toast.MakeText(this, "写入失败", ToastLength.Short).Show(); } connection.ReleaseInterface(intf); } connection.Close(); } }
3. 关键注意事项
- 不要在权限请求后立刻执行写入:必须等待广播接收器返回权限授予成功的结果后,再调用写入方法,否则此时权限还未生效,会触发异常。
- Manifest声明权限:记得在AndroidManifest.xml中添加USB相关权限:
<uses-permission android:name="android.permission.USB_PERMISSION" /> <!-- 存储权限根据你的Android版本添加 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> - 设备匹配要准确:遍历USB设备时,一定要通过VendorId和ProductId精准匹配你要操作的设备,避免请求错误设备的权限。
内容的提问来源于stack exchange,提问作者mjm_fast
相关产品推荐
相关产品推荐

