【问题标题】:android 6.0 can not write external sdcardandroid 6.0 无法写入外部sdcard
【发布时间】:2016-08-20 02:59:22
【问题描述】:

在 Android v6.0.1 中无法将文件写入外部 SDCard。 测试设备:Redmi Note3

我已经拥有写权限:

@TargetApi(21)
public void requestDocumentPermission() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, SDCardBrowser.REQUEST_DOCUMENTS);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_DOCUMENTS && resultCode == RESULT_OK) { // given permission
        Uri uri = data.getData();
        takeUriPermission(data.getFlags(), uri);
        SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
        editor.putString(Constants.PREFS_DEFAULT_URI, uri.toString()).apply();
        doCopy(selectedNodes, toNode);
    }
    super.onActivityResult(requestCode, resultCode, data);
}

下面是我的复制方法,它运行正常但我没有在目标字典中找到目标文件。谁遇到过这个问题?请帮帮我。

@TargetApi(23)
public static void copyFileV23(File srcFile, File destFile) {
    FileInputStream in = null;
    OutputStream out = null;
    Context context = XXXApplication.getInstance().getApplicationContext();
    ContentResolver resolver = context.getContentResolver();
    String strUri = PreferenceManager.getDefaultSharedPreferences(context).getString(Constants.PREFS_DEFAULT_URI, null);
    if (null == strUri) {
        return;
    }
    DocumentFile rootDocument = DocumentFile.fromTreeUri(context, Uri.parse(strUri));

    try {
        in = new FileInputStream(srcFile);
        DocumentFile target = find(destFile.getAbsolutePath(), rootDocument, getMimeType(srcFile));
        out = resolver.openOutputStream(target.getUri());

        if (null != out) {
            byte[] buf = new byte[4096];
            int len;
            while ((len = in.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            in.close();
            out.close();
        } catch (IOException ignore) {
        }
    }
}

private static DocumentFile find(String absolutePath, DocumentFile root, String mime) {
    if (null == root || null == absolutePath) {
        return null;
    }
    String[] paths = absolutePath.split("\\/");
    for (int i = 0; i < paths.length; i++) {
        if (paths[i].equals(""))
            continue;

        DocumentFile documentFile = root.findFile(paths[i]);

        if (null == documentFile) {
            if (i < paths.length - 1) {
                documentFile = root.createDirectory(paths[i]);
            } else {
                documentFile = root.createFile(mime, paths[i]);
            }
        }
        root = documentFile;
    }
    return root;
}

Edit-1 找到解决方案,find() 方法不正确。应该是这样的:

private static DocumentFile findFileInExternal(String absolutePath, DocumentFile root, String mime) {
    if (null == root || null == absolutePath) {
        return null;
    }

    String externalPath = ExternalStorage.getStoragePath(true);
    if (null == externalPath) {
        return null;
    }
    absolutePath = absolutePath.substring(externalPath.length());

    String[] paths = absolutePath.split("\\/");
    for (int i = 0; i < paths.length; i++) {
        if (paths[i].equals(""))
            continue;

        DocumentFile documentFile = root.findFile(paths[i]);

        if (null == documentFile) {
            if (i < paths.length - 1) {
                documentFile = root.createDirectory(paths[i]);
            } else {
                documentFile = root.createFile(mime, paths[i]);
            }
        }

        root = documentFile;
    }

    return root;
}

【问题讨论】:

  • 如果您的 find 方法不起作用,您应该在问题中包含该方法。
  • @ianhanniballake 也许你没看到兄弟,在代码区域向下滚动你会看到 find() 方法发布:-)
  • 检查您的应用信息 --> 是否拥有权限以确保您拥有。
  • 已经检查了很多次,PermissionChecker.checkSelfPermission返回GRANTED,app info --> Permission也被授予。 android6.0只有DocumentFile可以写外接sdcard?

标签: android android-6.0-marshmallow android-sdcard


【解决方案1】:

find() 方法错误。在执行split 操作之前,我应该删除外部 sdcard 路径。或者它会添加两次外部 sdcard 路径。下面是正确的find() 方法:

private static DocumentFile find(String absolutePath, DocumentFile root, String mime) {
    if (null == root || null == absolutePath) {
        return null;
    }

    String externalPath = ExternalStorage.getStoragePath(true);
    if (null == externalPath) {
        return null;
    }
    absolutePath = absolutePath.substring(externalPath.length());

    String[] paths = absolutePath.split("\\/");
    for (int i = 0; i < paths.length; i++) {
        if (paths[i].equals(""))
            continue;

        DocumentFile documentFile = root.findFile(paths[i]);

        if (null == documentFile) {
            if (i < paths.length - 1) {
                documentFile = root.createDirectory(paths[i]);
            } else {
                documentFile = root.createFile(mime, paths[i]);
            }
        }

        root = documentFile;
    }

    return root;
}

【讨论】:

    【解决方案2】:

    看看getExternalFilesDirs()。它会告诉你两个可以写入文件的路径。第二个是可移动的微型 SD 卡。

    应用只能写入卡上的应用特定目录。

    Google 允许这样做。但是现在你必须看看你的制造商是否实现了它。

    这个限制的有趣之处在于您不需要这些目录的通常写入和读取权限。

    【讨论】:

    • 但我需要写入文件 2 外部 sdcard,我已经测试过 file.mkdir 无法在外部路径成功创建字典 getExternalFilesDirs()
    • 那么您现在知道制造商对此进行了限制。你确定你用过 ...FilesDirs() 吗?而不是 ...FilesDir()?你有两条路吗?你只谈一条路。
    • 是的,但这是我的 PM 的要求 :-) 我必须这样做,所以我找到了 DocumentFile 并使用这种方式确实可以写。 (如果我是老板,我会切断这个功能= =。)
    • 是的,我有两条路径。我想要的是在外部 sdcard 中执行写操作,所以我只谈到了外部 sdcard。实际上它可以得到两条路径。
    • 你有没有尝试在第二条路径上写?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多