我正在尝试使用
从用户那里检索一个可以是图像或pdf的文件registerForActivityResult(ActivityResultContracts.GetContent()) { file: Uri ->
......
}.launch(<mimetypes>)
我已经尝试过另一个问题的答案中的
"image/*|application/pdf"
,但它不起作用,有没有办法在使用registerForActivityResult时要求多种MIME类型?
使用 registerForActivityResult 时有什么方法可以请求多个 MIME 类型吗?
不能直接使用当前版本的
ActivityResultContracts.GetContent
。但是,您应该能够对其进行子类化、覆盖 createIntent()
,并从那里自定义生成的 Intent
。然后,您可以尝试将 EXTRA_MIME_TYPES
添加到该 Intent
以及您想要的其他 MIME 类型的 String[]
。
这是我的示例代码,在 api 31 中测试
var resultGalleryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val intent: Intent? = result.data
if (intent != null) {
intent.data?.let { selectedImageUri ->
....
}
}
} else {
Timber.e(" >>> error selected image from gallery by intent")
}
}
}
fun galleryLauncher() {
val intent = Intent(Intent.ACTION_GET_CONTENT, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).apply {
type = "image/*"
action = Intent.ACTION_GET_CONTENT
putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/jpeg", "image/png", "image/jpg"))
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
}
resultGalleryLauncher.launch(intent)
}
请使用
ActivityResultContracts.OpenMultipleDocuments()
来代替。
import androidx.activity.result.contract.ActivityResultContracts
class DocumentsFragment : Fragment() {
companion object {
// 1. List of MIME types
/**@see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types">MIME types</a>
* @see <a href="https://www.iana.org/assignments/media-types/media-types.xhtml">IANA - MIME types</a>*/
private val MIME_TYPES: Array<String> = arrayOf(
"image/*", "application/pdf", "application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.oasis.opendocument.text", "text/plain", "text/markdown"
)
}
//2. Register for Activity Result callback as class field
private val getDocuments =
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()/*NOT OpenDocument*/) {
Log.d("Open documents", "incoming uri: size = ${it.size}")
add(it)
}
...
//3. set onclick listener
selectDocumentsButton.setOnClickListener { getDocuments.launch(MIME_TYPES) }
...
//4. handle incoming uri list
private fun add(list: List<Uri>) {
val setOfFiles = copyToAppDir(list)
setOfFiles.forEach {
//TODO: do something
}
}
//5. copy the files to the application folder for further work
private fun copyToAppDir(list: List<Uri>): Set<File> {
val set = mutableSetOf<File>()
list.forEach { uri ->
try {
val file: File = copyUriContentToTempFile(uri)
set.add(file)
} catch (e: Exception) {
e.printStackTrace()
}
}
return set
}
//6. copy selected content by uri
private fun copyUriContentToTempFile(uri: Uri): File {
val inputStream = requireContext().contentResolver.openInputStream(uri)
inputStream.use { input ->
val tempFile: File = .. ; //TODO: create file
tempFile.outputStream().use { output ->
input?.copyTo(output)
}
return tempFile
}
}
}
将建议的解决方案从 Kotlin 翻译为 Java,以防有人需要:
ActivityResultLauncher<Intent> photoPicker2 = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if(result.getResultCode() == Activity.RESULT_OK) {
Intent intent = result.getData();
if(intent != null) {
Uri picked = intent.getData();
if(picked != null) {
//Process the image...
}
}
}
});
调用启动器:
try {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/jpeg", "image/png", "image/x-png"});
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
photoPicker2.launch(intent);
} catch (ActivityNotFoundException e) {
try {
//Fallback to ActivityResultContracts.OpenDocument().
documentPicker.launch(new String[]{"image/jpeg", "image/png", "image/x-png"});
} catch (ActivityNotFoundException ignore) {}
}