gpt4 book ai didi

android - 为什么 ContentResolver 看不到其他应用添加的文件?

转载 作者:行者123 更新时间:2023-12-03 20:48:33 31 4
gpt4 key购买 nike

我将文件添加到 Documents/MyExcelsFolder通过使用 ContentResolver.insert然后还将新文件添加到 Documents/MyExcelsFolder另一个应用程序的文件夹(例如 FileManager )
然后我尝试从 MyExcelsFolder 获取所有文件文件夹

fun getAppFiles(context: Context): List<AppFile> {
val appFiles = mutableListOf<AppFile>()

val contentResolver = context.contentResolver
val columns = mutableListOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE
).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
add(
MediaStore.MediaColumns.RELATIVE_PATH
)
}
}.toTypedArray()
val extensions = listOf("xls", "xlsx")
val mimes = extensions.map { MimeTypeMap.getSingleton().getMimeTypeFromExtension(it) }

val selection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
"${MediaStore.MediaColumns.RELATIVE_PATH} LIKE ?"
} else {
"${MediaStore.Images.Media.DATA} LIKE ?"
}

val selectionArgs = arrayOf(
"%${Environment.DIRECTORY_DOCUMENTS}/MyExcelsFolder%"
)

contentResolver.query(
MediaStore.Files.getContentUri("external"),
columns,
selection,
selectionArgs,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
)?.use { cursor ->
while (cursor.moveToNext()) {
val pathColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val mimeColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
val filePath = cursor.getString(pathColumnIndex)
val mimeType = cursor.getString(mimeColumnIndex)
if (mimeType != null && mimes.contains(mimeType)) {
// handle cursor
appFiles.add(cursor.toAppFile())
} else {
// need to check extension, because the Mime Type is null
val extension = File(filePath).extension
if (extensions.contains(extension)) {
// handle cursor
appFiles.add(cursor.toAppFile())
}
}
}
}

return appFiles
}

fun Cursor.toAppFile(): AppFile {
val cursor = this

val idColumnIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)
val nameColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
val mimeColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
val pathColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)

val id = cursor.getLong(idColumnIndex)
val uri = ContentUris.withAppendedId(MediaStore.Files.getContentUri("external"), id)
val fileDisplayName = cursor.getString(nameColumnIndex)
val filePath = cursor.getString(pathColumnIndex)
var mimeType = cursor.getString(mimeColumnIndex)
val relativePath = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.RELATIVE_PATH))
} else {
null
}
var type = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
if (type == null) {
type = File(filePath).extension
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(type)
}
return AppFile(
id = id,
uri = uri,
absolutePath = filePath,
name = fileDisplayName,
mimeType = mimeType,
extension = type,
relativePath = relativePath
)
}
结果只有 ContentResolver 中的文件添加者 insert命令,并且文件管理器没有复制任何文件。如何查看 cursor 中的所有文件?
操作系统:Android 10 (Q) (API level 29)
目标 API 版本:api 29

最佳答案

从 Android 10 开始,有一个新的存储访问模型正在运行,称为 Scoped Storage而且限制性更强。简而言之:

  • 您的应用始终可以访问自己的目录。
  • 您的应用程序可以写入(在 ContentResolver.insert 的帮助下)到 the shared media收藏和只能读取您的应用程序创建的文件 从他们。您可以通过请求 READ_EXTERNAL_STORAGE 访问这些集合中的其他应用程序文件。允许。
  • 您的应用程序可以使用 file or directory system pickers 访问其他文件和目录.

  • 这有点奇怪,看起来像一个你可以访问的错误 xls文件通过 MediaStore.Files收藏。 The documentation

    The media store also includes a collection called MediaStore.Files.Its contents depend on whether your app uses scoped storage, availableon apps that target Android 10 or higher:

    If scoped storage is enabled, the collection shows only the photos,videos, and audio files that your app has created.

    If scoped storageis unavailable or not being used, the collection shows all types ofmedia files.


    但无论如何,您仍然无法访问上述其他应用程序创建的文件。
    因此,根据您的用例,有几个选项可供选择:
  • 通过 MediaStore.Files 访问文件现在为你工作,你可以尝试请求READ_EXTERNAL_STORAGE权限如this table获得对媒体收藏的非过滤访问。但我希望这种方式在不同的设备上不可靠地工作和/或希望停止它与新的更新一起工作,因为媒体集合应该只用于媒体文件。
  • 您可以使用 ACTION_OPEN_DOCUMENTACTION_OPEN_DOCUMENT_TREE向用户显示文件/目录选择器并访问文件或整个目录树。请查看the restrictions此法之也。我会说这是最好的方法。
  • Android 10 允许您 temporarily opt-out使用 android:requestLegacyExternalStorage 从作用域存储旗帜。但是 Android 11 已经发布了,这个标志在其中没有任何作用。
  • 您可以申请新的MANAGE_EXTERNAL_STORAGE许可,然后由用户向 access all files 请求特殊的白名单.这就是文件管理器现在的工作方式。此功能从 Android 11 开始可用,因此您可能会为 Android 10 使用选择退出标志。如果您要在那里发布您的应用,请务必检查使用此功能的限制和 Google Play 政策。
  • 关于android - 为什么 ContentResolver 看不到其他应用添加的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64276816/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com