Reputation: 3327
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
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