无法从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.
相关产品推荐
相关产品推荐

