gpt4 book ai didi

android - 访问 ActivityResult 上的公共(public)下载文件 Android 28 Samsung Galaxy S9+ (Verizon)

转载 作者:IT老高 更新时间:2023-10-28 13:45:29 25 4
gpt4 key购买 nike


UPDATE

我有一台运行 8.0.0 T-Mobile 的三星 Galaxy S8+,它运行良好 8.0.0

我的三星 Galaxy S9+ 运行 8.0.0 Verizon,每次都因非法参数而失败。

我的三星 Galaxy S9+ 运行 8.0.0 T-Mobile 没有任何问题并且工作正常

所以这可能是 OEM 特定型号问题,但不是 确定如何修复它。我也试过重启手机,不行 结果的变化。

另外,我从 Evernote 中打开了公共(public)下载并保存了 文件作为笔记的附件,告诉我 Evernote 可以 访问公共(public)目录就好了并附加文件,所以它是 可以在设备上进行。让我相信这是代码 相关。


所以我最近升级了一个运行良好的项目,现在它有一个错误,因为它正在使用构建工具 28 进行编译,适用于最新版本的 Android。

所以我一直使用这个 PathUtil 从隐式 Intent 中获取我需要的文件路径,以从用户那里获取文件选择。我将在下面分享一个我使用了很长时间的代码的链接。

PathUtil

它只是一个实用程序类,用于检查提供者权限并获取您尝试读取的文件的绝对路径。

当用户从公共(public)下载目录中选择一个文件时,它会返回到 onActivityResult 并显示:

content://com.android.providers.downloads.documents/document/2025

现在 nice 实用程序解析出来并告诉我这是一个下载目录文件,并且是一个 ID 为 2025 的文档。感谢实用程序,这是一个很好的开始。

Next up is to use the content resolver to find the file absolute path. This is what used to work, but no longer does :(.

现在,路径实用程序仅使用他们最有可能从核心库自己获得的合约数据。我尝试导入提供程序类以避免静态字符串,但它似乎不可用,所以我想简单地使用匹配字符串是目前最好的方法。

这里是核心 DownloadProvider 供引用,它为内容解析器提供所有访问权限。 DownloadProvider

NOTE* This DownloadProvider is Androids, not mine

这是为 contentProvider 构建 Uri 的代码

 val id = DocumentsContract.getDocumentId(uri)
val contentUri = ContentUris.withAppendedId(Uri.parse(PUBLIC_DOWNLOAD_PATH), id.toLong())
return getDataColumn(context, contentUri, null, null)

调用引用:

    private fun getDataColumn(context: Context, uri: Uri, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val column_index = cursor.getColumnIndexOrThrow(column)
return cursor.getString(column_index)
}
}catch (ex: Exception){
A35Log.e("PathUtils", "Error getting uri for cursor to read file: ${ex.message}")
} finally {
if (cursor != null)
cursor.close()
}
return null
}

基本上要解析的 contentUri 最终是

content://downloads/public_downloads/2025

然后当你调用它抛出的查询方法时:

java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/2025

我已经确认或尝试过的事情

  1. 读取外部权限(附带写入,但还是这样做了)
  2. 写入外部权限
  3. 权限在 list 中并在运行时检索
  4. 我选择了多个不同的文件,看看其中一个是否奇怪
  5. 我已确认已在应用设置中授予权限
  6. 我已将 Uri 硬编码为/1 甚至/#2052,以尝试各种结尾类型
  7. 我研究了核心库上的 uriMatching,以了解它期望它的格式并确保它匹配
  8. 我玩过 uri 中的 all_downloads 目录并解决了!!,但存在安全异常,因此解析器必须存在。

我不知道还有什么可以尝试的,任何帮助将不胜感激。

最佳答案

所以我仍然需要做一些向后兼容的测试,但经过数小时的反复试验,我已经成功解决了我自己的问题。

我的解决方法是修改getPath的isDownloadDirectory路径流程。我还不知道所有的链式 react ,因为质量保证明天就要开始了,如果我从中学到任何新东西,我会更新。

使用直接 URI 获取文件名的 contentResolver(注意*这不是获取文件名的好方法,除非您确定它是根据 Google 确定的本地文件,但对我来说,我确定它已下载.)

然后接下来使用环境外部公共(public)下载常量结合返回的内容解析器名称来获取您的绝对路径。新代码如下所示。

private val PUBLIC_DOWNLOAD_PATH = "content://downloads/public_downloads"
private val EXTERNAL_STORAGE_DOCUMENTS_PATH = "com.android.externalstorage.documents"
private val DOWNLOAD_DOCUMENTS_PATH = "com.android.providers.downloads.documents"
private val MEDIA_DOCUMENTS_PATH = "com.android.providers.media.documents"
private val PHOTO_CONTENTS_PATH = "com.google.android.apps.photos.content"

//HELPER METHODS
private fun isExternalStorageDocument(uri: Uri): Boolean {
return EXTERNAL_STORAGE_DOCUMENTS_PATH == uri.authority
}
private fun isDownloadsDocument(uri: Uri): Boolean {
return DOWNLOAD_DOCUMENTS_PATH == uri.authority
}
private fun isMediaDocument(uri: Uri): Boolean {
return MEDIA_DOCUMENTS_PATH == uri.authority
}
private fun isGooglePhotosUri(uri: Uri): Boolean {
return PHOTO_CONTENTS_PATH == uri.authority
}

fun getPath(context: Context, uri: Uri): String? {
if (DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(COLON.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
val storageDefinition: String
if (PRIMARY_LABEL.equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + FORWARD_SLASH + split[1]
} else {
if (Environment.isExternalStorageRemovable()) {
storageDefinition = EXTERNAL_STORAGE
} else {
storageDefinition = SECONDARY_STORAGE
}
return System.getenv(storageDefinition) + FORWARD_SLASH + split[1]
}
} else if (isDownloadsDocument(uri)) {
//val id = DocumentsContract.getDocumentId(uri) //MAY HAVE TO USE FOR OLDER PHONES, HAVE TO TEST WITH REGRESSION MODELS
//val contentUri = ContentUris.withAppendedId(Uri.parse(PUBLIC_DOWNLOAD_PATH), id.toLong()) //SAME NOTE AS ABOVE
val fileName = getDataColumn(context, uri, null, null)
var uriToReturn: String? = null
if(fileName != null){
uriToReturn = Uri.withAppendedPath(Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath), fileName).toString()
}
return uriToReturn
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(COLON.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if (IMAGE_PATH == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if (VIDEO_PATH == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if (AUDIO_PATH == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri!!, selection, selectionArgs)
}
} else if (CONTENT.equals(uri.scheme, ignoreCase = true)) {
return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null)
} else if (FILE.equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
return null
}




private fun getDataColumn(context: Context, uri: Uri, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
//val column = "_data" REMOVED IN FAVOR OF NULL FOR ALL
//val projection = arrayOf(column) REMOVED IN FAVOR OF PROJECTION FOR ALL
try {
cursor = context.contentResolver.query(uri, null, selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndexOrThrow(DocumentsContract.Document.COLUMN_DISPLAY_NAME) //_display_name
return cursor.getString(columnIndex) //returns file name
}
}catch (ex: Exception){
A35Log.e(SSGlobals.SEARCH_STRING + "PathUtils", "Error getting uri for cursor to read file: ${ex.message}")
} finally {
if (cursor != null)
cursor.close()
}
return null
}

关于android - 访问 ActivityResult 上的公共(public)下载文件 Android 28 Samsung Galaxy S9+ (Verizon),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52750508/

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