I set a preference for users to select save folder for my app using Storage Access Framework. After getting uri onActivityResult
I save it to SharedPreferences
as String and save image when it's to be saved.
I'm using this method to save image successfully.
public void saveImageWithDocumentFile(String uriString, String mimeType, String name) {
isImageSaved = false;
try {
Uri uri = Uri.parse(uriString);
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, uri);
DocumentFile file = pickedDir.createFile(mimeType, name);
OutputStream out = getContentResolver().openOutputStream(file.getUri());
isImageSaved = mBitmap.compress(CompressFormat.JPEG, 100, out);
out.close();
} catch (IOException e) {
throw new RuntimeException("Something went wrong : " + e.getMessage(), e);
}
Toast.makeText(MainActivity.this, "Image saved " + isImageSaved, Toast.LENGTH_SHORT).show();
}
If user deletes the folder selected using SAF, iget null DocumentFile file
and app crashes. My first question is how can i check if folder exist without opening SAF ui again.
I also want to use ParcelFileDescriptor to save same image with this method
public void saveImageWithParcelFileDescriptor(String folder, String name) {
if (mBitmap == null) {
Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
return;
}
String image = folder + File.separator + name + ".jpg";
Toast.makeText(MainActivity.this, "image " + image, Toast.LENGTH_LONG).show();
Uri uri = Uri.parse(image);
ParcelFileDescriptor pfd = null;
FileOutputStream fileOutputStream = null;
try {
pfd = getContentResolver().openFileDescriptor(uri, "w");
fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
mBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (pfd != null) {
try {
pfd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Toast.makeText(MainActivity.this, "Image saved " + isImageSaved, Toast.LENGTH_SHORT).show();
}
i get java.lang.IllegalArgumentException: Invalid URI: content://com.android.externalstorage.documents/tree/612E-B7BF%3Aname/imagePFD.jpg
on linepfd = getContentResolver().openFileDescriptor(uri, "w");
This is how I call this method, currentFolder is the folder I get using intent and same folder on first method.
saveImageWithParcelFileDescriptor(currentFolder, "imagePFD");
How can I fix this, and which method is more preferable and why?
DocumentFile
has anexists()
method. In theory,pickedDir.exists()
should tell you if it exists. In practice, it is up to the storage provider.That code has bugs:
You cannot grant yourself permissions using
grantUriPermission()
You cannot invent arbitrary
Uri
values via concatenation, particularly for a provider that is not yoursDelete it.
The first one.
The first one will work, perhaps with minor adjustment. The second one has no chance of working.