我想存储一个本地路径(内部或外部存储),用户可以在其中存储一些数据作为 Android 应用程序中的首选项。我希望用户在首选项中选择一个首选文件夹。默认文件夹是context.externalMediaDirs
它返回一个File
我将其绝对路径存储为 SharedPreferences 中的字符串的对象。稍后,当用户保存数据时,数据将通过 FileOutputStream 正确存储到该文件夹中新创建的文件中。
现在,我在首选项中添加了 OPEN_DOCUMENT_TREE 的意图,以便用户可以选择不同的文件夹。但意图返回格式为 URIcontent://com.android.externalstorage.documents/...
我将其存储为字符串,但是当我尝试通过 context.contentResolver.openOutputStream() 写入文件时,出现错误,指出我需要 MANAGE_DOCUMENTS 权限。但这仅适用于系统应用程序。
我找到了如何将 URI 转换为本地路径的解决方案,但总是有人指出这是 hacky,不应该这样做。我试过contentResolver.takePersistableUriPermission(...)
但一切都没有改变。
那么从用户那里接收文件夹、将其存储在首选项中并能够在那里创建新文件的正确方法是什么?
编辑:
目前的方法
首选项 XML(摘录):
<Preference
app:key="target_dir">
<intent android:action="android.intent.action.OPEN_DOCUMENT_TREE"/>
</Preference>
调用意图
val targetDirPreference: Preference? = findPreference("target_dir")
targetDirPreference?.setOnPreferenceClickListener {
startActivityForResult(it.intent, REQUEST_TARGET_FOLDER)
true
}
结果处理(根据 blackapps 请求进行更改,不包含共享首选项,而仅创建文件)
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
if ((requestCode == REQUEST_TARGET_FOLDER ) && resultCode == RESULT_OK && intent != null) {
//val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
//sharedPreferences.getString("target_dir", "")?.also {
// with(sharedPreferences.edit()) {
// putString("target_dir", intent.data.toString())
// commit()
// }
val newFile = Uri.parse("${intent.dataString}%2Ftest.png")
context?.contentResolver?.openOutputStream(newFile)
}
}
else {
super.onActivityResult(requestCode, resultCode, intent)
}
}
尝试在意图之后的某个时间(可能是几个小时)创建一个新文件
val targetDir = PreferenceManager.getDefaultSharedPreferences(context).getString("target_dir", null)
val targetFile = "${System.currentTimeMillis()}.png"
val uri = Uri.parse("$targetDir%2F$targetFile")
val stream = context.contentResolver.openOutputStream(uri)
最后一行因权限错误而崩溃。