25

I have a video file in the raw folder in my resources. I want to find the size of the file. I have this piece of code:

Uri filePath = Uri.parse("android.resource://com.android.FileTransfer/" + R.raw.video);
                File videoFile = new File(filePath.getPath());
                Log.v("LOG", "FILE SIZE "+videoFile.length());

But it always gives me that the size is 0. What am I doing wrong?

jww
  • 97,681
  • 90
  • 411
  • 885
Alex1987
  • 9,397
  • 14
  • 70
  • 92

5 Answers5

24

Try this:

AssetFileDescriptor sampleFD = getResources().openRawResourceFd(R.raw.video);
long size = sampleFD.getLength()
shem
  • 4,686
  • 2
  • 32
  • 43
  • 5
    That looks much safer than other answers. – Snicolas Oct 08 '13 at 09:25
  • 3
    +1 But it won't work by default on a lot of file types because `aapt` compresses them -- for a solution to that see here: http://stackoverflow.com/questions/19743169/how-can-i-use-openrawresourcesfd/19743170 – CodeClown42 Nov 02 '13 at 14:56
24

Try this lines:

InputStream ins = context.getResources().openRawResource (R.raw.video)
int videoSize = ins.available();
Aleadam
  • 40,203
  • 9
  • 86
  • 108
  • Same question / comment than I just posted under @EboMike's answer. Never had any problem this way?? – psycho Oct 08 '12 at 07:40
  • 3
    What `openRawResource()` returns is not a normal `InputStream` but an `AssetInputStream`. This subclass overrides `available()` and _is_ able to provide reliable information. – caw Feb 06 '13 at 22:44
  • @MarcoW. Umm, not according to the documentation: http://developer.android.com/reference/android/content/res/AssetManager.AssetInputStream.html#available() – CodeClown42 Nov 02 '13 at 14:58
  • 1
    @goldilocks: Well, yes! If you take a look at the documentation for `InputStream.available()`, you'll see that this is where the explanation comes from. `AssetInputStream` uses exactly the same text in its JavaDoc: http://developer.android.com/reference/java/io/InputStream.html#available() But the source shows that `AssetInputStream.available()` overrides the superclass's method and gets its result from a native method: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/content/res/AssetManager.java#AssetManager.AssetInputStream.available%28%29 – caw Nov 03 '13 at 01:39
  • @MarcoW. I don't doubt that or the fact that it there are implementations (*currently* including android) where it works. But if your standard is *what the API actually commits to*, then the API doesn't commit to this. If it doesn't work tomorrow on some device, it will be your fault for trusting in something basic programming principles say you should not! Also, there is a safe, by the book method -- see shem's answer. That's the canonical one, IMO. – CodeClown42 Nov 03 '13 at 09:19
16

You can't use File for resources. Use Resources or AssetManager to get an InputStream to the resource, then call the available() method on it.

Like this:

InputStream is = context.getResources().openRawResource(R.raw.nameOfFile);
int sizeOfInputStram = is.available(); // Get the size of the stream
EboMike
  • 76,846
  • 14
  • 164
  • 167
  • 14
    Never had a problem with this one?! This method is supposed to return `an estimated number of bytes that can be read`, not necessarily the real file size, and the documentation clearly discourages its use... http://developer.android.com/reference/java/io/InputStream.html#available() – psycho Oct 08 '12 at 07:40
  • 6
    Well, the documentation refers to generic streams that may take a while to retrieve data, like network streams. In a resource, the exact size is always known and available. – EboMike Oct 09 '12 at 00:04
10

Slight variation to the answer by @shem

AssetFileDescriptor afd = contentResolver.openAssetFileDescriptor(fileUri,"r");
long fileSize = afd.getLength();
afd.close();

Where fileUri is of type Android Uri

olfek
  • 3,210
  • 4
  • 33
  • 49
2

Reuseable Kotlin Extensions

You can call these on a context or activity. They are exception safe

fun Context.assetSize(resourceId: Int): Long =
    try {
        resources.openRawResourceFd(resourceId).length
    } catch (e: Resources.NotFoundException) {
        0
    }

This one is not as good as the first, but may be required in certain cases

fun Context.assetSize(resourceUri: Uri): Long {
    try {
        val descriptor = contentResolver.openAssetFileDescriptor(resourceUri, "r")
        val size = descriptor?.length ?: return 0
        descriptor.close()
        return size
    } catch (e: Resources.NotFoundException) {
        return 0
    }
}

If you'd like a simple way to get a different byte representation, you can use these

val Long.asKb get() = this.toFloat() / 1024
val Long.asMb get() = asKb / 1024
val Long.asGb get() = asMb / 1024 
Gibolt
  • 42,564
  • 15
  • 187
  • 127