ACTION_VIEW意图使用未知MimeType的文件

时间:2011-06-07 12:42:18

标签: android

我的应用程序具有浏览手机和SD卡上的文件并使用其他应用程序打开文件的功能。我想要一个解决方案,我不必指定MimeType,可以使用任何类型的文件。

这是我的代码:

Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.fromFile(item));
startActivity(myIntent);

但是,我收到以下错误:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.PICK dat=file:///sdcard/dropbox/test.pdf }

13 个答案:

答案 0 :(得分:111)

这应检测mimetype并使用默认值打开:

MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = myMime.getMimeTypeFromExtension(fileExt(getFile()).substring(1));
newIntent.setDataAndType(Uri.fromFile(getFile()),mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
    context.startActivity(newIntent);
} catch (ActivityNotFoundException e) {
    Toast.makeText(context, "No handler for this type of file.", Toast.LENGTH_LONG).show();
}

使用此功能:

private String fileExt(String url) {
    if (url.indexOf("?") > -1) {
        url = url.substring(0, url.indexOf("?"));
    }
    if (url.lastIndexOf(".") == -1) {
        return null;
    } else {
        String ext = url.substring(url.lastIndexOf(".") + 1);
        if (ext.indexOf("%") > -1) {
            ext = ext.substring(0, ext.indexOf("%"));
        }
        if (ext.indexOf("/") > -1) {
            ext = ext.substring(0, ext.indexOf("/"));
        }
        return ext.toLowerCase();

    }
}

答案 1 :(得分:11)

createChooser应该做的诀窍:

Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setData(Uri.fromFile(item));
Intent j = Intent.createChooser(myIntent, "Choose an application to open with:");
startActivity(j);

答案 2 :(得分:7)

Intent myIntent = new Intent(Intent.ACTION_VIEW);
String mime=URLConnection.guessContentTypeFromStream(new FileInputStream(item));
if(mime==null) mime=URLConnection.guessContentTypeFromName(item.getName());
myIntent.setDataAndType(Uri.fromFile(item), mime);
startActivity(myIntent);

首先我尝试用文件内容猜测,但是我发现它总是返回null。

答案 3 :(得分:5)

Android不会根据文件扩展名启动活动,除非有应用程序为其指定特定的意图过滤器。你需要mime类型到Intent告诉android足够的信息才能启动正确的Activity

您可以选择使用MimeTypeMap类自动执行此任务。检查方法String getMimeTypeFromExtension(String extension)

顺便说一下,您的设备中是否安装了PDF阅读器?

你也应该处理这个异常,可能是通过显示一个漂亮的弹出窗口,说明该特定类型的文件没有应用程序。

答案 4 :(得分:5)

尝试这个几乎涵盖所有文件扩展名

  public void openFile(File url) {

    Uri uri = Uri.fromFile(url);

    Intent intent = new Intent(Intent.ACTION_VIEW);
    if (url.toString().contains(".doc") || url.toString().contains(".docx")) {
        // Word document
        intent.setDataAndType(uri, "application/msword");
    } else if (url.toString().contains(".pdf")) {
        // PDF file
        intent.setDataAndType(uri, "application/pdf");
    } else if (url.toString().contains(".ppt") || url.toString().contains(".pptx")) {
        // Powerpoint file
        intent.setDataAndType(uri, "application/vnd.ms-powerpoint");
    } else if (url.toString().contains(".xls") || url.toString().contains(".xlsx")) {
        // Excel file
        intent.setDataAndType(uri, "application/vnd.ms-excel");
    } else if (url.toString().contains(".zip") || url.toString().contains(".rar")) {
        // WAV audio file
        intent.setDataAndType(uri, "application/x-wav");
    } else if (url.toString().contains(".rtf")) {
        // RTF file
        intent.setDataAndType(uri, "application/rtf");
    } else if (url.toString().contains(".wav") || url.toString().contains(".mp3")) {
        // WAV audio file
        intent.setDataAndType(uri, "audio/x-wav");
    } else if (url.toString().contains(".gif")) {
        // GIF file
        intent.setDataAndType(uri, "image/gif");
    } else if (url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) {
        // JPG file
        intent.setDataAndType(uri, "image/jpeg");
    } else if (url.toString().contains(".txt")) {
        // Text file
        intent.setDataAndType(uri, "text/plain");
    } else if (url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) {
        // Video files
        intent.setDataAndType(uri, "video/*");
    } else {
        //if you want you can also define the intent type for any other file
        //additionally use else clause below, to manage other unknown extensions
        //in this case, Android will show all applications installed on the device
        //so you can choose which application to use
        intent.setDataAndType(uri, "*/*");
    }

    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);

}

