We need to convert a file path to a content uri and pass on for subsequent processing to a common component. When we use "Uri.fromFile(file)" it returns a file uri and not a content uri. Please let us know how to get this converted. Appreciate your help.
for (File file : fileBaseFolder.listFiles()) {
Uri convertedUri = Uri.fromFile(file);//Need to convert this Uri to a Content uri
.........
}
Use FileProvider to serve your file.
It gives nice uries.
FileProvider.getUriForFile().
You can serve all files except those from removable micro sd card.
try MediaScannerConnection.scanFile
for (File file : fileBaseFolder.listFiles()) {
MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null,
(path, uri) -> Log.i(TAG, uri.toString()));
}
Take a look at the below link for the solution.
https://www.thetopsites.net/article/52460984.shtml
Also, the same question is asked here.
Related
I'm trying to adapt a File-based document system to something using DocumentFile in order to allow external storage read/write access on API >= 29.
I get the user to select the SD card root using Intent.ACTION_OPEN_DOCUMENT_TREE, and I get back a Uri as expected, which I can then handle using:
getContentResolver().takePersistableUriPermission(resultData.getData(),
Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
I can browse successfully through the external storage contents up to the selected root. All good.
But what I need to be able to do is write an arbitrary file in the chosen (sub)folder, and that's where I'm running into problems.
DocumentFile file = DocumentFile.fromSingleUri(mContext, Uri.parse(toPath));
Uri uri = file.getUri();
FileOutputStream output = mContext.getContentResolver().openOutputStream(uri);
Except on the openOutputStream() call I get:
java.io.FileNotFoundException: Failed to open for writing: java.io.FileNotFoundException: open failed: EISDIR (Is a directory)
That's slightly confusing to me, but the "file not found" part suggests I might need to create the blank output file first, so I try that, like:
DocumentFile file = DocumentFile.fromSingleUri(mContext, Uri.parse(toPath));
Uri uri = file.getUri();
if (file == null) {
return false;
}
if (file.exists()) {
file.delete();
}
DocumentFile.fromTreeUri(mContext, Uri.parse(getParentPath(toPath))).createFile("", uri.getLastPathSegment());
FileOutputStream output = mContext.getContentResolver().openOutputStream(uri);
I get a java.io.IOException:
java.lang.IllegalStateException: Failed to touch /mnt/media_rw/0B07-1910/Testing.tmp: java.io.IOException: Read-only file system
at android.os.Parcel.createException(Parcel.java:2079)
at android.os.Parcel.readException(Parcel.java:2039)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:188)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.call(ContentProviderNative.java:658)
at android.content.ContentResolver.call(ContentResolver.java:2042)
at android.provider.DocumentsContract.createDocument(DocumentsContract.java:1327)
at androidx.documentfile.provider.TreeDocumentFile.createFile(TreeDocumentFile.java:53)
at androidx.documentfile.provider.TreeDocumentFile.createFile(TreeDocumentFile.java:45)
Which doesn't make sense to me, since the tree should be writeable.
For what it's worth, the Uri I get back from Intent.ACTION_OPEN_DOCUMENT_TREE looks like this:
content://com.android.externalstorage.documents/tree/0B07-1910%3A
Interestingly, when I use that Uri to create a DocumentFile object to browse, using documentFile = DocumentFile.fromTreeUri(context, uri), then documentFile.getURI().toString() looks like:
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3A
i.e., it's had something appended to the end of it.
Then, I descend into what should be a writeable folder (like "Download"), and try creating a writeable file as described above. The "Download" folder gets the Uri:
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload
and the Uri I'm using for toPath, above, is then:
content://com.android.externalstorage.documents/tree/0B07-1910%3A/document/0B07-1910%3ADownload/Testing.tmp
which leads to the problems described previously trying to create it.
I haven't actually found any decent information about writing an arbitrary file under Storage Access Framework restrictions.
What am I doing wrong? Thanks. :)
Uri uri = uri obtained from ACTION_OPEN_DOCUMENT_TREE
String folderName = "questions.59189631";
DocumentFile documentDir = DocumentFile.fromTreeUri(context, uri);
DocumentFile folder = documentDir.createDirectory(folderName);
return folder.getUri();
Use createFile() for a writable file.
I have a File object and I want to get its Uri, that looks like:
content://media/external/images/media/2683
I've tried the following code:
val uri = FileProvider.getUriForFile(activity, "${BuildConfig.APPLICATION_ID}.file_provider", pictureFile)
But I'm getting this:
content://my.package.name.file_provider/external_files/Pictures/photo-1574403815163.jpg
Is it possible to get the Uri I need?
UPD: The reason I want to get another Uri - I can't create File object from this Uri later.
val uri = FileProvider.getUriForFile(activity, "${BuildConfig.APPLICATION_ID}.file_provider", pictureFile)
val file = File(uri.path)
When I try to file.exists() I'm always getting false.
I can't create File object with this Uri
That's because you don't do that. Moreover, you don't need that. pictureFile is a File.
If your are creating file with actual path then you just concad the content:// to that path
Iam not sure this is correct method or not but i get that what you expected , Try this one
I select an image from the gallery. Now I load it in a temp-file and can show it in a ImageView. Everything works fine.
Uri uri = data.getData();
File file = new File(uri+"");
String fileName = file.getName();
String filePath = file.getParent();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri);
//here come's the code to save the temp-file and so on
In the fileName and filePath I save the name and path for later use. Because if the user want to save the image I want to make a copy of them.
URI shown in the debugger: content:/media/external/images/media/12345
filePath: content:/media/external/images/media
fileName: 12345
If I want to save the image I use the fileName and filePath to build the URI and want to do the same like above. But it doesn't works. I get a FileNotFoundException "no content provider" from the MediaStore. Hmm - before I deleted the App for a fresh testing there comes "No such file or directory" and I thought I eliminate the "no content provider" Exception with the READ_EXTERNAL_STORAGE permission.
Uri uri = Uri.parse(filePath +"/"+ fileName);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Here I see also the correct URI in the debugger.
What is wrong?
I've set the permissions READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE in the AndroidManifest.
In the fileName and filePath I save the name and path for later use
A Uri is not a file, and yours most certainly is not a file.
What is wrong?
Your Uri has a content scheme. This is being served by a ContentProvider. You do not indicate where this Uri comes from, but I am going to guess that it is from ACTION_GET_DOCUMENT or something similar. In that case, like a Web URL that requires a working session, your access to the content identified by that Uri is short.
If you want to have longer-term access to the content, download it into your app, just as you would download content from a Web URL.
I am using directory selection as described in this Google Sample. It does provide file name and mime type of the children of the selected directory. I can get Document ID of the file too, if I use COLUMN_DOCUMENT_ID on the Cursor Query.
I am interested in the file URI of the children instead. When I use ACTION_OPEN_DOCUMENT instead of ACTION_OPEN_DOCUMENT_TREE, I get the child uri easily which is just obtained from adding a %2Fchildfile.extention (%2F is just a forward slash). So I tried to get child file uri using the following code -
uri = Uri.parse(docUri.toString()+"%2F"+fileName);
I got the file name, however when I run exists() method on it (By converting it into DocumentFile), it returns false. That means, either I don't have the permission of the file or it's not the correct way to get children uri.
Am I missing something here or is there any other way I can select a folder and get file uri of all of it's children easily.
PS: I am currently checking it in Marshamallow.
After reading the doc and trying out certain examples, I got the following way to get a single file Uri from a selected docUri/treeUri
uri = DocumentsContract.buildDocumentUriUsingTree(docUri,docId);
And then you can convert it anytime into a DocumentFile using following code -
DocumentFile file = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (DocumentsContract.isDocumentUri(context, uri)) {
file = DocumentFile.fromSingleUri(context, uri);
} else {
file = DocumentFile.fromTreeUri(context, uri);
}
}
fromTreeUri() method is required for the selected Tree Directory, so that it can return true on file.exists() method call.
You need to remember that if the children contain any directory, then you can't call childDirectory.listFiles() on it. It'll give UnsupportedOperationException, because you don't have permission to access the child directory's file. Read more about this here.
I am having a problem with selecting image file from external storage using file picker in Android. This question is the consequence of this question - No such file or diectory error in image file upload using Retrofit in Android. What my problem is opening and reading file from external storage on activity result. I want to convert result URI into File.
I read a pdf file from download folder on activity result
Uri bookUri = data.getData();
if(bookUri!=null)
{
String filePath = bookUri.toString();//bookUri.toString()
String mime = app.getMimeType(filePath);
if(mime!=null && !mime.isEmpty() && (mime.toLowerCase()=="application/pdf" || mime.toLowerCase()=="application/txt" || mime.toLowerCase()=="application/text"))
{
bookFile = new File(bookUri.getPath());
ivBookFile.setImageResource(R.drawable.book_selected);
}
else{
Toast.makeText(getBaseContext(),"Unable to process file you have chosen.",Toast.LENGTH_SHORT).show();
}
}
As you can see I used new File(bookUri.getPath()); to convert into File. The above code works well. It is working. The problem is now I am trying to open an image file in DCIM/Camera folder on activity result.
This is the code I used
Uri selectedImageUri = data.getData();
if(selectedImageUri!=null)
{
try{
bmpCoverImage = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImageUri);
imageFile = new File(selectedImageUri.getPath());
if(bmpCoverImage!=null)
{
ivCoverImage.setImageBitmap(bmpCoverImage);
}
}
catch (IOException e)
{
Toast.makeText(getBaseContext(),"An error occurred with the file selected",Toast.LENGTH_SHORT).show();
}
}
As you can see I used new File(selectedImageUri.getPath()); like I did in reading pdf file. This time the code is not working. When I do operation with the file like in previous question, it gives me error.
I used this way also
imageFile = new File(Environment.getExternalStorageDirectory(),selectedImageUri.getPath());
I got the same error. How can I open the image file correctly from external storage? How can I convert the chosen file URI from external storage into File?
I am having a problem with selecting image file from external storage using file picker in Android
If you are referring to the code that you are using in this question, you are not "using file picker". You are using ACTION_GET_CONTENT, which has never been a "file picker", nor will it ever be a "file picker".
I want to convert result URI into File.
Usually, that is not necessary. But, if that is what you want to do:
use ContentResolver and openInputStream() to get an InputStream on the content represented by the Uri
create a FileOutputStream on your desired file
use Java I/O to copy the bytes from the InputStream into the FileOutputStream
The above code works well. It is working.
It works for the small number of devices that you tested, for the specific activities that the user chose to handle the ACTION_GET_CONTENT request. It will not work on most Android devices, and it will not work in most circumstances. The only time that code will work is if the Uri has a file scheme. Most of the time, it will not. Instead, it will have a content scheme, representing content supplied by a ContentProvider.
Please how can I open the image file correctly from external storage?
If you wish to continue using ACTION_GET_CONTENT, please understand that this has nothing to do with external storage specifically. You are not getting a file, on external storage or elsewhere. You are getting a Uri. This is akin to a URL, such as the URL for this Web page. Just as a URL does not necessarily point to a file on your hard drive, a Uri does not necessarily point to a file on the filesystem. Use a ContentResolver and DocumentFile to work with the Uri and the content that it identifies.
If you want to always get files on external storage (and nowhere else), then use an actual file picker library.