Android 12下如何读取已挂载USB闪存驱动器中的文件
Android USB OTG存储读取可行方案
1. 处理MANAGE_EXTERNAL_STORAGE特殊权限
MANAGE_EXTERNAL_STORAGE是特殊权限,仅在清单中声明无效,必须引导用户到系统设置手动授权:
if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); }
授权后重启应用,确保权限生效。
2. 用存储访问框架(SAF)替代直接路径访问
/mnt/media_rw/属于系统挂载点,直接用File类访问会受SELinux限制,推荐通过StorageManager获取存储卷对应的DocumentFile:
StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE); List<StorageVolume> volumes = storageManager.getStorageVolumes(); for (StorageVolume volume : volumes) { // 判断是否为可移除存储(USB OTG) if (volume.isRemovable()) { // 获取访问该卷的Intent Intent intent = volume.createAccessIntent(null); startActivityForResult(intent, REQUEST_CODE_USB_ACCESS); } }
在onActivityResult中获取返回的Uri,再用DocumentFile遍历文件:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_USB_ACCESS && resultCode == RESULT_OK) { Uri uri = data.getData(); DocumentFile rootDir = DocumentFile.fromTreeUri(this, uri); // 遍历根目录下的文件 for (DocumentFile file : rootDir.listFiles()) { Log.d("USB_FILE", file.getName()); } } }
3. 完善USB_PERMISSION权限申请流程
USB_PERMISSION需要主动发起请求并接收广播回调:
// 注册广播接收器 private BroadcastReceiver usbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (UsbManager.ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(device != null){ // 权限已获取,可进行后续操作 } } else { Log.d("USB", "Permission denied for device " + device); } } } } }; // 发起权限请求 UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList(); UsbDevice device = deviceList.values().iterator().next(); // 获取第一个USB设备 PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(UsbManager.ACTION_USB_PERMISSION), 0); usbManager.requestPermission(device, permissionIntent);
清单中注册广播接收器:
<receiver android:name=".UsbReceiver"> <intent-filter> <action android:name="android.hardware.usb.action.USB_PERMISSION" /> </intent-filter> </receiver>
4. 避免硬编码挂载路径
不要直接使用/mnt/media_rw/这类系统路径,不同设备的挂载点可能不同,始终通过StorageManager或SAF获取合法的访问入口,这是Android 10+的规范要求。
内容的提问来源于stack exchange,提问作者BuzzBee
相关产品推荐
相关产品推荐

