无法再次将 Uri 转换为 String 并将 String 转换为 Uri
Can't convert Uri to String and String to Uri again
我正在开发音乐播放器,想使用存储访问框架来访问存储中的文件。为此,我使用了 Intent.ACTION_OPEN_DOCUMENT_TREE
和 contentResolver.takePersistableUriPermission(...)
。但是一旦我获得了权限,我就必须存储允许的路径,所以我为此使用 SharedPreferences
。
当我将从 Intent.ACTION_OPEN_DOCUMENT_TREE
获得的 URI 转换为字符串以重用它时,它给了我一个 nullPointerException
(它说我从首选项中转换字符串得到的 URI 是 null
).
虽然如果我使用相同的 URI 而没有保存到 SharedPreferences
,它工作得很好。
代码如下:
package com.gaurav712.music
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.documentfile.provider.DocumentFile
class MainActivity : AppCompatActivity() {
private val openDocumentTreeRequestCode: Int = 40
private lateinit var setPreferences: SharedPreferences
private lateinit var rootUri: Uri
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setPreferences = getPreferences(Context.MODE_PRIVATE)
// Check if access to storage is permitted
checkAccess()
// Now that we have access to storage, set the root Uri
rootUri = Uri.parse(setPreferences.getString("allowed_path", ""))
Log.i("rootUri", rootUri.toString())
// listFiles()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == openDocumentTreeRequestCode && resultCode == RESULT_OK) {
val treeUri = data?.data // get data
if (treeUri != null) {
contentResolver.takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
val editor = setPreferences.edit()
editor.putBoolean("got_permissions", true)
editor.putString("allowed_path", treeUri?.toString())
editor.apply()
Log.i("treeUri", treeUri.toString())
val documentFile = treeUri?.let { DocumentFile.fromTreeUri(this, it) }
for (file in documentFile?.listFiles()!!) {
file.name?.let { Log.i("file: ", it) }
}
}
}
private fun checkAccess() {
val gotPermission: Boolean = setPreferences.getBoolean("got_permissions", false)
if (!gotPermission)
getAccess()
else
Log.i("got_permissions",
gotPermission.toString()
+ " : "
+ setPreferences.getString("allowed_path", ""))
}
private fun getAccess() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, openDocumentTreeRequestCode)
}
private fun listFiles() {
val documentFile: DocumentFile = DocumentFile.fromTreeUri(this, rootUri)!!
for (file in documentFile.listFiles()) {
Log.i("file: ", file.name.toString())
}
}
}
在 onCreate()
中,如果我取消注释 listFiles()
,它会给出 nullPointerException
但使用与上面 onActivityResult()
中相同的代码块,一切正常.我正在谈论的块:
val documentFile = treeUri?.let { DocumentFile.fromTreeUri(this, it) }
for (file in documentFile?.listFiles()!!) {
file.name?.let { Log.i("file: ", it) }
}
我不明白为什么它说 rootUri
是空的。
我看了所有类似 this one 的问题。我正在使用建议的相同函数(toString()
和 Uri.parse
)进行转换,但它似乎不适用于存储访问框架。
我解决了!函数 getAccess()
应该是:
private fun getAccess() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
}
startActivityForResult(intent, openDocumentTreeRequestCode)
}
我在意图中缺少 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
标记。
我正在开发音乐播放器,想使用存储访问框架来访问存储中的文件。为此,我使用了 Intent.ACTION_OPEN_DOCUMENT_TREE
和 contentResolver.takePersistableUriPermission(...)
。但是一旦我获得了权限,我就必须存储允许的路径,所以我为此使用 SharedPreferences
。
当我将从 Intent.ACTION_OPEN_DOCUMENT_TREE
获得的 URI 转换为字符串以重用它时,它给了我一个 nullPointerException
(它说我从首选项中转换字符串得到的 URI 是 null
).
虽然如果我使用相同的 URI 而没有保存到 SharedPreferences
,它工作得很好。
代码如下:
package com.gaurav712.music
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.documentfile.provider.DocumentFile
class MainActivity : AppCompatActivity() {
private val openDocumentTreeRequestCode: Int = 40
private lateinit var setPreferences: SharedPreferences
private lateinit var rootUri: Uri
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setPreferences = getPreferences(Context.MODE_PRIVATE)
// Check if access to storage is permitted
checkAccess()
// Now that we have access to storage, set the root Uri
rootUri = Uri.parse(setPreferences.getString("allowed_path", ""))
Log.i("rootUri", rootUri.toString())
// listFiles()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == openDocumentTreeRequestCode && resultCode == RESULT_OK) {
val treeUri = data?.data // get data
if (treeUri != null) {
contentResolver.takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
val editor = setPreferences.edit()
editor.putBoolean("got_permissions", true)
editor.putString("allowed_path", treeUri?.toString())
editor.apply()
Log.i("treeUri", treeUri.toString())
val documentFile = treeUri?.let { DocumentFile.fromTreeUri(this, it) }
for (file in documentFile?.listFiles()!!) {
file.name?.let { Log.i("file: ", it) }
}
}
}
private fun checkAccess() {
val gotPermission: Boolean = setPreferences.getBoolean("got_permissions", false)
if (!gotPermission)
getAccess()
else
Log.i("got_permissions",
gotPermission.toString()
+ " : "
+ setPreferences.getString("allowed_path", ""))
}
private fun getAccess() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, openDocumentTreeRequestCode)
}
private fun listFiles() {
val documentFile: DocumentFile = DocumentFile.fromTreeUri(this, rootUri)!!
for (file in documentFile.listFiles()) {
Log.i("file: ", file.name.toString())
}
}
}
在 onCreate()
中,如果我取消注释 listFiles()
,它会给出 nullPointerException
但使用与上面 onActivityResult()
中相同的代码块,一切正常.我正在谈论的块:
val documentFile = treeUri?.let { DocumentFile.fromTreeUri(this, it) }
for (file in documentFile?.listFiles()!!) {
file.name?.let { Log.i("file: ", it) }
}
我不明白为什么它说 rootUri
是空的。
我看了所有类似 this one 的问题。我正在使用建议的相同函数(toString()
和 Uri.parse
)进行转换,但它似乎不适用于存储访问框架。
我解决了!函数 getAccess()
应该是:
private fun getAccess() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
}
startActivityForResult(intent, openDocumentTreeRequestCode)
}
我在意图中缺少 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
标记。