【问题标题】:SAF - Invalid Uri error when copying file from private app folder to authorized SAF folderSAF - 将文件从私有应用程序文件夹复制到授权的 SAF 文件夹时出现无效的 Uri 错误
【发布时间】:2020-01-28 10:14:54
【问题描述】:

我的 Android 必须将文件从私有应用程序文件夹复制到之前被授予权限和授权的 SAF 位置。 代码是:

static boolean copyDocumentFileToTargetFolderWithNewName(Activity activity, String docUri,String targetFolderUri,String newName)
{
    deleteIfExisting(activity,Uri.parse(targetFolderUri),newName);
    ContentResolver resolver = activity.getContentResolver();
    boolean result=false;
    Log.d("copy",docUri+" "+targetFolderUri+" "+newName);
    Log.d("doc exists",String.valueOf(fileExists(activity,docUri)));  //error here
    try {
        DocumentsContract.copyDocument(resolver,Uri.parse(docUri),Uri.parse(targetFolderUri));//or error here
        DocumentsContract.renameDocument(resolver,Uri.parse(docUri),newName);
        result=true;
    } catch (FileNotFoundException e) {
        result=false;
    }

    return result;
}

static public boolean fileExists(Activity activity,String fileUriString)
{
    ContentResolver contentResolver;
    contentResolver = activity.getContentResolver();
    String parentFolderUriString=StringUtils.fromLastSlashLeft(fileUriString);
    String fileName=StringUtils.fromLastSlashRight(fileUriString);
    Uri parentFolderUri=Uri.parse(parentFolderUriString);
    boolean exists;
    DocumentFile docFile=DocumentFile.fromTreeUri(activity,parentFolderUri).findFile(fileName); //error here
    exists= (null!=docFile);
    return exists;
}

(带有一些不言自明的字符串实用程序调用)

这里是 Log.d() 行的结果

D/copy: file:///storage/emulated/0/Android/data/com.myappname.app/folder/subfolder/file.txt content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FSAFfolder/newname.txt

我明白了

java.lang.IllegalArgumentException: Invalid URI: file:///storage/emulated/0/Android/data/com.myappname.app/folder/subfolder/file.txt

DocumentFile docFile=DocumentFile.fromTreeUri(activity,parentFolderUri).findFile(fileName);

第二种方法

或者,当 Log.d() 被注释时,

java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.ContentProviderClient.call(java.lang.String, java.lang.String, android.os.Bundle)' on a null object reference

在这一行:

DocumentsContract.copyDocument(resolver,Uri.parse(docUri),Uri.parse(targetFolderUri));

在第一种方法中。 我的代码有什么问题?私人文件夹uris没有授权吗?如何授权?

【问题讨论】:

    标签: android directory nullpointerexception file-copying storage-access-framework


    【解决方案1】:

    我的代码有什么问题?

    docUriparentFolderUri 都不是文档 Uri。它们是您使用Uri.fromFile() 或其他东西创建的Uri 值。你可以知道,因为他们有file 方案。

    关于您的即时崩溃,fromTreeUri() 需要一个文档Uri。将fromFile() 用于file Uri 值。

    一旦你克服了这个问题,我希望你会在你的copyDocument() 通话中崩溃。这就是我最初认为的问题所在,直到我重新阅读您的问题。您正在尝试复制非文档Uri (docUri),并且the JavaDocs for copyDocument() 声明第一个参数需要是文档Uri

    带有 Document#FLAG_SUPPORTS_COPY 的文档,此值不得为空。

    DocumentsContractUri 称为“文档”时,表示通过DocumentsContract 本身获得的Uri。这将包括通过ACTION_OPEN_DOCUMENT 获得的Uri 或通过树DocumentFile 获得的Uri。但是,这不包括:

    • Uri.fromFile() 创建的Uri
    • 来自FileProvider.getUriForFile()Uri
    • Uri.parse()httphttps URL 创建的Uri

    私有文件夹 uris 没有授权吗?

    这不是“授权”的问题。 fromTreeUri() 需要一个文档 UricopyDocument() 需要一个文档 Uri。您不能将它们与非文档 Uri 值一起使用,仅此而已。

    【讨论】:

    • 那么,我必须发送一个 Intent 还是有办法将 file:/// uris 转换为适当授权的 content:/// 表单?
    • @P5music:我不知道有什么方法可以做到这一点。请注意,您可以使用普通的 Java 文件 I/O 将文件复制到文档中,使用 ContentResolver 及其 openOutputStream() 方法获取 OutputStream 以将字节写入。 AFAIK copyDocument() 是否存在以防两个文档都由同一个提供商处理,并且碰巧存在不涉及实际本地复制操作的“快捷方式”。例如,从一个 Google Drive 文档复制到另一个文档可能只涉及到 Google 服务器的网络调用,而实际的副本是在那里进行的。
    • 是的,我认为有多种方法。也许还传递了一个意图。我得检查一下。我还可以使用 OutpuStream 创建自己的复制方法。
    猜你喜欢
    • 2020-01-28
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 2012-01-03
    相关资源
    最近更新 更多