我想用作为存储访问架构的一部分,以打开一个文件中提供的Android系统对话框。我这样做有
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
startActivityForResult(intent, EDIT_REQUEST);
然后处理返回的URI中onActivityResult()
。
问题是,在出现的菜单中,我得到远不内容提供商超过我的预期。只有谷歌驱动程序(见左下图截屏)。其他的,像Dropbox的,固体资源管理器,...不显示。
我怀疑的原因是,这些应用程序根本就没有设置必要的意图过滤器在这个列表中显示。
然而,其他应用程序,例如回天邮件或Chrome,以某种方式管理,以显示在列表的顶部完全实现的内容提供商,然后其他人,如Dropbox和固体资源管理器,下面,由薄条分开的系统对话框(见右截屏)。
我怎样才能得到这个行为?
使用“ACTION_GET_CONTENT:
Intent intent = new Intent(Intent. ACTION_GET_CONTENT);
intent.setType("application/pdf");
startActivityForResult(intent, EDIT_REQUEST);
我们也有这个问题。这似乎有多种方式来获得一个选择器。
这就是我们所做的:
object ThirdPartyIntentsUtil {
// https://medium.com/@louis993546/how-to-ask-system-to-open-intent-to-select-jpg-and-png-only-on-android-i-e-no-gif-e0491af240bf
//example usage: mainType= "*/*" extraMimeTypes= arrayOf("image/*", "video/*") - choose all images and videos
//example usage: mainType= "*/image" extraMimeTypes= arrayOf("image/jpeg", "image/png") - choose all images of png and jpeg types
/**note that this only requests to choose the files, but it's not guaranteed that this is what you will get*/
@JvmStatic
fun getPickFileIntent(context: Context, mainType: String = "*/*", extraMimeTypes: Array<String>? = null): Intent? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return null
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = mainType
if (!extraMimeTypes.isNullOrEmpty())
intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeTypes)
if (context.packageManager.queryIntentActivities(intent, 0).isNullOrEmpty())
return null
return intent
}
// https://github.com/linchaolong/ImagePicker/blob/master/library/src/main/java/com/linchaolong/android/imagepicker/cropper/CropImage.java
@JvmStatic
fun getPickFileChooserIntent(
context: Context, title: CharSequence?, preferDocuments: Boolean = true,includeCameraIntents:Boolean, mainType: String
, extraMimeTypes: Array<String>? = null, extraIntents: ArrayList<Intent>? = null
): Intent? {
val packageManager = context.packageManager
var allIntents =
getGalleryIntents(packageManager, Intent.ACTION_GET_CONTENT, mainType, extraMimeTypes)
if (allIntents.isEmpty()) {
// if no intents found for get-content try pick intent action (Huawei P9).
allIntents =
getGalleryIntents(packageManager, Intent.ACTION_PICK, mainType, extraMimeTypes)
}
val cameraIntents = getCameraIntents(packageManager)
allIntents.addAll(0, cameraIntents)
// Log.d("AppLog", "got ${allIntents.size} intents")
if (allIntents.isEmpty())
return null
if (preferDocuments)
for (intent in allIntents)
if (intent.component!!.packageName == "com.android.documentsui")
return intent
if (allIntents.size == 1)
return allIntents[0]
var target: Intent? = null
for ((index, intent) in allIntents.withIndex()) {
if (intent.component!!.packageName == "com.android.documentsui") {
target = intent
allIntents.removeAt(index)
break
}
}
if (target == null)
target = allIntents[allIntents.size - 1]
allIntents.removeAt(allIntents.size - 1)
// Create a chooser from the main intent
val chooserIntent = Intent.createChooser(target, title)
if (extraIntents != null && extraIntents.isNotEmpty())
allIntents.addAll(extraIntents)
// Add all other intents
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toTypedArray<Parcelable>())
return chooserIntent
}
private fun getCameraIntents(packageManager: PackageManager): ArrayList<Intent> {
val cameraIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
val listCamera = packageManager.queryIntentActivities(cameraIntent, 0)
val intents = ArrayList<Intent>()
for (res in listCamera) {
val intent = Intent(cameraIntent)
intent.component = ComponentName(res.activityInfo.packageName, res.activityInfo.name)
intent.`package` = res.activityInfo.packageName
intents.add(intent)
}
return intents
}
/**
* Get all Gallery intents for getting image from one of the apps of the device that handle
* images. Intent.ACTION_GET_CONTENT and then Intent.ACTION_PICK
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
private fun getGalleryIntents(
packageManager: PackageManager, action: String,
mainType: String , extraMimeTypes: Array<String>? = null
): ArrayList<Intent> {
val galleryIntent = if (action == Intent.ACTION_GET_CONTENT)
Intent(action)
else
Intent(action, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
galleryIntent.type = mainType
if (!extraMimeTypes.isNullOrEmpty()) {
galleryIntent.addCategory(Intent.CATEGORY_OPENABLE)
galleryIntent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeTypes)
}
val listGallery = packageManager.queryIntentActivities(galleryIntent, 0)
val intents = ArrayList<Intent>()
for (res in listGallery) {
val intent = Intent(galleryIntent)
intent.component = ComponentName(res.activityInfo.packageName, res.activityInfo.name)
intent.`package` = res.activityInfo.packageName
intents.add(intent)
}
return intents
}
@JvmStatic
fun getMimeType(context: Context, uri: Uri): String? {
val mimeType: String? = if (ContentResolver.SCHEME_CONTENT == uri.scheme) {
val cr = context.contentResolver
cr.getType(uri)
} else {
val fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension.toLowerCase())
}
return mimeType
}
}
因此,假设你想选择一个视频文件,你可以这样做:
private val mimeTypeMap = MimeTypeMap.getSingleton()
private val videosMimeTypes = arrayOf(mimeTypeMap.getMimeTypeFromExtension("mkv"), mimeTypeMap.getMimeTypeFromExtension("mp4"), mimeTypeMap.getMimeTypeFromExtension("3gp"))
...
val intentForChoosingVideos = ThirdPartyIntentsUtil .getPickFileChooserIntent(this,null,
true, "videos/*", videosMimeTypes)
?: getPickFileIntent(this, "video/*,", videosMimeTypes)
你可以改变它来处理其他类型的文件,当然。下面是图片文件:
private val mimeTypeMap = MimeTypeMap.getSingleton()
private val imagesMimeTypes = arrayOf(mimeTypeMap.getMimeTypeFromExtension("png"), mimeTypeMap.getMimeTypeFromExtension("jpg"), mimeTypeMap.getMimeTypeFromExtension("webp"))
...
val intentForChoosingImages = ThirdPartyIntentsUtil .getPickFileChooserIntent(this, null,
true, "image/*", imagesMimeTypes)
?: getPickFileIntent(this, "image/*,", imagesMimeTypes)
它会尝试有扩展的一个,如果失败,就会想方设法把要使用的应用程序一个选择器。如果失败,它会返回null。
请注意,出于某种原因,“谷歌图片”应用程序不允许只选择视频,所以如果你想将其包括,使用更通用的形式:
val intentForChoosingVideos = ThirdPartyIntentsUtil.getPickFileChooserIntent(this, null,
false, true,"*/*", videosMimeTypes)
?: ThirdPartyIntentsUtil.getPickFileIntent(this, "video/*,", videosMimeTypes)