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

Android无需ACTION_OPEN_DOCUMENT_TREE自动访问USB存储实现文件备份

自动复制指定USB设备文件的实现方案

一、采用Android USB Host API直接访问目标U盘

由于你的设备是锁定状态的内部应用,无需遵循应用商店合规限制,可以通过USB Host API直接识别并访问名为Flash_1的U盘,跳过用户手动选择的步骤。

核心实现步骤

  • 监听U盘插入事件
    注册广播接收器监听系统发送的android.hardware.usb.action.USB_DEVICE_ATTACHED广播,当U盘插入时自动触发逻辑,过滤识别目标设备。
  • 定位U盘挂载路径
    通过读取/proc/mounts文件或执行mount命令,解析USB存储设备的挂载信息,匹配卷标为Flash_1的设备路径。示例代码片段:
    private String getFlash1MountPath() {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("/proc/mounts"));
            String line;
            while ((line = reader.readLine()) != null) {
                // 过滤USB存储挂载项,适配vfat/exfat等常见U盘文件系统
                if (line.contains("/dev/block/sd") && (line.contains("vfat") || line.contains("exfat"))) {
                    String[] parts = line.split(" ");
                    String mountPoint = parts[1];
                    if ("Flash_1".equals(getVolumeLabel(new File(mountPoint)))) {
                        reader.close();
                        return mountPoint;
                    }
                }
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    private String getVolumeLabel(File mountDir) {
        try {
            Process process = Runtime.getRuntime().exec("mount");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.contains(mountDir.getAbsolutePath())) {
                    int labelIndex = line.indexOf("label=");
                    if (labelIndex != -1) {
                        String labelPart = line.substring(labelIndex + 6);
                        int endIndex = labelPart.indexOf(" ");
                        return endIndex != -1 ? labelPart.substring(0, endIndex) : labelPart;
                    }
                }
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
  • 后台执行文件复制
    获取到U盘挂载路径后,使用普通File API递归遍历所有文件,复制到平板指定存储目录(如getExternalFilesDir(null))。注意必须在后台线程执行复制操作,避免ANR,可使用Coroutine或WorkManager实现。

二、权限与清单配置

在AndroidManifest.xml中添加必要权限和广播注册:

<!-- USB Host功能声明 -->
<uses-feature android:name="android.hardware.usb.host" android:required="true" />
<!-- 存储访问权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 10+ 全文件访问权限 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    android:minSdkVersion="30" />

<!-- USB设备广播接收器 -->
<receiver android:name=".UsbDeviceReceiver">
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
        <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
    </intent-filter>
    <!-- 可选:添加U盘VID/PID过滤,精准识别目标设备 -->
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/usb_device_filter" />
</receiver>

若需要精准过滤设备,在res/xml下创建usb_device_filter.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device vendor-id="你的U盘VID" product-id="你的U盘PID" />
</resources>

三、关键注意事项

  • Android版本适配:Android 10及以上需手动开启MANAGE_EXTERNAL_STORAGE权限,可预先在锁定设备上配置完成。
  • 错误提示:添加未检测到目标U盘、复制失败等场景的用户提示(如Toast),确保技术小白能直观了解状态。
  • 测试验证:在目标平板上使用实际的Flash_1U盘测试,确保挂载路径识别和文件复制逻辑稳定。

内容的提问来源于stack exchange,提问作者Josh Hunter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:21:13