android - 无法在外部 SD 卡 (Lollipop) 中创建目录

标签 android android-5.0-lollipop android-sdcard

我的内部存储没有问题,但我想在外部 SD 卡上创建一个目录,对于 KitKat 之前的版本,File.mkdirs() 可以工作。

我的代码的一部分:

//external sd card
DocumentFile.fromFile(new File("/storage/sdcard1/")).exists(); //returns true
DocumentFile.fromFile(new File("/storage/sdcard1/")).canRead(); //returns true
DocumentFile.fromFile(new File("/storage/sdcard1/")).canWrite(); //returns true
DocumentFile.fromFile(new File("/storage/sdcard1/test")).exists(); //returns false
DocumentFile.fromFile(new File("/storage/sdcard1/")).createDirectory("test"); //returns null

//internal storage
DocumentFile.fromFile(new File("/storage/emulated/0/")).exists(); //returns true
DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns false
DocumentFile.fromFile(new File("/storage/emulated/0/")).createDirectory("test"); //it works
DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns true
DocumentFile.fromFile(new File("/storage/emulated/0/test")).createFile("text", "file.txt"); //it works

//external sd card
(new File("/storage/sdcard1/test2/subfolder")).exists(); //returns false
(new File("/storage/sdcard1/test2/subfolder")).mkdirs(); //returns false

//internal storage
(new File("/storage/emulated/0/test2/subfolder")).exists(); //returns false
(new File("/storage/emulated/0/test2/subfolder")).mkdirs(); //returns true

在 AndroidManifest.xml 中:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

使用 BQ Aquaris e4、Android Lollipop 5.0 和 1GB micro SD 卡进行测试。

更新:这就是我获取卷列表的方式:

private static ArrayList<StorageInfo> listAvaliableStorage(Context context) {
        ArrayList<StorageInfo> storagges = new ArrayList<>();
        StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        try {
            Class<?>[] paramClasses = {};
            Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses);
            getVolumeList.setAccessible(true);
            Object[] params = {};
            Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params);
            if (invokes != null) {
                StorageInfo info;
                for (Object obj : invokes) {
                    Method getPath = obj.getClass().getMethod("getPath");
                    String path = (String) getPath.invoke(obj);
                    info = new StorageInfo(path);
                    File file = new File(info.getPath());
                    if ((file.exists()) && (file.isDirectory())
                        //&& (file.canWrite())
                            ) {
                        info.setTotalStorage(file.getTotalSpace());
                        info.setFreeStorage(file.getUsableSpace());
                        Method isRemovable = obj.getClass().getMethod("isRemovable");
                        String state;
                        try {
                            Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class);
                            state = (String) getVolumeState.invoke(storageManager, info.getPath());
                            info.setState(state);
                            info.setRemovable((Boolean) isRemovable.invoke(obj));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        storagges.add(info);
                    }
                }
            }
        } catch (NoSuchMethodException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        storagges.trimToSize();

        return storagges;
    }

硬编码路径仅适用于本示例

更新2: 我使用文件浏览器在 SD 卡中创建了目录:“test”。当我执行这段代码时:

File file = new File("/storage/sdcard1/test/", "file.txt");
fileOutput = new FileOutputStream(file);

第二行抛出FileNotFoundException:/storage/sdcard1/test/file.txt:打开失败:EACCES(权限被拒绝)

我做错了什么?

最佳答案

这是由于 Android Lollipop 的设计造成的。 Environment.getExternalStorageDirectory() 将仅返回模拟外部存储的路径。 Android 不会公开任何为您提供 sdcard 路径的 API。

此外,在 Lollipop 中,应用程序无法写入 SD 卡中自己目录之外的位置,除非通过存储访问框架获得用户权限。

尝试context.getExternalFilesDirs()。这将为您提供应用程序可以写入数据的路径列表。其中之一位于 SD 卡中,类似于/storage/sdcardname/Android/data/yourAppName/files

关于android - 无法在外部 SD 卡 (Lollipop) 中创建目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32629792/

相关文章:

java - android api 参数编号更改。如何支持?

android - 如何在windows中从git获取代码

android - 在 APK 中编码/解码 AndroidManifest.xml

java - 在 Android 中使用整数 ArrayList

android - 工具栏在窗体上滚出屏幕

java - 如何使用 OS Lollipop 在 Android 中裁剪 Java 图像

java - 图像未保存在我的相机应用程序中

java - 图像无法识别

Android - 获取对 SD 卡上任何文件路径具有写入权限的 DocumentFile(已获得 SD 卡权限)

android - 工具栏 - findViewbyID 返回 null