如何在Android首选项中正确接收和存储本地目录/路径?

2024-05-09

我想存储一个本地路径(内部或外部存储),用户可以在其中存储一些数据作为 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) 

最后一行因权限错误而崩溃。


您无法创建文档Uri通过简单的字符串连接。反而:

  • Use DocumentFile.fromTreeUri()得到一个DocumentFile代表树

  • 关于这一点,请致电createFile()得到一个DocumentFile代表您想要创建的内容

  • 对此,call getUri() https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile#getUri()得到Uri与使用openOutputStream()

您仍然需要takePersistableUriPermissions()如果您希望能够创建文档和子树,请调用树。

默认文件夹是 context.externalMediaDirs,它返回一个 File 对象,我将其绝对路径存储在 SharedPreferences 中。稍后,当用户保存数据时,数据将通过 FileOutputStream 正确存储到该文件夹​​中新创建的文件中。

如果您使用数组中的第 0 个索引,这可能会成立。其他代表可移动存储,如果用户更换其可移动存储(例如交换微型 SD 卡),其目录名称可能会更改。只有内置外部存储上的目录是稳定的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android首选项中正确接收和存储本地目录/路径? 的相关文章

随机推荐