Android平台通过OTG适配器连接U盘的文件读写访问方案问询
OTG U盘读写适配方案说明
核心疑问答复
- Android 11(R)及以上版本*无法不使用Storage Access Framework(SAF)*实现OTG U盘的合法读写,
requestLegacyExternalStorage配置在Android 11及以上系统中完全失效,原生系统没有绕过SAF直接访问外部存储设备的公开API。 - 仅运行Android 10及以下系统的设备,可以不使用SAF,直接获取U盘路径后通过File API读写。
各系统版本实现方案
1. Android 10及以下版本(非SAF方案)
你当前的配置(targetSdkVersion 29 + android:requestLegacyExternalStorage="true" + 存储运行时权限)在此场景下完全可用,U盘路径可以通过StorageManager服务获取:
// 需先获取READ_EXTERNAL_STORAGE运行时权限 StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE); List<StorageVolume> volumes = storageManager.getStorageVolumes(); for (StorageVolume volume : volumes) { // 过滤可移除的非主存储设备,即OTG U盘 if (volume.isRemovable() && !volume.isPrimary()) { // 反射获取U盘根路径,Android 10及以下可用 try { String usbPath = (String) volume.getClass().getDeclaredMethod("getPath").invoke(volume); // 拿到usbPath后就可以直接通过File API读写对应路径下的文件 } catch (Exception e) { e.printStackTrace(); } } }
2. Android 11(R)及以上版本(必须用SAF方案)
此场景下没有非SAF的合法实现方案,SAF的适配流程如下:
- 调用系统文件选择器,引导用户授权访问OTG U盘
private static final int REQUEST_OTG_PERMISSION = 1001; // 唤起系统目录选择器 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent, REQUEST_OTG_PERMISSION);
- 拿到用户授权后的Uri,获取长期访问权限并读写文件
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_OTG_PERMISSION && resultCode == RESULT_OK && data != null) { Uri treeUri = data.getData(); // 申请长期访问权限,下次启动应用无需重复授权 getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // 后续通过ContentResolver即可操作该Uri对应目录下的所有文件,包括读写、新建、删除等 } }
兼容建议
如果你的应用需要覆盖Android 10到Android 14全版本,建议统一使用SAF方案实现OTG文件读写,无需做系统版本判断,适配成本更低,也符合谷歌应用市场的权限规范,不会出现上架被拒的问题。
内容的提问来源于stack exchange,提问作者Neeraj Rana
相关产品推荐
相关产品推荐

