如何在Android中获取外部USB大容量存储路径?

时间:2018-08-15 08:34:38

标签: android usb-mass-storage

我需要从/导入/导出一些数据到USB记忆棒。 有没有办法获取已安装USB设备的路径?

我的代码如下:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while(deviceIterator.hasNext()){

    UsbDevice device = deviceIterator.next();
    UsbInterface deviceInterface = device.getInterface(0);

    if(deviceInterface != null && deviceInterface.getInterfaceClass() == UsbConstants.USB_CLASS_MASS_STORAGE){
        // check if path "mnt/usb_storage/*" exist
    }
}

当设备是大容量存储设备时,我可以搜索路径“ mnt / usb_storage / *”是否存在。 如果仅连接了一个USB大容量存储,或者在附加了第二个USB大容量存储时应用程序处于前台,则此方法会很好地工作。 如果您想知道,是的,有一些具有多个USB端口的Android设备。

当我具有UsbManager / UsbDevice / UsbInterface时,是否无法获取路径? 是所有设备上的路径,例如“ mnt / usb_storage / *”吗?

更新1:

目标Android版本5.1 要求:“ Filechooser”必须集成在应用程序内,必须过滤文件夹,文件名和文件类型。

更新2:

根据@greenapps的建议,我尝试了“ ACTION_OPEN_DOCUMENT_TREE”:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
intent.putExtra("android.content.extra.FANCY", true);
intent.putExtra("android.content.extra.SHOW_FILESIZE", true);
startActivityForResult(intent, OPEN_DOCUMENT_TREE_REQUEST_CODE);

这没有显示USB记忆棒,也无法过滤文件和文件夹。 Select Document Tree

同一设备:es-datei资源管理器能够显示usb设备。

ES Datei explorer

我的要求是显示一个自定义文件选择器,用户可以在其中从类似于es datei资源管理器的客户特定的云,内部存储或USB设备中选择文件。

我的搜索路径是否存在“ mnt / usb_storage / *”的解决方案按要求工作,我只是想知道是否有更好的方法。

2 个答案:

答案 0 :(得分:2)

现代Android系统上几乎没有路径。如今,您将尝试获得文档树方案。

有几种选择。

您可以查看getExternalFilesDirs()返回的第二或第三项。 (会给您一条路。但是无法写。)

对于Android 6及更高版本,请使用Intent.ACTION_OPEN_DOCUMENT_TREE让用户选择驱动器。这将使您满意。没有文件路径。

对于Android 7及更高版本,请查看Storage Volumes

答案 1 :(得分:0)

因此,我已经搜索了很多SO问题,以获取USB设备的路径。我还没有找到答案,但是由于这是Google搜索的重头戏,也是一个相当近期的问题,因此我将发布找到的答案。

尝试(已实现)

所以最初我尝试(使用自己的实现),因为问题包含:

public static String getUSBProblematic(Context context){
    UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
    if (usbManager == null) {
        Log.e(TAG, "Unable to get USB_SERVICE");
        return "";
    }
    UsbAccessory[] accessoryList = usbManager.getAccessoryList();
    if (accessoryList != null) {
        for (UsbAccessory usbAccessory : accessoryList) {
            // here we check the vendor
            Log.d(TAG, "getUSBProblematic: " + usbAccessory.toString());
        }
    }

    HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
    if(deviceList != null) {
        List<UsbDevice> usbDeviceList = new ArrayList<>(deviceList.values());

        for (Iterator<UsbDevice> iterator = usbDeviceList.iterator(); iterator.hasNext();) {
            UsbDevice next = iterator.next();

            boolean isMassStorage = false;
            for (int i = 0; i < next.getInterfaceCount(); i++) {
                // Check USB interface type is mass storage
                UsbInterface usbInterface = next.getInterface(i);
                if(usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_MASS_STORAGE && usbInterface.getEndpointCount() == 2) {

                    // Check endpoints support bulk transfer
                    for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
                        UsbEndpoint endpoint = usbInterface.getEndpoint(j);
                        if(endpoint != null) {
                            if(endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK){

                                // Valid mass storage
                                isMassStorage = true;
                            }
                        }
                    }
                }
            }

            if(!isMassStorage) {
                iterator.remove();
            }
        }

        for (UsbDevice usbDevice : usbDeviceList) {
            Log.d(TAG, "getUSBProblematic: Device Name" + usbDevice.getDeviceName());
            Log.d(TAG, "getUSBProblematic: Device Desc" + usbDevice.toString());
        }
    }
    return "";
}

所以我能从中得到的最好的东西是/dev/bus/usb/003,但仅此而已。

因此,在mounts中的/proc/mounts文件中查找(在设备上找到,请参见Android Studio中的Device File Explorer,我发现USB特定的存储设备已安装在/mnt/media_rw/ 。但是浏览到/storage,我看到了我期望或正在寻找的USB设备。

我不确定这是一个好的策略还是特定设备(我使用Huawei Mate 10 Pro),但是我正在使用

可能的解决方案

public static String getUSB(){
    File storageDirectory = new File("/storage");
    if(!storageDirectory.exists()) {
        Log.e(TAG, "getUSB: '/storage' does not exist on this device");
        return "";
    }

    File[] files = storageDirectory.listFiles();
    if(files == null) {
        Log.e(TAG, "getUSB: Null when requesting directories inside '/storage'");
        return "";
    }

    List<String> possibleUSBStorageMounts = new ArrayList<>();
    for (File file : files) {
        String path = file.getPath();
        if (path.contains("emulated") ||
                path.contains("sdcard") ||
                path.contains("self")) {
            Log.d(TAG, "getUSB: Found '" + path + "' - not USB");
        } else {
            possibleUSBStorageMounts.add(path);
        }
    }

    if (possibleUSBStorageMounts.size() == 0) {
        Log.e(TAG, "getUSB: Did not find any possible USB mounts");
        return "";
    }
    if(possibleUSBStorageMounts.size() > 1) {
        Log.d(TAG, "getUSB: Found multiple possible USB mount points, choosing the first one");
    }

    return possibleUSBStorageMounts.get(0);
}

编辑1

This也可能有用(搜索 USB