You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法从FileProvider生成的Uri获取文件创建/最后修改日期怎么办?

从FileProvider的Uri获取文件创建/修改日期的解决方案

默认的FileProvider仅支持查询_display_name和_size两个元数据字段,要获取文件的最后修改日期或创建日期,需要自定义FileProvider子类来扩展查询支持的字段。以下是具体实现步骤:


1. 自定义FileProvider子类

重写query方法,在原有Cursor的基础上添加修改时间、创建时间字段:

import android.os.Build
import android.provider.MediaStore
import android.content.Context
import android.database.Cursor
import android.database.CursorWrapper
import android.net.Uri
import androidx.core.content.FileProvider
import java.io.File
import java.nio.file.Files

class CustomFileProvider : FileProvider() {
    override fun query(
        uri: Uri,
        projection: Array<String>?,
        selection: String?,
        selectionArgs: Array<String>?,
        sortOrder: String?
    ): Cursor? {
        val originalCursor = super.query(uri, projection, selection, selectionArgs, sortOrder)
        val targetFile = getFileForUri(uri) ?: return originalCursor

        // 准备额外的元数据字段(转成秒级时间戳)
        val extraMetadata = mutableMapOf(
            MediaStore.MediaColumns.DATE_MODIFIED to (targetFile.lastModified() / 1000),
            MediaStore.MediaColumns.DATE_ADDED to getCreationTimestamp(targetFile)
        )

        // 包装原始Cursor,添加额外字段
        return originalCursor?.let {
            object : CursorWrapper(it) {
                override fun getColumnIndex(columnName: String): Int {
                    val originalIndex = super.getColumnIndex(columnName)
                    return if (originalIndex != -1) {
                        originalIndex
                    } else {
                        extraMetadata.keys.indexOf(columnName) + super.getColumnCount()
                    }
                }

                override fun getColumnCount(): Int {
                    return super.getColumnCount() + extraMetadata.size
                }

                override fun getColumnName(columnIndex: Int): String {
                    val originalColumnCount = super.getColumnCount()
                    return if (columnIndex < originalColumnCount) {
                        super.getColumnName(columnIndex)
                    } else {
                        extraMetadata.keys.elementAt(columnIndex - originalColumnCount)
                    }
                }

                override fun getLong(columnIndex: Int): Long {
                    val originalColumnCount = super.getColumnCount()
                    return if (columnIndex < originalColumnCount) {
                        super.getLong(columnIndex)
                    } else {
                        extraMetadata.values.elementAt(columnIndex - originalColumnCount) as Long
                    }
                }
            }
        }
    }

    // 获取文件创建时间戳(秒级)
    private fun getCreationTimestamp(file: File): Long {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Files.getLastModifiedTime(file.toPath()).toMillis() / 1000
        } else {
            // Android 8.0及以下无统一API获取创建时间,用修改时间替代
            file.lastModified() / 1000
        }
    }
}

2. 替换Manifest中的FileProvider注册

将原有的androidx.core.content.FileProvider替换为自定义的CustomFileProvider:

<provider
    android:name=".CustomFileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

3. 查询扩展后的元数据字段

现在可以通过ContentResolver查询新增的DATE_MODIFIED和DATE_ADDED字段:

val fileUri = getUriForFile(this, "$packageName.fileprovider", targetFile)
val projection = arrayOf(
    MediaStore.MediaColumns._DISPLAY_NAME,
    MediaStore.MediaColumns._SIZE,
    MediaStore.MediaColumns.DATE_MODIFIED,
    MediaStore.MediaColumns.DATE_ADDED
)

contentResolver.query(fileUri, projection, null, null, null)?.use { cursor ->
    if (cursor.moveToFirst()) {
        val modifiedTimeMillis = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED)) * 1000
        val creationTimeMillis = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED)) * 1000
        // 处理时间数据
    }
}

注意事项

  • Android 8.0及以下系统没有统一的API获取文件创建时间,上述代码中用文件修改时间替代;若业务需要精确的创建时间,可在文件创建时自行记录到本地存储(如SharedPreferences、数据库),再通过Uri关联查询。
  • 自定义Provider时,getFileForUri是FileProvider的protected方法,可直接调用获取Uri对应的File对象。

内容的提问来源于stack exchange,提问作者Luke B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:57:17