通过 Android 中的意图限制可选择的文件类型

Posted

技术标签:

【中文标题】通过 Android 中的意图限制可选择的文件类型【英文标题】:Restricting selectable file types via intent in Android 【发布时间】:2016-01-12 02:02:07 【问题描述】:

我正在将选定的文件上传到服务器,但我想限制用户只选择文档文件(.doc、.pdf 等)和图像文件。

目前我的代码适用于所有文件,它会获取所有文件的 uri。

如何限制用户只选择特定类型的文件?

这是我选择任何文件的代码。

Intent i=new Intent();
i.setType("*/*");
i.setAction(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(i, "abc"),requestCode);

【问题讨论】:

androidproblem.wordpress.com/2012/01/18/… 【参考方案1】:

通过| 分隔多个 MIME 类型 喜欢

i.setType("image/*|application/pdf|audio/*");

或创建一个 MIME 类型数组,例如

String[] mimetypes = "image/*", "application/*|text/*";

并将其传递为

i.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);

【讨论】:

如何获取选中文件(pdf, text)的路径 嗨伙计,我曾尝试选择文件的 doc 或 docx 类型,但无法选择我的意图类型如下,intent.setType("image/*|application/pdf|application /doc|application/docm|application/docx|application/dot|application/mcw|application/rtf" + "|application/pages|application/odt|application/ott"); 将 mime 类型添加到字符串数组。 Here 是 mime 类型的列表。这个link 可以帮助你。 @MadhukarHebbar 我只想选择图像和视频。但是当我打开文件管理器时,甚至可以选择音频。他们没有被过滤掉。 i.setType("image/* | video/*");由于文件管理器可以处理 ACTION_GET_CONTENT,我如何过滤音频和其他类型? 第一种方法,即用 | 分隔不适合我,但使用字符串数组的第二个工作!【参考方案2】:

基于上述答案和类似的线程,我开发了一个可行的解决方案。我正在共享代码 sn-p ,所以它很容易使用。

如何使用 Intent 过滤或选择特定文件类型的文件。

代码

public static Intent getCustomFileChooserIntent(String ...types)
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            // Filter to only show results that can be "opened"
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("*/*");
            intent.putExtra(Intent.EXTRA_MIME_TYPES, types);
            return intent;
        

示例文件类型常量

        public static final String DOC = "application/msword";
        public static final String DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        public static final String IMAGE = "image/*";
        public static final String AUDIO = "audio/*";
        public static final String TEXT = "text/*";
        public static final String PDF = "application/pdf";
        public static final String XLS = "application/vnd.ms-excel";

用法

  // i passed string values, you can pass a array of string too.
    Intent intent = getCustomFileChooserIntent(DOC, PDF, IMAGE);

    startActivityForResult(intent, 101);

【讨论】:

【参考方案3】:

虽然不是通过 Intent,但我找到了 droidninja 的一个很好的库项目,它可以让人们一次性浏览存储在本地的 doc 文件或图像。

repositories 
    jcenter()
    maven 
        url "https://jitpack.io"
    

将其插入您的 app.gradle 文件中

compile 'com.droidninja:filepicker:1.0.6'

然后在给定的函数下方调用此函数以生成一个以材料为主题的对话框,该对话框将提供一个选项来选择是否选择图像或组或与文档相同

private void showFileChooser() 

    new MaterialStyledDialog.Builder(getActivity())
            .setTitle("Upload Documents")
            .setDescription("Upload single or multiple documents in a single attempt now, maximum being 5.\n \nChoose between Images option or PDF's option now. \n")
            //.setStyle(Style.HEADER_WITH_ICON)
            .setHeaderColor(R.color.colorPrimary)
            .withDialogAnimation(true)
            .setIcon(R.drawable.ic_pdf)
            .setCancelable(true)
            .autoDismiss(false)
            .setPositiveText(R.string.images)
            .onPositive(new MaterialDialog.SingleButtonCallback() 
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                    dialog.dismiss();
                    FilePickerBuilder.getInstance().setMaxCount(5)
                            .setSelectedFiles(selectedPhotos)
                            .setActivityTheme(R.style.AppTheme)
                            .pickPhoto(getActivity());
                
            )
            .setNeutralText(R.string.pdf)
            .onNeutral(new MaterialDialog.SingleButtonCallback() 
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                    dialog.dismiss();
                    FilePickerBuilder.getInstance().setMaxCount(5)
                            .setSelectedFiles(filePaths)
                            .setActivityTheme(R.style.AppTheme)
                            .pickDocument(getActivity());
                
            )
            .show();

不过,对于这个对话框,你需要在 gradle 文件中拥有

compile com.github.javiersantos:MaterialStyledDialogs:2.0'

最后,会调用 onActivityResult() 来提取类似这样的结果

   @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        switch (requestCode) 
            case FilePickerConst.REQUEST_CODE_PHOTO:
                if (resultCode == Activity.RESULT_OK && data != null) 
                    selectedPhotos = new ArrayList<>();
                    selectedPhotos.addAll(data.getStringArrayListExtra(FilePickerConst.KEY_SELECTED_PHOTOS));
                
                break;
            case FilePickerConst.REQUEST_CODE_DOC:
                if (resultCode == Activity.RESULT_OK && data != null) 
                    filePaths = new ArrayList<>();
                    filePaths.addAll(data.getStringArrayListExtra(FilePickerConst.KEY_SELECTED_DOCS));
                
                break;
        

    

应用主题

  <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">

        <!-- Customize your theme here. -->
        <item name="android:windowNoTitle">true</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

【讨论】:

【参考方案4】:

我所做的是 setTypeimageIntent.setType("image/*\", \"application/pdf");

【讨论】:

【参考方案5】:
object CustomFileChooserIntent
const val DOC = "application/msword"
const val DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
const val IMAGE = "image/*"
const val AUDIO = "audio/*"
const val VIDEO = "video/*"
const val TEXT = "text/*"
const val PDF = "application/pdf"
const val XLS = "application/vnd.ms-excel"

fun getCustomFileChooserIntent(vararg types: String): Intent 
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
    intent.addCategory(Intent.CATEGORY_OPENABLE)
    intent.type = "*/*"
    intent.putExtra(Intent.EXTRA_MIME_TYPES, types)
    return intent


CustomFileChooserIntent.getCustomFileChooserIntent(CustomFileChooserIntent.IMAGE)

【讨论】:

以上是关于通过 Android 中的意图限制可选择的文件类型的主要内容,如果未能解决你的问题,请参考以下文章

通过 Android 中的 Intent 选择任何类型的文件

为啥Android在通过蓝牙OPP接收时对可接受的文件类型进行如此严格的限制?

通过 android studio 中的意图发送 MultiMap 类型的数据结构

试图从谷歌地图获取纬度是通过 Android 中的意图返回 null

android - 如何使用意图选择视频文件并获取它的视频

Android:联系人选择器意图 |无法实例化类型 Uri