【问题标题】:ACTION_VIEW intent for a file with unknown MimeType具有未知 MimeType 的文件的 ACTION_VIEW 意图
【发布时间】:2011-06-07 12:42:18
【问题描述】:

我的应用具有浏览手机和 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 }

【问题讨论】:

    标签: android


    【解决方案1】:

    这应该会检测 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();
    
        }
    }
    

    【讨论】:

    • 这段代码有一个问题:在第三行代码中你不应该使用 substring(1)。使用这条线:String mimeType = myMime.getMimeTypeFromExtension(fileExt(getFile()));。 (fileExt 只会返回不带点的扩展名。)
    • 用户 FileProvider 而不是目标上的 URI.fromFile() >= 24 androids
    【解决方案2】:

    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);
    

    【讨论】:

      【解决方案3】:

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

        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);
      
      }
      

      【讨论】:

      • 酷!干得好!
      • 但是endsWith 而不是contains 方法怎么样?
      • @V.Kalyuzhnyu 当然任何适合你的都可以
      • 如果扩展名是大写字母会发生什么,例如sample.DOCX?
      • 我使用了 url.toString().contains(".zip") || url.toString().contains(".rar") 和 application/x-wav 但我得到错误 android.content.ActivityNotFoundException: No Activity found to handle Intent any solution
      【解决方案4】:
      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。

      【讨论】:

      • Thomas Vos 的观点至关重要。此代码很有用,但如果您要使用它,则需要将 targetSdkVersion 设置为 23 或更低。如果 Android 7.0 设备运行此代码,它将崩溃。
      【解决方案5】:

      Android 不会根据文件扩展名启动 Activity,除非有一个应用为其指定了特定的 Intent 过滤器。您需要Intent 的mime 类型来告诉android 足够的信息来启动正确的Activity

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

      顺便说一句,您的设备中安装了 pdf 阅读器吗?

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

      【讨论】:

        【解决方案6】:

        您可以找出文件的 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;
            }
        

        【讨论】:

          【解决方案7】:

          简单共享文件(“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);
          

          【讨论】:

          • FileUriExposedException
          【解决方案8】:

          这肯定行得通..

           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();
          
                          }
                      }
          

          【讨论】:

            【解决方案9】:

            我用 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()
                                }
                            }
            

            【讨论】:

              【解决方案10】:

              NoBugs 的回答有问题。这是直接跳出eclipse函数信息窗口:

              字符串 android.webkit.MimeTypeMap.getMimeTypeFromExtension(String 扩展名)

              public String getMimeTypeFromExtension(字符串扩展)

              自:API 级别 1

              返回给定扩展的 MIME 类型。

              参数

              extension 没有前导 '.' 的文件扩展名

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

              【讨论】:

              • 你能举个例子吗?如果是null类型怎么办?
              • 我正在寻找返回 null 的解决方案,但仍然没有找到。
              • 你能举一个返回null的文件类型的例子吗?
              • 我有一个定制的。我什至不记得那是什么。我早就放弃了那个项目。
              • 哦,好的。在自定义文件扩展名的情况下,我想你会先检查一下,然后直接打开你的活动,如果你不能让意图过滤器工作。
              【解决方案11】:

              使用此方法从文件的 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;
              }
              

              【讨论】:

                【解决方案12】:

                你应该总是检查相同的

                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;
                    }
                

                【讨论】:

                  【解决方案13】:

                  您必须使用 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
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-22
                    • 2015-12-03
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多