在Android的默认图库图片查看器中使用URI打开图片


83

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

Answers:


168

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

起作用的是:

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

4
是的,但是您如何避免在Android 2.2和2.3上等待10秒的黑屏,而图库却说它正在搜索新的照片和专辑呢?
2012年

@ max4ever:找到解决您问题的方法了吗?
Code_Life 2012年

4
是的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); } });
max4ever 2012年

1
如果您仅指定“ image / *”,则Android 4.1将向您显示图像。这不适用于Android 2.3。您必须指定哑剧类型:“ image / jpeg”。
AndroidDev

6
这个答案最终以file:///sdcard...-是故意的吗?
Danyal Aytekin 2014年

38

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

相反,您应该使用ContentProvider。

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

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解决了我的问题。非常感谢。你是绝对正确的!
Serg Burlaka '18年

非常感谢!!仅此解决方案适用于android较新版本
Divakar Rajesh

它也适用于共享空间(SD卡)中保存的文件吗?
Albert221 '19

@ Albert221应该,但是我认为我没有测试过。请尝试让我知道。
Android开发人员

万一我将Uri图像保存到图库

29

问问自己,也回答自己:

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

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


2
嗨,哈里,您的代码对于打开图像很有用。您能为打开图库文件夹提供解决方案吗?这里是我的问题stackoverflow.com/questions/6519024/...
DJK

@ djk我只是在这里回答这个问题stackoverflow.com/questions/6074270/…看看它是否与您的问题有关。
PiyushMishra 2011年

以防万一有人陷入与我相同的问题-我添加了intent.setType(“ image / png”)(我知道该图像将是png文件),并且它阻止了画廊打开该图像!所以.setType在这里适得其反:)
Daniel

此外,您可以intent.setDataAndType(uri, "image/*");用来强制Android使用图像查看应用程序。
迭戈·斯蒂尔2014年

可以使用这种方法来避免仅为了查看图像而创建新的布局吗?
力克(Marek)2015年

20

尝试使用它:

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打开弹出窗口/布局,以便用户可以根据用户选择选择播放器或查看器。例如,显示图像,音乐,视频,应用程序甚至任何文件。
Pratik Saluja,2013年

我收到“通过Intent.getData()暴露给应用程序之外的错误”错误。
拉米兹·安萨里

如果您收到“通过Intent.getData()在应用程序之外公开”错误,则可以检查此链接以解决问题stackoverflow.com/a/45751453/10619147
Wojuola Ayotola

18

基于维卡斯的答案,但稍作修改:通过参数接收Uri:

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

1
这仅显示单个选择的图像,而不显示同一文件夹中的其他图像(以便用户可以向左/向右滑动以查看其他图像)。任何想法如何实现这一目标?
Atul 2016年

在这种情况下,@ Atul的用例是完全不同的。OP希望使用其URI显示X图像。似乎您想要a)在确定的位置打开画廊,或者b)在画廊中打开您具有URI的照片子集。由于您的用例完全不同,因此可以在网络上进行一些研究或提出新问题。
Joaquin Iurchuk '16

感谢您的快速回复。我需要达到OP要求的相同条件。您(和Vikas的)答案可以很好地实现这一点,唯一的是,一旦它显示了图像,就不允许滚动浏览同一文件夹中的其他图像(当用户向左或向右滑动时)。我已经看到许多应用程序(例如WhatsApp)在图库查看器中显示图像(就像您所做的一样),但它们还允许用户在同一文件夹中左右滚动图像。
Atul 2016年

@Atul OP希望使用给定其URI的Gallery打开一个图像。WhatsApp的实现是完全不同的。我不知道Gallery是否支持接收带有许多URI的Intent。无论如何,请查看此内容,它可能会对您有所帮助。
Joaquin Iurchuk '16

我已经看过您给出的链接。不管怎么说,多谢拉。但是我发现有人已经对我想要的内容发表了疑问。但是,他的答案太简短了,难以理解。
Atul 2016年

11

如果您使用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帮助查看图像
Pavan,

为我工作。请记住,如果您使用的是“ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);” 那么您必须添加“ intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);” 之后。.感谢您的出色解决方案。
悄悄

6

一个更干净,更安全的解决方案(您实际上不应该对字符串进行硬编码):

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的路径末尾。然后使用“视图”操作和Uri启动一个Intent。

图像ID来自查询内容解析器。


它是否允许用户在同一文件夹中的其他图像上滑动和滚动?
Atul 2016年

4

以上所有答案均未打开图片。.当我第二次尝试打开它时,显示图库未图片。

我从各种各样的答案中得到了解决方案。

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

这只对我有用。


4

使用显示文件的问题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()返回Stringwith Mimetype。例:"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();
    }
}

让我知道您是否需要更多代码。


3

我用它对我有用

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

1

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

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

0

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

在此处签出类似问题的其他答案


0

我的解决方案

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.