Uri content://media/external/downloads/<file> doesn't exist for some devices
Hey! Reproduced on real devices and simulators based on Android 11.
Future<OpenResult> openFileFromPath(String path) {
try {
return OpenFile.open(path)
} catch (e) {
print(e.toString());
}
}
openFileFromPath('content://media/external/downloads/79')
I/flutter (13676): Open file result (ResultType.fileNotFound): the content://media/external/downloads/79 file does not exists
Flutter 2.2.2 • channel unknown • unknown source
Framework • revision d79295af24 (3 weeks ago) • 2021-06-11 08:56:01 -0700
Engine • revision 91c9fc8fe0
Tools • Dart 2.13.3
Maybe you can try the file path instead of the URI
@crazecoder, it works with the full path, but I have no way to get it on Android 11.
I'm not sure about your usage scenario, but if you want to select a file, you can use file_picker to get the path
Hi, I have a similar scenario. My app needs to save downloaded files to public download dir (/storage/emulated/0/Download). From API 29 the only way to do this is to use MediaStore API. Below is the example method in Java to copy file to Download dir:
private String saveToDownloadsAndroidQAndHigher(String sourceFilePath, String fileName) throws IOException {
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.Downloads.MIME_TYPE, "application/pdf");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
contentValues.put(MediaStore.Downloads.IS_PENDING, 1);
final Uri targetPdfUri =
getActivity().getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues);
final OutputStream outputStream =
getActivity().getContentResolver().openOutputStream(targetPdfUri);
copyFile(sourceFilePath, outputStream);
contentValues.clear();
contentValues.put(MediaStore.Downloads.IS_PENDING, 0);
getActivity().getContentResolver().update(targetPdfUri, contentValues, null, null);
return targetPdfUri.toString();
}
Uri returned from MediaStore is exactly in format: content://media/external/downloads/79
Now I want to open this file in external app. Unfortunately open_file cannot do this, so I need to do this native way:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(Uri.parse("content://media/external/downloads/79"), "application/pdf");
try {
getActivity().startActivity(intent);
} catch (Exception e) {
throw new RuntimeException(e);
}
It would be nice to be able to open such uri using your plugin
Hi, I have a similar scenario. My app needs to save downloaded files to public download dir (/storage/emulated/0/Download). From API 29 the only way to do this is to use MediaStore API. Below is the example method in Java to copy file to Download dir:
private String saveToDownloadsAndroidQAndHigher(String sourceFilePath, String fileName) throws IOException { final ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Downloads.DISPLAY_NAME, fileName); contentValues.put(MediaStore.Downloads.MIME_TYPE, "application/pdf"); contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS); contentValues.put(MediaStore.Downloads.IS_PENDING, 1); final Uri targetPdfUri = getActivity().getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues); final OutputStream outputStream = getActivity().getContentResolver().openOutputStream(targetPdfUri); copyFile(sourceFilePath, outputStream); contentValues.clear(); contentValues.put(MediaStore.Downloads.IS_PENDING, 0); getActivity().getContentResolver().update(targetPdfUri, contentValues, null, null); return targetPdfUri.toString(); }Uri returned from MediaStore is exactly in format: content://media/external/downloads/79
Now I want to open this file in external app. Unfortunately open_file cannot do this, so I need to do this native way:
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addCategory("android.intent.category.DEFAULT"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(Uri.parse("content://media/external/downloads/79"), "application/pdf"); try { getActivity().startActivity(intent); } catch (Exception e) { throw new RuntimeException(e); }It would be nice to be able to open such uri using your plugin
You can use Cursor to get the path
Thanks for the tip. I managed to get full path using following code:
try (Cursor cursor = getActivity().getContentResolver().query(targetPdfUri, null, null, null, null)) {
cursor.moveToFirst();
final int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
return cursor.getString(columnIndex);
}
However MediaStore.MediaColumns.DATA has been deprecated in API 29. When I open above path to pdf using OpenFile, on Android 10 I get an error that Adobe Pdf Reader cannot access file. It works fine on Android 11. So I still believe it would be good to support content uris. Invoking activity in Java for content uri works fine for both Android 10 and 11.