【问题标题】:Open an image using URI in Android's default gallery image viewer在 Android 的默认图库图像查看器中使用 URI 打开图像
【发布时间】:2011-07-20 00:29:33
【问题描述】:

我已经提取了图像 uri,现在我想用 Android 的默认图像查看器打开图像。或者更好的是,用户可以选择使用什么程序来打开图像。如果您尝试打开文件,文件资源管理器之类的工具会为您提供。

【问题讨论】:

    标签: android android-image


    【解决方案1】:

    接受的答案对我不起作用,

    什么有效:

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    intent.setDataAndType(Uri.parse("file://" + "/sdcard/test.jpg"), "image/*");
    startActivity(intent);
    

    【讨论】:

    • 是的,但是你如何避免在 android 2.2 和 2.3 上等待 10 秒黑屏,而画廊说它正在搜索新照片和专辑?
    • @max4ever : 找到解决问题的方法了吗?
    • 是的,File f = new File(..., ...); if (f.isFile()) { MediaScannerConnection.scanFile(SchedaActivity.this, new String[] { f.toString() }, null, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri, "image/*"); SchedaActivity.this.startActivityForResult(intent, SchedaActivity.this.ACTIVITY_CODE); } });
    • 如果您只指定“image/*”,Android 4.1 将向您显示图像。这不适用于 Android 2.3。您必须指定 mime 类型:“image/jpeg”。
    • 这个答案以file:///sdcard... 结尾——这是故意的吗?
    【解决方案2】:

    如果您的应用面向 Android N (7.0) 及更高版本,则不应使用上述答案(“Uri.fromFile”方法),因为它不适合您。

    相反,您应该使用 ContentProvider。

    例如,如果您的图像文件在外部文件夹中,您可以使用这个(类似于我制作的代码here):

    File file = ...;
    final Intent intent = new Intent(Intent.ACTION_VIEW)//
                                        .setDataAndType(VERSION.SDK_INT >= VERSION_CODES.N ?
                                                        FileProvider.getUriForFile(this,getPackageName() + ".provider", file) : Uri.fromFile(file),
                                "image/*").addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    

    清单:

    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>
    

    res/xml/provider_paths.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <!--<external-path name="external_files" path="."/>-->
        <external-path
            name="files_root"
            path="Android/data/${applicationId}"/>
        <external-path
            name="external_storage_root"
            path="."/>
    </paths>
    

    如果您的图片在应用的私有路径中,您应该创建自己的 ContentProvider,因为我在链接上创建了“OpenFileProvider”。

    【讨论】:

    • 是的,只有这样才能解决我在 Android N 和 Oreo 上的问题。非常感谢。你完全正确!
    • 非常感谢!!仅此解决方案适用于 android 较新版本
    • 它是否也适用于保存在共享空间(SD卡)中的文件?
    • @Albert221 应该,但我认为我没有测试过。请尝试告诉我。
    • 不适用于 Android 10,以防我将 Uri 保存到图库中的图像
    【解决方案3】:

    问自己,也回答自己:

    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("content://media/external/images/media/16"))); /** replace with your own uri */
    

    它还会询问使用什么程序来查看文件。

    【讨论】:

    • 嗨,hari,您的代码对于打开图像很有用。你能有一个打开画廊文件夹的解决方案吗?这是我的问题stackoverflow.com/questions/6519024/…
    • @djk 我只是在这里回答这个问题stackoverflow.com/questions/6074270/… 看看它是否与你的问题有关。
    • 以防其他人遇到与我相同的问题 - 我添加了 intent.setType("image/png") (我知道图像将是 png 文件)并且它阻止了画廊从打开图像!所以 .setType 在这里适得其反:)
    • 另外,您可以使用intent.setDataAndType(uri, "image/*");强制Android使用图像查看应用程序。
    • 这个方法可以用来避免创建一个新的布局只是为了查看图像吗?
    【解决方案4】:

    尝试使用它:

    Uri uri =  Uri.fromFile(entry);
    Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
    String mime = "*/*";
    MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
    if (mimeTypeMap.hasExtension(
        mimeTypeMap.getFileExtensionFromUrl(uri.toString())))
        mime = mimeTypeMap.getMimeTypeFromExtension(
            mimeTypeMap.getFileExtensionFromUrl(uri.toString()));
    intent.setDataAndType(uri,mime);
    startActivity(intent);
    

    【讨论】:

    • 这太完美了!它打开基于android os的弹出/布局,以便用户可以根据用户选择选择播放器或查看器。例如,显示图像、音乐、视频、应用程序甚至任何文件。
    • 我得到了“通过 Intent.getData() 暴露在应用程序之外”错误。
    • 如果您遇到“通过 Intent.getData() 暴露在应用程序之外”错误,您可以查看此链接以解决问题stackoverflow.com/a/45751453/10619147
    【解决方案5】:

    基于Vikas answer,但稍作修改:Uri由参数接收:

    private void showPhoto(Uri photoUri){
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(photoUri, "image/*");
        startActivity(intent);
    }
    

    【讨论】:

    • 这仅显示单个选定的图像,而不显示同一文件夹中的其他图像(以便用户可以向左/向右滑动以查看其他图像)。知道如何实现这一目标吗?
    • @Atul 在这种情况下,用例完全不同。 OP 希望使用其 URI 显示 X 图像。您似乎想要 a) 在确定的位置打开图库或 b) 在图库中打开您拥有 URI 的照片子集。在网络上进行一些研究或提出新问题,因为您的用例完全不同。
    • 感谢您的快速回复。我需要达到 OP 的要求。您(和 Vikas 的)的答案很好地实现了它,唯一的问题是,一旦它显示图像,它就不允许滚动浏览同一文件夹中的其他图像(当用户向左或向右滑动时)。我见过许多应用程序(例如 WhatsApp)在图库查看器中显示图像(就像您所做的一样),但它们也允许用户滚动浏览同一文件夹中的左右图像。
    • @Atul OP 想要打开 one 图像,其中包含给定 URI 的 Gallery。 WhatsApp 的实现完全不同。我不知道 Gallery 是否支持接收具有许多 URI 的 Intent。无论如何,check out this, 可能会对您有所帮助。
    • 我已经看过你给的链接了。不管怎么说,多谢拉。但我发现有人已经posted a question 我想要什么。但是,他的回答太简短,无法理解。
    【解决方案6】:

    如果您使用 android N 及以下版本,这可能会有所帮助

     File file=new File(Environment.getExternalStorageDirectory()+"/directoryname/"+filename);
            Uri path= FileProvider.getUriForFile(MainActivity.this,BuildConfig.APPLICATION_ID + ".provider",file);
    
            Intent intent=new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(path,"image/*");
            intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION); //must for reading data from directory
    

    【讨论】:

    • FLAG_GRANT_READ_URI_PERMISSION 帮助使用 Intent.ACTION_VIEW 查看图像
    • 为我工作。请记住,如果您使用的是“intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);”那么你必须添加“intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);”之后..感谢您提供的出色解决方案。
    【解决方案7】:

    对这个问题的更清晰、更安全的答案(你真的不应该对字符串进行硬编码):

    public void openInGallery(String imageId) {
      Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendPath(imageId).build();
      Intent intent = new Intent(Intent.ACTION_VIEW, uri);
      startActivity(intent);
    }
    

    您所要做的就是将图像 ID 附加到 EXTERNAL_CONTENT_URI 路径的末尾。然后使用 View 操作和 Uri 启动 Intent。

    图片id来自查询内容解析器。

    【讨论】:

    • 它是否允许用户滑动和滚动同一文件夹中的其他图像?
    【解决方案8】:

    以上所有答案都没有打开图片..当我第二次尝试打开它时显示画廊没有图片。

    我从各种 SO 答案中得到了解决方案..

    Intent galleryIntent = new Intent(Intent.ACTION_VIEW, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    galleryIntent.setDataAndType(Uri.fromFile(mImsgeFileName), "image/*");
    galleryIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(galleryIntent);
    

    这个只对我有用..

    【讨论】:

      【解决方案9】:

      使用Intent.ACTION_VIEW 显示文件的问题在于,如果您通过Uri 解析路径。并非在所有情况下都有效。要解决该问题,您需要使用:

      Uri.fromFile(new File(filePath));
      

      代替:

      Uri.parse(filePath);
      

      编辑

      这是我的完整代码:

      Intent intent = new Intent(Intent.ACTION_VIEW);
      intent.setDataAndType(Uri.fromFile(new File(mediaFile.filePath)), mediaFile.getExtension());
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      startActivity(intent);
      

      信息

      MediaFile 是我的域类,用于将数据库中的文件包装在对象中。 MediaFile.getExtension() 返回一个 StringMimetype 作为文件扩展名。示例:"image/png"


      附加代码:需要显示任何文件(扩展名)

      import android.webkit.MimeTypeMap;
      
      public String getExtension () {
          MimeTypeMap myMime = MimeTypeMap.getSingleton();
          return myMime.getMimeTypeFromExtension(MediaFile.fileExtension(filePath));
      }
      
      public static String fileExtension(String path) {
          if (path.indexOf("?") > -1) {
              path = path.substring(0, path.indexOf("?"));
          }
          if (path.lastIndexOf(".") == -1) {
              return null;
          } else {
              String ext = path.substring(path.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();
          }
      }
      

      如果您需要更多代码,请告诉我。

      【讨论】:

        【解决方案10】:

        我用这个对我有用

        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent,
        "Select Picture"), 1);
        

        【讨论】:

          【解决方案11】:

          我使用文件提供程序的解决方案

              private void viewGallery(File file) {
          
           Uri mImageCaptureUri = FileProvider.getUriForFile(
            mContext,
            mContext.getApplicationContext()
            .getPackageName() + ".provider", file);
          
           Intent view = new Intent();
           view.setAction(Intent.ACTION_VIEW);
           view.setData(mImageCaptureUri);
           List < ResolveInfo > resInfoList =
            mContext.getPackageManager()
            .queryIntentActivities(view, PackageManager.MATCH_DEFAULT_ONLY);
           for (ResolveInfo resolveInfo: resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            mContext.grantUriPermission(packageName, mImageCaptureUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
           }
           view.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
           Intent intent = new Intent();
           intent.setAction(Intent.ACTION_VIEW);
           intent.setDataAndType(mImageCaptureUri, "image/*");
           mContext.startActivity(intent);
          }
          

          【讨论】:

            【解决方案12】:

            几乎没有机会使用照片或画廊应用程序(可能存在),但您可以尝试内容查看器。

            请查看类似问题的另一个答案here

            【讨论】:

              【解决方案13】:

              我的解决方案

              Intent intent = new Intent();
              intent.setAction(Intent.ACTION_VIEW);
              intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory().getPath()+"/your_app_folder/"+"your_picture_saved_name"+".png")), "image/*");
              context.startActivity(intent);
              

              【讨论】:

                【解决方案14】:

                uri 必须是内容 uri 而不是文件 uri, 您可以通过 FileProvider 获取 contentUri 为

                Uri contentUri = FileProvider.getUriForFile(getContext(),"com.github.myApp",curFile);
                

                不要忘记在 Manifest 文件中添加提供者。

                <provider
                        android:name="androidx.core.content.FileProvider"
                        android:authorities="com.github.myApp"
                        android:exported="false"
                        android:grantUriPermissions="true">
                        <meta-data
                            android:name="android.support.FILE_PROVIDER_PATHS"
                            android:resource="@xml/provider_paths" />
                </provider>
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-07-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-01-04
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多