我想使用作为Storage Access Framework一部分提供的android系统对话框来打开文件。我这样做
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/pdf");
startActivityForResult(intent, EDIT_REQUEST);
然后在onActivityResult()
处理返回的URI。
问题在于,在结果菜单中,我得到的内容提供商远远少于我的预期。仅限Google云端硬盘和下载(请参阅下面的左侧屏幕截图)。其他人,如Dropbox,Solid Explorer,......都没有显示。
我怀疑原因是这些应用程序根本没有设置必要的intent过滤器以显示在此列表中。
然而,其他应用程序,例如Kaiten Mail或Chrome,以某种方式设法显示系统对话框,列表顶部的完全实现的内容提供商,然后其他人,如下面的Dropbox和Solid Explorer,由细条分隔(见右侧屏幕截图)。
我怎样才能得到这种行为?
答案 0 :(得分:1)
使用'ACTION_GET_CONTENT:
Intent intent = new Intent(Intent. ACTION_GET_CONTENT);
intent.setType("application/pdf");
startActivityForResult(intent, EDIT_REQUEST);
答案 1 :(得分:0)
我们也遇到了这个问题。看来有多种选择方法。
这是我们所做的:
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。
请注意,由于某些原因,“ Google相册”应用程序不允许仅选择视频,因此,如果要包含它,请使用更通用的形式:
val intentForChoosingVideos = ThirdPartyIntentsUtil.getPickFileChooserIntent(this, null,
false, true,"*/*", videosMimeTypes)
?: ThirdPartyIntentsUtil.getPickFileIntent(this, "video/*,", videosMimeTypes)