MediaStore在Kotlin中无法列出手机内的所有视频。为什么?

5
我创建了一个函数来获取视频。
private val projectionVideo = arrayOf(
MediaStore.Video.Media._ID, //ID
MediaStore.Video.Media.DISPLAY_NAME, //NAME
MediaStore.Video.Media.DATA, //PATH TO CONTENT
MediaStore.Video.Media.DATE_TAKEN, //DATE
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.SIZE
)

private fun queryVideos(cr: ContentResolver): Cursor? =
        cr.query(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
            projectionVideo, null, null,
            MediaStore.Video.Media.DATE_TAKEN + " $SORT_ORDER"
        )

在Java中
public static Uri getContentUri(String volumeName) {
                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
                        "/video/media");
            }
            /**
             * The content:// style URI for the internal storage.
             */
            public static final Uri INTERNAL_CONTENT_URI =
                    getContentUri("internal");
            /**
             * The content:// style URI for the "primary" external storage
             * volume.
             */
            public static final Uri EXTERNAL_CONTENT_URI =
                    getContentUri("external");

问题在于默认相机应用程序创建的视频不会显示在任何路径中,例如“DCIM”、“WhatsApp 视频”等。使用我的应用程序创建的每个视频都将被正确插入,但默认相机应用程序创建的视频除非我先打开它们,否则不会被正确插入。
2个回答

1
fun getAllVideos(): ArrayList<FileGallery>? {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            var columnVideo:Int ?= null
            var columnFolder:Int ?= null
            var columnDateAdded:Int ?= null

            var absolutePathVideo:String ?= null
            var folderName:String ?= null
            var dateAdded:String ?= null

            val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
            val projection = arrayOf(
                MediaStore.Video.Media.DATA,
                MediaStore.Video.VideoColumns.DATE_ADDED,
                MediaStore.Video.Media.BUCKET_DISPLAY_NAME
            )

            val orderBy:String = MediaStore.Video.Media.DATE_TAKEN

            val cursor = context.contentResolver.query(
                uri,
                projection,
                null,
                null,
                "$orderBy DESC"
            )

            var listVideo = arrayListOf<FileGallery>()

            columnVideo = cursor?.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
            columnFolder = cursor?.getColumnIndexOrThrow(MediaStore.Video.Media.BUCKET_DISPLAY_NAME)
            columnDateAdded = cursor?.getColumnIndexOrThrow(MediaStore.Video.VideoColumns.DATE_ADDED)

            while (cursor?.moveToNext() == true){
                absolutePathVideo = cursor.getString(columnVideo!!)
                folderName = cursor.getString(columnFolder!!)
                dateAdded = cursor.getString(columnDateAdded!!)
                listVideo.add(FileGallery(absolutePathVideo, folderName, dateAdded))
            }
            return listVideo
        }else{
            return null
        }
    }catch (e:Exception){
        Log.e("ERROR", e.message?:"")
        return null
    }
}

试一下这个


0

你可以使用以下代码读取Android Shared Storage中的所有视频

    private val videoProjection = arrayOf(
               MediaStore.Video.Media._ID,
               MediaStore.Video.Media.DATA,
               MediaStore.Video.Media.DURATION,
               MediaStore.Video.Media.MIME_TYPE,
               MediaStore.Video.Media.SIZE,
               MediaStore.Video.Media.DATE_ADDED)


    context.contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
            videoProjection,
            null,
            null,
            "${MediaStore.Video.Media.DATE_ADDED} DESC"
    )?.use { cursor ->
        while (cursor.moveToNext()) {
           //read video attr from cursor
           cursor.getLong(cursor.getColumnIndexOrThrow(videoProjection[0])) // read video id 
           cursor.getString(cursor.getColumnIndexOrThrow(videoProjection[1])) // read video path 
           // and .....
        }
    }

有什么区别吗?这不会改变任何行为。 - Kred
将“Nothing but you”按“datetaken(DATE_TAKEN)”排序,而我则按“date_added(DATE_ADDED)”排序。你使用投影中的DATE_TAKEN,而我使用了DATE_ADDED。我在生产中使用此代码,在所有Android版本中都运行良好,但如果您的Android版本为10,请阅读Android 10隐私更改 - Mehdi Yari
排序不是主要问题。有没有关于如何显示设备内所有视频的想法? - Kred
抱歉,如果我无法在这种情况下提供帮助,但我之前说过,此代码获取设备(在mediaStore中)的所有视频,并且我已经在生产中使用此代码多年。您能否提供有关您的情况的更多信息,例如Android版本或设备型号或运行此代码时收到的错误? - Mehdi Yari
我弄清楚了:无论排序方法如何,在这两种情况下,查询函数都能正常工作,它会获取正确数量的视频;问题是需要缩略图来链接视频的条件。我应该为每个没有缩略图路径的视频创建一个位图,通过ThumbnailUtils实现。 - Kred
1
@MehdiYari 请注意,从 android 11 开始,DATE_ADDED 将不再起作用,您必须使用 DATE_TAKEN。因此,基本上您的答案是正确的,但对于 android 11 来说不适用(对我来说它可以工作,但有时 cursor.getString(dateTakenColumn) 会抛出空指针异常)! - Vivek Thummar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接