I am getting uri using GET_CONTENT and also it works when used in Glide to show the image. But I am not getting file size. It always shows 0.
I tried using File(uri.path).length()
fun fileSize(uri: Uri){
var a = File(uri.path).length()
}
A Uri is not a file.
Add a dependency for DocumentFile, such as androidx.documentfile:documentfile. Then, replace your code with:
fun fileSize(uri: Uri){
var a = DocumentFile.fromSingleUri(uri).length()
}
The File constructor takes a file system pathname as as its argument. You have given it a "path" extracted from a URI which is probably not a pathname for a file system object. (It might be if you are using a file: URL, but you are not checking the schema, so you can't be sure.)
If your File object has a pathname for a non-existent file, then when you call File::length, the documentation states that length() will return zero.
In the Java world you could try the following:
URI uri = ...
File file = new File(uri);
long length = file.length();
However, this only works if:
The URI is an absolute URI with a file: schema.
The file that the URI denotes exists in the local file system namespace.
(If 1. is not true, you get an exception. If 2. is not true, you get a zero result.)
This should also work on the Android platform ... without adding any extra dependencies.
Related
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'm [still] new on android development and about Java and about Kotlin (also an explanation in Java could be ok, however, I'm studying it also, Kotlin is prefered) and I'm struggling for deleting a simple downloaded file into the ExternalStorage.
Of course I enabled permission for read & write, and, even if this code returns a "True", I still can see the untouched file into my Download folder
here the code:
___UPDATE
// uri of my file in external storage ~/Download dir
var uri = Uri.parse (Environment.getExternalStorageDirectory().getPath() + "/Download/$myFilename$myExtensionVar")
// file object pointing at uri of file in external storage
val downloadedFile = File(uri.toString())
var deletedBool:Boolean = downloadedFile.delete()
println("myTag - deleted Boolean: $deletedBool")
if (deletedBool){
println("myTag - uri of file-to-be-deleted: $uri")
var secondStepToDelete:Int = context.getContentResolver().delete(uri, null, null)
println("myTag - second Step for deletion: $secondStepToDelete")
}
The file i am trying to rid of is a multimedia file (.mp3) and I added the second block of code (the one inside the IF statement) since I found that should work, having to do with the "DocumentProvider" (I'm new and I still don't know how to proper call its methods..) but, of course, It doesn't work at all.
I think I do need the ID (long type i guess) for the file stored into the external storage, however I haven't found yet how to get it
Thanks in advance for the help!
To build a File object, use the File constructor. To build a File object for a location off of a certain root directory, use the two-parameter File(File, String) constructor:
val downloadedFile = File(Environment.getExternalStorageDirectory(), "Download/$myFilename$myExtensionVar")
Unless you are getting a Uri from DownloadManager or something, there is no Uri that you need to delete().
I have more written here on external storage and how to work with it.
In Kotlin
file.deleteRecursively()
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.
In Android, I want to create a pointer that points to already existing file by way of its filepath.
For example, my pseudo-code:
String path = "file/directory/filename";
File ptr = File's pointed to by the path
The Android documentation only provides methods with which one can create a new file through a file path, but I just want a File object that only points to an already existing File.
How do I do that?
Use:
String path = "file/directory/filename";
File ptr = new File(path);
// check If file exists.
if(ptr.exists()) {
// Your code Here if file exists
}
File f = new File(path);
f points to a virtual file , if the file doesnt exist, writing anything to it, will either create it or cause a system crash , depending on the type of content you are writing to it.
deleting a file that doesnt exist will also fail, so any operation with files must be encapsulated with try catch for IOException
see http://developer.android.com/reference/java/io/File.html
also on android's new Kitkat you explicity have to request the permission to READ_EXTRANL_STORAGE if you want to read, and WRITE_EXTERNAL_STORAGE if you want to write
I'm trying to post a notification that lets the user open a locally stored file. My code looks like this:
Intent notificationIntent = new Intent(Intent.ACTION_VIEW);
notificationIntent.setAction(android.content.Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(new File(filename));
notificationIntent.setData(uri);
Where "filename" is the full path to a locally stored file, usually in the /mnt/sdcard/download directory. The files I want to display are of various types: images, PDF documents, HTML, etc.
This works, but sometimes Android tries to open the file as the wrong type. For example, a jpeg file will open in a web browser view and instead of seeing the image, I see the binary data from the file displayed as text. Other times it works file. For example, some PDF files correctly open in a PDF viewer and some do not.
I'm not sure why this is. The documentation says I should not have to pass an explicit content type. If I do set the content type explicitly, things seem to work fine. The problem is, I don't always know what the content type should be (the file is downloaded from an external source and can be anything, and no, the MIME type is not in the HTTP headers, I checked for that).
What can I do here? Is there some function I can call with a filename to have Android return me the best content type for that file? Moreover, why is this not happening automatically when the Intent is processed?
Thanks.
You've most likely figured this out; I'm posting in case someone else is stuck on this. I do the following to get the mime-type of the file:
//Get the file path
Uri path = Uri.fromFile(file);
MimeTypeMap type_map = MimeTypeMap.getSingleton();
//Get the extension from the path
String extension = MimeTypeMap.getFileExtensionFromUrl(path.toString());
extension = extension.toLowerCase();
if (extension.contains(".")) {
extension = extension.substring(extension.lastIndexOf("."));
}
String mime_type = type_map.getMimeTypeFromExtension(extension);