88

I'm a beginner in Android programming.

I'm writing an application to list all video file in a folder and display information of all videos in the folder. But when i try to get the video duration it return null and i can't find the way to get it.

Any one can help me?

Below is my code:

Uri uri = Uri.parse("content://media/external/video/media/9");
Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
if(cursor.moveToFirst()) {
    String duration = cursor.getString(0);
    System.out.println("Duration: " + duration);
}
neowinston
  • 7,584
  • 10
  • 52
  • 83
Tue Nguyen
  • 933
  • 1
  • 7
  • 7

9 Answers9

148

Use MediaMetadataRetriever to retrieve media specific data:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
//use one of overloaded setDataSource() functions to set your data source
retriever.setDataSource(context, Uri.fromFile(videoFile));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long timeInMillisec = Long.parseLong(time );

retriever.release()
vir us
  • 9,920
  • 6
  • 57
  • 66
  • 2
    this is the best solution (for API 10+) – Amir Uval Jan 11 '16 at 13:00
  • 3
    This is a good solution, but the method extractMetadata returns "null" on some devices with Android 4.4 or lower. I used the MediaPlayer class to retrieve the file duration... – Massimo Jul 09 '16 at 10:13
  • Extracted duration will be in "Micro seconds" not "Milli seconds". – Ashkan Sarlak May 14 '18 at 16:43
  • 4
    ^ I was wrong, it's in milli seconds. I thought that way because of the doc and signature of other methods in the class: @param timeUs The time position in microseconds ... getFrameAtTime(long timeUs) – Ashkan Sarlak May 14 '18 at 17:21
  • Please note that extractMetadata will return null on some devices. You will have to find another way to get duration in that case. – ShrimpCrackers May 27 '20 at 16:16
45

I think the easiest way is:

MediaPlayer mp = MediaPlayer.create(this, Uri.parse(uriOfFile));
int duration = mp.getDuration();
mp.release();
/*convert millis to appropriate time*/
return String.format("%d min, %d sec", 
        TimeUnit.MILLISECONDS.toMinutes(duration),
        TimeUnit.MILLISECONDS.toSeconds(duration) - 
        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration))
    );
saschoar
  • 8,150
  • 5
  • 43
  • 46
Nolesh
  • 6,848
  • 12
  • 75
  • 112
12

Kotlin Extension Solution

Here is the way to fetch media file duration in Kotlin

fun File.getMediaDuration(context: Context): Long {
    if (!exists()) return 0
    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(context, Uri.parse(absolutePath))
    val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
    retriever.release()

    return duration.toLongOrNull() ?: 0
}

If you want to make it safer (Uri.parse could throw exception), use this combination. The others are generally just useful as well :)

fun String?.asUri(): Uri? {
    try {
        return Uri.parse(this)
    } catch (e: Exception) {
    }
    return null
}

val File.uri get() = this.absolutePath.asUri()

fun File.getMediaDuration(context: Context): Long {
    if (!exists()) return 0
    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(context, uri)
    val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
    retriever.release()

    return duration.toLongOrNull() ?: 0
}

Not necessary here, but generally helpful additional Uri extensions

val Uri?.exists get() = if (this == null) false else asFile().exists()

fun Uri.asFile(): File = File(toString())
Gibolt
  • 42,564
  • 15
  • 187
  • 127
7

I don't think you post your URI into the mediastore video query

Uri uri = Uri.parse("content://media/external/video/media/9");

Cursor cursor = MediaStore.Video.query(res, data.getData(), new String[]{MediaStore.Video.VideoColumns.DURATION});
EdChum
  • 376,765
  • 198
  • 813
  • 562
blorgggg
  • 414
  • 6
  • 15
2
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(uriOfFile);
long duration = Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION))
int width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
int height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
retriever.release();
d219
  • 2,707
  • 5
  • 31
  • 36
1
public static long getDurationOfSound(Context context, Object soundFile)
  {
    int millis = 0;
    MediaPlayer mp = new MediaPlayer();
    try
    {
      Class<? extends Object> currentArgClass = soundFile.getClass();
      if(currentArgClass == Integer.class)
      {
        AssetFileDescriptor afd = context.getResources().openRawResourceFd((Integer)soundFile);
            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        afd.close();
      }
      else if(currentArgClass == String.class)
      {
        mp.setDataSource((String)soundFile);
      }
      else if(currentArgClass == File.class)
      {
        mp.setDataSource(((File)soundFile).getAbsolutePath());
      }
      mp.prepare();
      millis = mp.getDuration();
    }
    catch(Exception e)
    {
    //  Logger.e(e.toString());
    }
    finally
    {
      mp.release();
      mp = null;
    }
    return millis;
  }
Ashok Domadiya
  • 1,124
  • 13
  • 31
1
MediaPlayer mpl = MediaPlayer.create(this,R.raw.videoFile);   
int si = mpl.getDuration();

This will give the duration of the video file

Rob
  • 26,989
  • 16
  • 82
  • 98
aakash dua
  • 19
  • 2
  • 3
    MediaPlayer.create is a heavy method, MediaMetadataRetriever suggested by "vir us" seems more suitable. – Hrk Jan 21 '18 at 19:11
0
object MediaHelper {

    const val PICK_IMAGE_FROM_DEVICE = 100
    const val PICK_MEDIA_FROM_DEVICE = 101

    fun openPhoneGalleryForImage(fragment: Fragment){
        Intent(Intent.ACTION_GET_CONTENT).run {
            this.type = "image/*"
            fragment.startActivityForResult(this, PICK_IMAGE_FROM_DEVICE)
        }
    }

    fun openPhoneGalleryForMedia(fragment: Fragment){
        Intent(Intent.ACTION_GET_CONTENT).run {
            this.type = "*/*"
            fragment.startActivityForResult(this, PICK_MEDIA_FROM_DEVICE)
        }
    }

    fun getMediaType(context: Context, source: Uri): MediaType? {
        val mediaTypeRaw = context.contentResolver.getType(source)
        if (mediaTypeRaw?.startsWith("image") == true)
            return MediaType.Image
        if (mediaTypeRaw?.startsWith("video") == true)
            return MediaType.Video
        return null
    }

    fun getVideoDuration(context: Context, source: Uri): Long? {
        if (getMediaType(context, source) != MediaType.Video) 
            return null
        val retriever = MediaMetadataRetriever()
        retriever.setDataSource(context, source)
        val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
        retriever.release()
        return duration?.toLongOrNull()
    }
}

enum class MediaType {
    Image {
        override val mimeType: String = "image/jpeg"
        override val fileExtension: String = ".jpg"
    },
    Video {
        override val mimeType: String = "video/mp4"
        override val fileExtension: String = ".mp4"
    };

    abstract val mimeType: String
    abstract val fileExtension: String
}
Konstantin Konopko
  • 5,229
  • 4
  • 36
  • 62
0
fun File.getVideoDuration(context: Context): Long {
    context.contentResolver.query(toUri(), arrayOf(MediaStore.Video.Media.DURATION), null, null, null)?.use {
        val durationColumn = it.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
        it.moveToFirst()
        return it.getLong(durationColumn)
    }
    return 0
Mohmmaed-Amleh
  • 383
  • 2
  • 11