答案 5 :(得分:4)

您可以找到文件的mime类型,并自己打算打开文件。

使用以下代码打开任何文件......

File temp_file=new File("YOUR FILE PATH");
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(temp_file),getMimeType(temp_file.getAbsolutePath()));
startActivity(intent); 

其中getMimeType()是....(此方法将返回所需的mime类型,如果文件没有任何正确的mime类型,则返回null)...

private String getMimeType(String url)
    {
        String parts[]=url.split("\\.");
        String extension=parts[parts.length-1];
        String type = null;
        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            type = mime.getMimeTypeFromExtension(extension);
        }
        return type;
    }

答案 6 :(得分:2)

简单共享文件(“multipart /”)

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
intent.setType("multipart/");
startActivity(intent);

答案 7 :(得分:2)

这肯定会有效..

 private void showFile(File file, String filetype) 
{
                MimeTypeMap myMime = MimeTypeMap.getSingleton();
                Intent intent = new Intent(Intent.ACTION_VIEW);
                String mimeType = 
                myMime.getMimeTypeFromExtension(filetype);
                if(android.os.Build.VERSION.SDK_INT >=24) {
                 Uri fileURI = FileProvider.getUriForFile(getContext(),
                            BuildConfig.APPLICATION_ID + ".provider",
                            file);
                    intent.setDataAndType(fileURI, mimeType);

                }else {
                    intent.setDataAndType(Uri.fromFile(file), mimeType);
                }
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try {
                    context.startActivity(intent);
                }catch (ActivityNotFoundException e){
                    Toast.makeText(context, "No Application found to open this type of file.", Toast.LENGTH_LONG).show();

                }
            }

答案 8 :(得分:0)

NoBugs的答案存在问题。这直接来自eclipse功能信息窗口:

  

String android.webkit.MimeTypeMap.getMimeTypeFromExtension(String   扩展)

     

public String getMimeTypeFromExtension(String extension)

     

自:API Level 1

     

返回给定扩展名的MIME类型。

     

参数

     

扩展名没有前导'。'的文件扩展名

     

返回给定扩展名的MIME类型,如果没有,则返回null。

答案 9 :(得分:0)

使用此方法从文件的URI中获取MIME类型:

public static String getMimeType(String url) {

    String type = null;
    String extension = url.substring(url.lastIndexOf(".") + 1);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}

答案 10 :(得分:0)

您应该始终使用

检查相同内容
PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent);
} else {
    Log.d(TAG, "No Intent available to handle action");

}

要获取文件的MimeTpye,您可以使用: -

 public String getMimeType(Uri uri, Context context) {
        String mimeType = null;
        if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
            ContentResolver cr = context.getContentResolver();
            mimeType = cr.getType(uri);
        } else {
            String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
                    .toString());
            mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                    fileExtension.toLowerCase());
        }
        return mimeType;
    }

答案 11 :(得分:0)

我用Kotlin编写了这几行,它的工作就像一种魅力。享受它。

val file = File(path)              
val mimeType = URLConnection.guessContentTypeFromName(file.absolutePath)
                Intent().apply {
                    setDataAndType(Uri.fromFile(file), mimeType)
                    flags = Intent.FLAG_ACTIVITY_NEW_TASK
                }.let {
                    try {
                        itemView.context.startActivity(it)
                    } catch (e: ActivityNotFoundException) {
                        Toast.makeText(itemView.context, "There's no program to open this file", Toast.LENGTH_LONG).show()
                    }
                }

答案 12 :(得分:0)

您必须使用 MimeTypeMap 并使用文件扩展名获取类型。然后将其传递给意图以打开任何类型的文件。

科特林

fun getIntentForFile(filePath: String, context: Context): Intent {
    val intent = Intent()

    val uri = FileProvider.getUriForFile(
        context,
        context.applicationContext.packageName + ".fileprovider",
        File(filePath)
    )
    intent.action = Intent.ACTION_VIEW
    intent.putExtra(Intent.EXTRA_STREAM, uri)
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    intent.setDataAndType(uri, getFileContentType(filePath))
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    return intent
}

fun getFileContentType(filePath: String): String? {
    val file = File(filePath)
    val map = MimeTypeMap.getSingleton()
    val ext = MimeTypeMap.getFileExtensionFromUrl(file.name)
    var type = map.getMimeTypeFromExtension(ext)
    if (type == null) type = "*/*"
    return type
}