我有以下代码
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
//Some code here..
}
在其他地方,
getContent.launch("application/vnd.openxmlformats-officedocument.wordprocessingml.document")
我可以成功地选择docx文件。我需要选择pdf或doc或text或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的自定义类。有趣";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的答案显示了一种获得多MIMEGetContent
的方法,即通过使用级联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
}
}
作为安卓编程的新手,我很难做到这一点。这些文档没有提到一些事情,没有这些事情,我的代码就无法工作。也许它们在经验丰富的安卓开发者中是常识,但对于2023年加入的任何人来说,就不那么多了。我最终不得不查看GetContent
:的Android源代码
GetContent
合同使用ACTION_GET_CONTENT
意图:Intent(Intent.ACTION_GET_CONTENT)
- 如果您正在制定一份新合同,而不是延长现有合同,则需要添加
OPENABLE
类别。如果你不这样做,你会得到一个令人困惑的错误:.addCategory(Intent.CATEGORY_OPENABLE)
- 在放入额外的mime类型之前,您必须首先使用
setType()
,即使您放入的内容将被忽略。CCD_ 16是常见的,并且可能是最短的。如果你不这样做,你会再次得到一个令人困惑的错误:.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)
}