问题描述
我对 Android Kotlin 编程非常陌生。我正在制作一个使用存储访问框架创建、读取和删除文件的应用程序。我通过实现已弃用的 startActivityForResult 意图来执行文件读取、创建、删除任务来做到这一点。我尝试使用 Activity Result API 来实现它,但我陷入了找不到它的请求代码中。 在新的实现中,有 resultCode 但没有 requestCode。
我的实现如下。我如何使用 Activity Result API 实现以下内容?
如何从 Activity Result API 获取请求代码?
fun createFile()
{
val filename: String = etFileName.text.toString()
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/*"
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_TITLE,filename)
}
startActivityForResult(intent,WRITE_REQUEST_CODE)
}
fun readFile(){
etFileName.setText("")
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/*"
}
startActivityForResult(intent,READ_REQUEST_CODE)
}
fun deleteFile(uri: Uri){
val filename = queryName(contentResolver,uri)
DocumentsContract.deleteDocument(contentResolver,uri)
Toast.makeText(applicationContext,"Done deleting $filename",Toast.LENGTH_SHORT).show()
}
fun writeText(uri: Uri) : String{
//var writetext: String = "typing high speed"
var writeStream = contentResolver.openFileDescriptor(uri,"w")
val filename: String = queryName(contentResolver,uri)
etFileName.setText(filename)
var fileOutputStream = FileOutputStream(writeStream?.fileDescriptor)
fileOutputStream.write(filename.toByteArray())
fileOutputStream.close()
return filename.toString()
}
fun openFileContent(uri: Uri): String{
val inputStream = contentResolver.openInputStream(uri)
val reader = BufferedReader(InputStreamReader(inputStream))
val stringBuilder = StringBuilder()
val filename = queryName(contentResolver,uri)
etFileName.setText(filename)
var currentline = reader.readLine()
while (currentline != null) {
stringBuilder.append(currentline + "\n")
currentline = reader.readLine()
}
inputStream?.close()
val str = stringBuilder.toString()
Log.d("Uri Read",": $str")
return str
}
private fun queryName(resolver: ContentResolver,uri: Uri): String {
val returnCursor: Cursor = resolver.query(uri,null,null)!!
val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.disPLAY_NAME)
returnCursor.movetoFirst()
val name: String = returnCursor.getString(nameIndex)
returnCursor.close()
return name
}
override fun onActivityResult(requestCode: Int,resultCode: Int,resultData: Intent?) {
super.onActivityResult(requestCode,resultCode,resultData)
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Read","$uri")
if (uri != null) {
val readfile: String = openFileContent(uri)
etContent.setText(readfile)
}
} else if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
Log.i("Uri Write","Uri: $uri") // 1
val write = writeText(uri) // 2
etContent.setText(write)
}
} else if (requestCode == DELETE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Delete","$uri")
if (uri != null) {
deleteFile(uri)
}
}
}
由于上述方法已被弃用,我尝试使用 Intent 启动器来实现它,但在任何地方都没有对 requestCode 的引用,所以我被困在这里。如下图:
val startforFile: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
// Could not find reference to requestCode here
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Read","$uri")
if (uri != null) {
deleteFile(uri)
}
}
}
谁能告诉我它是如何正确完成的?
解决方法
ActivityResultContracts.StartActivityForResult
有两种方式。
- 通过注册多个侦听器发出多个请求:
val startforFileRead: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
if (resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Read","$uri")
if (uri != null) {
val readfile: String = openFileContent(uri)
etContent.setText(readfile)
}
}
}
val startforFileWrite: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
if (resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
Log.i("Uri Write","Uri: $uri") // 1
val write = writeText(uri) // 2
etContent.setText(write)
}
}
}
val startforFileDelete: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){
result: ActivityResult ->
if (resultCode == Activity.RESULT_OK) {
val uri =resultData?.data
Log.d("Uri Delete","$uri")
if (uri != null) {
deleteFile(uri)
}
}
}
- 在从其他活动返回的 Intent 中添加额外内容。将其解压为您的请求代码。
const val REQUEST_CODE = "REQUEST_CODE"
//...
val startforFile: ActivityResultLauncher<Intent> =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
val requestCode = result.data?.extras?.getInt(REQUEST_CODE)
if (requestCode == null) {
Log.e("FileResultLauncher","No REQUEST_CODE was returned in data intent.")
return@registerForActivityResult
}
val uri = result.data?.data
if (uri == null || result.resultCode != RESULT_OK) {
Log.i("FileResultLauncher","No Uri returned or result wasn't OK.")
return@registerForActivityResult
}
when (requestCode) {
READ_REQUEST_CODE -> run {
Log.d("Uri Read","$uri")
val readfile: String = openFileContent(uri)
etContent.setText(readfile)
}
WRITE_REQUEST_CODE -> run {
Log.i("Uri Write","Uri: $uri") // 1
val write = writeText(uri) // 2
etContent.setText(write)
}
DELETE_REQUEST_CODE -> run {
Log.d("Uri Delete","$uri")
deleteFile(uri)
}
}
}