P5music
P5music

Reputation: 3327

SAF - File written in parent folder, not in the right path

My app wants to copy a file from a private app folder to a SAF folder that was created inside an user-selected SAF folder. Folder creation is Ok.

The copy method is:

public static boolean copyFileToTargetSAFFolder(Context context, String filePath, String targetFolder, String destFileName ) 
{


    Uri uri = Uri.parse(targetFolder);

    String docId = DocumentsContract.getTreeDocumentId(uri);
    Log.d("target folder uri",uri.toString());
    Log.d("target folder id",docId);
    Uri dirUri = DocumentsContract.buildDocumentUriUsingTree(uri, docId );
    Log.d("dir uri",dirUri.toString());
    Uri destUri = null;

    try
    {
        destUri = DocumentsContract.createDocument(context.getContentResolver(), dirUri, "*/*", destFileName);
        Log.d("dest uri",destUri.toString());
    } 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;
}

the log is:

target folder uri: content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername%2Fsubfoldername

target folder id: raw:/storage/emulated/0/Download/foldername

dir uri: content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername

dest uri: content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername%2Ffile.txt

It is indeed what happens on the filesystem. In fact the file is copied and created in the parent folder, not in the subfolder. This code was from an answer on SO:

SAF - Invalid URI error from DocumentsContract.createDocument method (FileOutputStream copy)

Upvotes: 2

Views: 400

Answers (1)

P5music
P5music

Reputation: 3327

I do not know if it is only a workaround but if I replace

String docId = DocumentsContract.getTreeDocumentId(uri);

with

String docId = DocumentsContract.getDocumentId(uri);

the method works.

public static boolean copyFileToTargetSAFFolder(Context context, String filePath, String targetFolder, String destFileName ) 
{


    Uri uri = Uri.parse(targetFolder);

    String docId = DocumentsContract.getDocumentId(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;
}

Indeed now log has

dirUri content://com.android.providers.downloads.documents/tree/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Ffoldername%2Fsubfoldername

the file is correctly copied inside this folder.

Upvotes: 3

Related Questions