You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:46:50