Content resolver returns wrong size
Asked Answered
L

2

8

I am picking an image from the gallery and querying its size via ContentResolver API, it returns 29kb.

However when I check the file via adb using ls -al it is 44kb

here is how I query the size of the image:

    private fun getFileInfo(contentResolver: ContentResolver, fileUri: Uri): Pair<String, Long>? {
    val projection = arrayOf(MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.SIZE)
    val metaCursor = contentResolver.query(fileUri, projection, null, null, null)
        metaCursor?.use {
            if (it.moveToFirst()) {
                val displayNameIndex = it.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
                val sizeIndex = it.getColumnIndex(MediaStore.MediaColumns.SIZE)
                return Pair(it.getString(displayNameIndex), it.getLong(sizeIndex))
            }
    }
    return null
}

I am using an Oreo Emulator. I have also checked via emulator's tools, file browser shows as 29kb on the other hand file details shows 45kb. What is going on?

Here are the images from file browser:

Summary

Details

Another side note, above situation can be reproducible every time when using camera app on emulator with Android 26-Oreo emulator, however it is fine with emulator Android 25-Nougat.

I have checked, new Document API also returns 29kb

Lifton answered 17/1, 2018 at 14:2 Comment(6)
Did you tried to force media store to rescan? Maybe size was changed and it is not updated in the databaseAncel
@Ancel It is a Google API emulator, so cannot run root commands, but restarted the emulator.Lifton
root commands? I'm pretty sure that Intent.ACTION_MEDIA_SCANNER_SCAN_FILE doesn't need rootAncel
@Ancel I have tried after your comment, not helping.Lifton
Is it not because one is the real size of the file, and the other one the space occupied by the file on the storage?Coleen
@Coleen is it so different as 29kb vs 45kb? Secondly why and how it is changed on Oreo? I am asking from content provider to give me a stream and a size. Where is the logic on that if size does not match with stream length...Lifton
K
6

I had a similar issue. The ContentResolver was underestimating the true filesize by about 400 bytes. I solved it using a similar approach to that explained in How to correctly get the file size of an android.net.Uri? :

ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(imageUri, "r");
fileLength = pfd.getStatSize();
pfd.close();
Koestler answered 21/8, 2020 at 19:59 Comment(1)
I wouldn't recommend using it inside a loop. When I used this function in a loop with 10000 objects, it caused a delay of about 10-20 seconds.Artiste
N
-1

Android 8.0 (Oreo) introduced the 'SDCardFS' filesystem, which replaced 'FUSE' on the /sdcard partition.

it is possible that this new filesystem has a large cluster size and is therefore not able to allocate exactly 29kb, but instead the smallest block larger than 29kb, which in your case is 44.*kb.

The difference between ls -al and file details is probably caused by different rounding.

Namhoi answered 27/1, 2018 at 14:39 Comment(3)
I doubt if that is the case. I have took several shots; when an image showed 35kb, details showed 53kb on the same emulator. And side note, 8.1 Emulator also returns different values, however difference is much more small.Lifton
@guness, does this only happen on images? have you tried different image formats? EDIT: sometimes the filesystem doesn't deallocate space after the file has shrunk, causing fragmentation, this also might be the case if you've edited the file a bunch.Namhoi
Videos seems to be fine, and I haven't edited images ever. Lastly Camera takes images in one format only: jpg Edit: I believe this is related to following question: #21882822Lifton

© 2022 - 2024 — McMap. All rights reserved.