Android 为什么ContentResolver看不到其他应用添加的文件?
我使用Android 为什么ContentResolver看不到其他应用添加的文件?,android,file,uri,android-contentresolver,file-manager,Android,File,Uri,Android Contentresolver,File Manager,我使用ContentResolver.insert将文件添加到Documents/MyExcelsFolder,然后还通过另一个应用程序将新文件添加到Documents/MyExcelsFolder文件夹(例如FileManager) 然后我尝试从MyExcelsFolder文件夹中获取所有文件 fun getAppFiles(context: Context): List<AppFile> { val appFiles = mutableListOf<AppF
ContentResolver.insert将文件添加到Documents/MyExcelsFolder
,然后还通过另一个应用程序将新文件添加到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
)
}
fun getAppFiles(context:context):列表{
val appFiles=mutableListOf()
val contentResolver=context.contentResolver
val columns=mutableListOf(
MediaStore.Images.Media.\u ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_已添加,
MediaStore.Images.Media.DISPLAY\u名称,
MediaStore.Images.Media.MIME_类型
).申请{
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.Q){
加(
MediaStore.MediaColumns.RELATIVE_路径
)
}
}.toTypedArray()
val扩展=列表(“xls”、“xlsx”)
val mimes=extensions.map{MimeTypeMap.getSingleton().getMimeTypeFromExtension(it)}
val selection=if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.Q){
“${MediaStore.MediaColumns.RELATIVE_PATH}类似吗?”
}否则{
“${MediaStore.Images.Media.DATA}类似吗?”
}
val selectionArgs=arrayOf(
“%${Environment.DIRECTORY_DOCUMENTS}/MyExcelsFolder%”
)
contentResolver.query(
MediaStore.Files.getContentUri(“外部”),
柱,
选择,
精选,
MediaStore.Files.FileColumns.DATE_添加+“DESC”
)?使用{游标->
while(cursor.moveToNext()){
val pathColumnIndex=cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val mimeColumnIndex=cursor.getColumnIndex(MediaStore.Images.Media.MIME_类型)
val filePath=cursor.getString(pathColumnIndex)
val mimeType=cursor.getString(mimeColumnIndex)
if(mimeType!=null&&mimes.contains(mimeType)){
//手柄光标
appFiles.add(cursor.toAppFile())
}否则{
//需要检查扩展名,因为Mime类型为空
val扩展名=文件(filePath).extension
if(extensions.contains(extension)){
//手柄光标
appFiles.add(cursor.toAppFile())
}
}
}
}
返回应用程序文件
}
fun Cursor.toAppFile():AppFile{
val cursor=这个
val idColumnIndex=cursor.getColumnIndex(MediaStore.Images.ImageColumns.\u ID)
val nameColumnIndex=cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
val mimeColumnIndex=cursor.getColumnIndex(MediaStore.Images.Media.MIME_类型)
val pathColumnIndex=cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val id=cursor.getLong(idColumnIndex)
val uri=ContentUris.withAppendedId(MediaStore.Files.getContentUri(“外部”),id)
val fileDisplayName=cursor.getString(nameColumnIndex)
val filePath=cursor.getString(pathColumnIndex)
var mimeType=cursor.getString(mimeColumnIndex)
val relativePath=if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.Q){
cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.RELATIVE_PATH))
}否则{
无效的
}
var type=MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
if(type==null){
类型=文件(filePath).extension
mimeType=MimeTypeMap.getSingleton().getMimeTypeFromExtension(类型)
}
返回应用文件(
id=id,
uri=uri,
绝对路径=文件路径,
name=fileDisplayName,
mimeType=mimeType,
扩展=类型,
相对路径=相对路径
)
}
结果,只有来自ContentResolver
的文件是通过insert
命令添加的,并且没有文件管理器复制的文件。如何在光标中查看所有文件
操作系统:安卓10(Q)(API级别29)
目标API版本:API 29从Android 10开始,有一个新的存储访问模型正在运行,它被调用,限制性更强。简言之:
您的应用程序始终可以访问自己的目录
您的应用程序可以(借助ContentResolver.insert
)写入集合,并且可以从集合中读取应用程序创建的文件。通过请求READ\u EXTERNAL\u STORAGE
权限,您可以访问这些集合中的其他应用程序文件
您的应用程序可以使用访问其他文件和目录
这有点奇怪,看起来像是一个bug,您可以通过MediaStore.files
集合访问xls
文件。说
媒体存储还包括一个名为MediaStore.Files
的集合。
其内容取决于您的应用程序是否使用范围存储(可用)
在针对Android 10或更高版本的应用程序上:
如果启用了作用域存储,则集合仅显示照片,
应用程序创建的视频和音频文件
If作用域存储
不可用或未使用,集合显示所有类型的
媒体文件
但无论如何,您仍然无法访问由上述其他应用程序创建的文件。
因此,根据您的用例,有几个选项可供选择:
由于通过MediaStore.files
访问文件现在对您有效,您可以尝试请求READ\u EXTERNAL\u STORAGE
权限,如中所示,以获得对媒体收藏的非筛选访问权限。但我希望这种方式在不同的设备上不可靠地工作,并且/或者在新的更新中停止工作,因为媒体收藏应该只用于媒体文件
你