问题描述
还有其他人发现范围存储几乎不可能开始工作吗?大声笑.
Anyone else finding scoped-storage near-impossible to get working? lol.
我一直在尝试了解如何允许用户向我的应用授予对应用文件夹以外的文本文件的写权限. (比方说,允许用户在其文档"文件夹中编辑文件的文本).我已经设置了MANAGE_EXTERNAL_STORAGE
权限,并且可以确认该应用程序具有该权限.但是还是每次我尝试
I've been trying to understand how to allow the user to give my app write permissions to a text file outside of the app's folder. (Let's say allow a user to edit the text of a file in their Documents folder). I have the MANAGE_EXTERNAL_STORAGE
permission all set up and can confirm that the app has the permission. But still every time I try
val fileDescriptor = context.contentResolver.openFileDescriptor(uri, "rwt")?.fileDescriptor
我收到Illegal Argument: Media is read-only
错误.
我的清单请求这三个权限:
My manifest requests these three permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
我也尝试过使用旧版存储:
I've also tried using legacy storage:
<application
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
但仍然遇到此只读问题.
But still running into this read-only issue.
我想念什么?
更多说明
我如何获取URI:
view?.selectFileButton?.setOnClickListener {
val intent =
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
}
startActivityForResult(Intent.createChooser(intent, "Select a file"), 111)
}
然后
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 111 && resultCode == AppCompatActivity.RESULT_OK && data != null) {
val selectedFileUri = data.data;
if (selectedFileUri != null) {
viewModel.saveFilename(selectedFileUri.toString())
val contentResolver = context!!.contentResolver
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(selectedFileUri, takeFlags)
view?.fileName?.text = viewModel.filename
//TODO("if we didn't get the permissions we needed, ask for permission or have the user select a different file")
}
}
}
推荐答案
您可以尝试下面的代码.它对我有用.
You may try the code below. It works for me.
class MainActivity : AppCompatActivity() {
private lateinit var theTextOfFile: TextView
private lateinit var inputText: EditText
private lateinit var saveBtn: Button
private lateinit var readBtn: Button
private lateinit var deleteBtn: Button
private lateinit var someText: String
private val filename = "theFile.txt"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (!isPermissionGranted()) {
val permissions = arrayOf(WRITE_EXTERNAL_STORAGE)
for (i in permissions.indices) {
requestPermission(permissions[i], i)
}
}
theTextOfFile = findViewById(R.id.theTextOfFile)
inputText = findViewById(R.id.inputText)
saveBtn = findViewById(R.id.saveBtn)
readBtn = findViewById(R.id.readBtn)
deleteBtn = findViewById(R.id.deleteBtn)
saveBtn.setOnClickListener { savingFunction() }
deleteBtn.setOnClickListener { deleteFunction() }
readBtn.setOnClickListener {
theTextOfFile.text = readFile()
}
}
private fun readFile() : String{
val rootPath = "/storage/emulated/0/Download/"
val myFile = File(rootPath, filename)
return if (myFile.exists()) {
FileInputStream(myFile).bufferedReader().use { it.readText() }
}
else "no file"
}
private fun deleteFunction(){
val rootPath = "/storage/emulated/0/Download/"
val myFile = File(rootPath, filename)
if (myFile.exists()) {
myFile.delete()
}
}
private fun savingFunction(){
deleteFunction()
someText = inputText.text.toString()
val resolver = applicationContext.contentResolver
val values = ContentValues()
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
val uri = resolver.insert(MediaStore.Files.getContentUri("external"), values)
uri?.let { it ->
resolver.openOutputStream(it).use {
// Write file
it?.write(someText.toByteArray(Charset.defaultCharset()))
it?.close()
}
}
} else {
val rootPath = "/storage/emulated/0/Download/"
val myFile = File(rootPath, filename)
val outputStream: FileOutputStream
try {
if (myFile.createNewFile()) {
outputStream = FileOutputStream(myFile, true)
outputStream.write(someText.toByteArray())
outputStream.flush()
outputStream.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
private fun isPermissionGranted(): Boolean {
val permissionCheck = ActivityCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE)
return permissionCheck == PackageManager.PERMISSION_GRANTED
}
private fun requestPermission(permission: String, requestCode: Int) {
ActivityCompat.requestPermissions(this, arrayOf(permission), requestCode)
}
}
这篇关于写入权限不起作用-范围存储Android SDK 30(又名Android 11)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!