将多个Mime类型传递给ActivityResultLauncher.launch()



我有以下代码

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源代码

  1. GetContent合同使用ACTION_GET_CONTENT意图:
    Intent(Intent.ACTION_GET_CONTENT)
    
  2. 如果您正在制定一份新合同,而不是延长现有合同,则需要添加OPENABLE类别。如果你不这样做,你会得到一个令人困惑的错误:
    .addCategory(Intent.CATEGORY_OPENABLE)
    
  3. 在放入额外的mime类型之前,您必须首先使用setType(),即使您放入的内容将被忽略。CCD_ 16是常见的,并且可能是最短的。如果你不这样做,你会再次得到一个令人困惑的错误:
    .setType("*/*")
    
  4. 当然,主要部分是:
    .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)
}

相关内容

  • 没有找到相关文章

最新更新