最近又在扮演合规工程师觉得。
华为应用市场把公司应用下架了,原因是权限申请时,没有明确的解释说明权限的用途。
大概就是下面这样,在顶部弄个权限说明![在这里插入图片描述]
好吧,看了一眼几个大厂的App,确实是做了提示。行, 那就改吧。
看了之前的代码,使用的是第三方的库实现,已经无法再Android API 30后的版本了,只能另外实现。
但是既然系统有自带的文件选择器,那就用系统的吧,没有必要自己实现,麻烦。用第三方库有怕更新不及时,出现一些问题修复不及时。还是用系统的靠谱,没有 UI 的要求,能用就行。
private fun onPickDoc() {
generateActivityResultContract(
Intent(Intent.ACTION_GET_CONTENT).apply {
type = "*"
addCategory(Intent.CATEGORY_OPENABLE)
},
) { code, intent ->
intent?.data?.takeIf { code == Activity.RESULT_OK }
}.let {
startActivityForResult(it) { uri ->
uri ?: return@startActivityForResult
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
lastPdfName = if (cursor.count > 0) {
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.getString(nameIndex)
} else {
uri.path?.let { it1 -> File(it1).name }
}
// 这里有坑
uploadFile(FileUtils.copyFile(this, uri, "pdf", lastPdfName ?: "pdf"))
}
}
}
}
在注释的地方有个问题,就是在进行上传的时候,会报错没有文件访问权限。
但是我的已经是Androi 14(API 34)了,已经没有"android.permission.WRITE_EXTERNAL_STORAGE"权限,而且已经申请了下面三个权限:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
既然权限都申请了,居然还会报错无法访问文件!
后面怀疑是不是从拿到的Uri获取的路径不对,然后各种尝试拿到真实的文件地址。
最后呢拿到真实地址了,结果还是一样,无法读取文件数据,报错没有权限。
一天后才想到,应该是这个文件可能出现在任何位置,我们的App虽然拿到了地址,但是在上传的时候,第三方SDK在处理这个文件地址时,应该没有权限去访问。
所以,只要把文件拷贝到我们App内data下的目录下,应该就有访问权限了。访问这个我们自己的目录是不需要权限的。
object FileUtils {
fun copyFile(context: Context, sourceUri: Uri, folderPath: String, fileName: String): String? {
val contentResolver: ContentResolver = context.contentResolver
return try {
val folder = File(App.instance.externalCacheDir, folderPath)
if (!folder.mkdirs() && (!folder.exists() || !folder.isDirectory)) {
return null
}
val destinationFile = File(folder, fileName)
contentResolver.openInputStream(sourceUri)?.use { input ->
destinationFile.outputStream().use { output ->
input.copyTo(output, DEFAULT_BUFFER_SIZE)
}
}
destinationFile.absolutePath
} catch (e: IOException) {
null
}
}
}
最后运行代码,确实解决了文件访问问题。