0

我的应用程序正在迁移到 SAF,或者至少正在进行一些实验。

现在它必须将文件从私有应用程序文件夹复制到授权的 SAF 文件夹。

使用的方法是:

 static boolean copyFileToTargetFolderWithNewName(Activity activity, String filePath,String targetFolderUri,String newName)
{
    File file = new File(filePath);

    FileInputStream fis=null;
    Uri docUri=null;
    try {
        fis=new FileInputStream(file);
    } catch (FileNotFoundException e) {
    return false;
    }

    deleteIfExisting(activity,Uri.parse(targetFolderUri),newName);


    ContentResolver resolver = activity.getContentResolver();
    boolean result=false;

    int offset=filePath.lastIndexOf(".");
    String ext="";
    if (offset!=-1) ext=filePath.substring(offset+1);
    String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
    try {
//error here
          docUri=DocumentsContract.createDocument(resolver,Uri.parse(targetFolderUri),mimetype,newName);
    } catch (FileNotFoundException e) {
        result=false;
    }

    try {
        ParcelFileDescriptor pfd=resolver.openFileDescriptor(docUri, "w");
        FileOutputStream fos=new FileOutputStream(pfd.getFileDescriptor());
        int b;
        while  ((b=fis.read()) != -1)
            fos.write(b);       
        fis.close();
        fos.close();
        pfd.close();
        result= true;
        } catch (FileNotFoundException e) {
        result=false;
        } catch (IOException e) {
        result=false;
        }
    return result;
}

我明白了

java.lang.IllegalArgumentException: Invalid URI: content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffolder/subfolder

该文件夹是通过以下方法创建的:

static public DocumentFile createFolderInFolder(Activity activity,String parentFolderUriString,String folderName)
{
DocumentFile result=null;
ContentResolver contentResolver;
contentResolver = activity.getContentResolver();

Uri parentFolderUri=null;

Uri oldParentUri = Uri.parse(parentFolderUriString);
String id = DocumentsContract.getTreeDocumentId(oldParentUri );

parentFolderUri= DocumentsContract.buildChildDocumentsUriUsingTree(oldParentUri , id);

/*
    String id=DocumentsContract.getTreeDocumentId(Uri.parse(parentFolderUriString));

id=StringUtils.fromLastSlashRight(parentFolderUriString);
parentFolderUri= DocumentsContract.buildTreeDocumentUri(PROVIDER_AUTHORITY,id
        );
*/


DocumentFile parentFolder = DocumentFile.fromTreeUri(activity, parentFolderUri);
result=parentFolder.createDirectory(folderName);

/*try {
   result=DocumentsContract.createDocument(contentResolver,parentFolderUri,DocumentsContract.Document.MIME_TYPE_DIR,folderName);

} catch (FileNotFoundException e) {
    result =null;
}*/

return result;
}

如您所见,之前版本的创建已被注释,因为它不起作用。有必要使用 DocumentFile,但似乎与 DocumentsContract 不兼容。我错了吗?

那么SAF坏了吗?还是我在绕圈子?

4

1 回答 1

2

当使用本地文件的完整路径调用以下代码时,ACTION_OPEN_DOCUMENT_TREE 获得的内容方案将文件复制到该 saf 位置,名称相同或不同,由您决定。

public static boolean copyFileToSafFolder(Context context, String filePath, String rootPath, String destFileName) {
    Uri uri = Uri.parse(rootPath);
    String docId = DocumentsContract.getTreeDocumentId(uri);
    Uri dirUri = DocumentsContract.buildDocumentUriUsingTree(uri, docId);
    Uri destUri = null;

    try {
        destUri = DocumentsContract.createDocument(context.getContentResolver(), dirUri, "*/*", destFileName);
    } catch (FileNotFoundException e) {
        e.printStackTrace();

        return false;
    }

    InputStream is = null;
    OutputStream os = null;
    try {
        is = new FileInputStream(filePath);
        os = context.getContentResolver().openOutputStream(destUri, "w");
        byte[] buffer = new byte[1024];

        int length;
        while ((length = is.read(buffer)) > 0)
            os.write(buffer, 0, length);

        is.close();
        os.flush();
        os.close();

        return true;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return false;
}
于 2019-09-28T16:41:59.783 回答