我有以下代码
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
//Some code here..
}
还有其他地方,
getContent.launch("application/vnd.openxmlformats-officedocument.wordprocessingml.document")
我可以成功选择docx文件。我需要选择 pdf 或 doc 或文本或 docx 而只是能够选择一种(此处为 docx)。
我建议使用
OpenDocument
而不是 GetContent
。
val documentPick =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
// do something
}
启动意图时只需添加您想要获取的 mime 类型
documentPick.launch(
arrayOf(
"application/pdf",
"application/msword",
"application/ms-doc",
"application/doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"text/plain"
)
)
使用数组在我的情况下不起作用。相反,以下工作正常。 这里使用了 ActivityResultContracts.GetContent 的自定义类。 fun“createIntent”被重写以自定义方法以从输入中获取意图。
// custom class of GetContent: input string has multiple mime types divided by ";"
// Here multiple mime type are divided and stored in array to pass to putExtra.
// super.createIntent creates ordinary intent, then add the extra.
class GetContentWithMultiFilter:ActivityResultContracts.GetContent() {
override fun createIntent(context:Context, input:String):Intent {
val inputArray = input.split(";").toTypedArray()
val myIntent = super.createIntent(context, "*/*")
myIntent.putExtra(Intent.EXTRA_MIME_TYPES, inputArray)
return myIntent
}
}
// define ActivityResultLauncher to launch : using custom GetContent
val getContent=registerForActivityResult(GetContentWithMultiFilter()){uri ->
... // do something
}
// launch it
// multiple mime types are separated by ";".
val inputString="audio/mpeg;audio/x-wav;audio/wav"
getContent.launch(inputString)
GetContent
合约仅采用单个String
参数,该参数只能包含单个MIME类型。
OpenDocument
合约采用一组String
,每个数组都有一个 MIME 类型。
各有利弊,因此请参阅此 StackOverflow 问题以帮助您决定使用哪一个。我不知道为什么决定将
GetContact
限制为单一 MIME 类型。
lglink 的答案展示了一种获得多 MIME
GetContent
的方法,即通过使用 ;
分隔的串联 MIME 类型的 String
来扩展该契约。
我用另一种方式解决了这个问题,按照官方文档制作自定义合同:
class BespokeContract: ActivityResultContract<Array<String>, Uri?>() {
@CallSuper
override fun createIntent(context: Context, input: Array<String>): Intent {
return Intent(Intent.ACTION_GET_CONTENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("*/*")
.putExtra(Intent.EXTRA_MIME_TYPES, input)
}
override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
return intent.takeIf { resultCode == Activity.RESULT_OK }?.data
}
}
作为一名 Android 编程新手,我花了很多功夫才得到这个。这些文档没有提到一些事情,否则我的代码就无法工作。也许它们是经验丰富的 Android 开发人员的常识,但对于 2023 年涉足该领域的人来说,情况并非如此。我最终不得不查看 Android 源代码
GetContent
:
GetContent
合约使用ACTION_GET_CONTENT
意图:
Intent(Intent.ACTION_GET_CONTENT)
OPENABLE
类别。如果你不这样做,你会得到一个令人困惑的错误:
.addCategory(Intent.CATEGORY_OPENABLE)
setType()
,即使您放置在那里的内容将被忽略。 */*
很常见,而且可能是最短的。如果你不这样做,你会再次得到一个令人困惑的错误:
.setType("*/*")
.putExtra(Intent.EXTRA_MIME_TYPES, input)
对于像我一样在互联网上搜索帮助时看到多种方法而感到困惑的人,不知道哪些方法已被弃用,哪些是由于旧的 Views 代码与新的 Compose 代码等造成的,这是一种等效的不同编码方式
createIntent
:
override fun createIntent(context: Context, input: Array<String>) =
Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(Intent.EXTRA_MIME_TYPES, input)
}