[英]Persistable permissions URI android Q
我正在使用模擬器並以這種方式發送意圖:
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Intent i;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
i = sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent();
} else {
return null;
}
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
在onActivityResult()
:
Uri uri = data.getData();
if (uri == null)
return null;
context.getContentResolver()
.takePersistableUriPermission(uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
每次我重新啟動時,該應用程序都無權訪問。 任何人都可以在模擬器上的 beta 6 上確認這個錯誤嗎? 我做錯了什么嗎?
我將您的代碼片段轉換為此 Kotlin 活動:
package com.commonsware.jetpack.myapplication
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import android.os.storage.StorageManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.documentfile.provider.DocumentFile
private const val PREF_URI = "uri"
private const val REQUEST_SAF = 1337
class MainActivity : AppCompatActivity() {
private val prefs: SharedPreferences by lazy {
getSharedPreferences("test", Context.MODE_PRIVATE)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val uriString = prefs.getString(PREF_URI, null)
val storageManager = getSystemService(StorageManager::class.java)!!
if (uriString == null) {
startActivityForResult(
storageManager.primaryStorageVolume.createOpenDocumentTreeIntent(),
REQUEST_SAF
)
} else {
val uri = Uri.parse(uriString)
val docFile = DocumentFile.fromTreeUri(this, uri)
Toast.makeText(
this,
"canRead: ${docFile?.canRead()} canWrite: ${docFile?.canWrite()}",
Toast.LENGTH_LONG
).show()
}
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
val uri = data?.data
if (uri == null) {
Toast.makeText(this, "Did not get a Uri??!?", Toast.LENGTH_LONG).show()
} else {
contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
prefs.edit().putString(PREF_URI, uri.toString()).apply()
Toast.makeText(this, "OK, run the activity again", Toast.LENGTH_LONG).show()
}
finish()
}
}
然后我運行包含此活動的應用程序作為其啟動器活動,並選擇Downloads/
作為文檔樹。 此活動的后續啟動 - 在重新啟動之前和之后 - 顯示canRead()
和canWrite()
都返回true
。 這是在運行 Q Beta 6 的 Google Pixel 上進行測試的。
由於 Google ,我無法在 Q 模擬器上嘗試此操作,因此我無法確認是否可以在那里重現您的行為。 但是,這在硬件上按預期工作的事實應該是一個積極的信號。
對於那些欣賞已接受答案但不想使用startActivityForResult
,在接受原始答案后已棄用。
我的示例展示了如何從您的應用程序中將文件保存到存儲中。
首先,創建一個類范圍的變量來保存ActivityResultLauncher
信息:
private lateinit var saveDataResultLauncher: ActivityResultLauncher<String>
然后,您可以將其放在MainActivity
的onCreate
fun 中,而不是使用已棄用的功能:
/** Backup Website Entries */
saveDataResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument()) {}
在按下與上面實現的功能綁定的菜單項后,讓用戶選擇一個位置來保存文件:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_save_file -> {
saveDataResultLauncher.launch("example.txt")
true
}
else -> super.onOptionsItemSelected(item)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.