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

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

178727 次浏览

Ask myself, answer myself also:

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

It will also ask what program to use to view the file.

Accepted answer was not working for me,

What had worked:

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

Try use it:

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

A much cleaner, safer answer to this problem (you really shouldn't hard code Strings):

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

All you have to do is append the image id to the end of the path for the EXTERNAL_CONTENT_URI. Then launch an Intent with the View action, and the Uri.

The image id comes from querying the content resolver.

I use this it works for me

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

Based on Vikas answer but with a slight modification: The Uri is received by parameter:

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

Almost NO chance to use photo or gallery application(might exist one), but you can try the content-viewer.

Please checkout another answer to similar question here

All the above answers not opening image.. when second time I try to open it show the gallery not image.

I got solution from mix of various SO answers..

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

This one only worked for me..

If your app targets Android N (7.0) and above, you should not use the answers above (of the "Uri.fromFile" method), because it won't work for you.

Instead, you should use a ContentProvider.

For example, if your image file is in external folder, you can use this (similar to the code I've made 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);

manifest:

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

If your image is in the private path of the app, you should create your own ContentProvider, as I've created "OpenFileProvider" on the link.

This thing might help if your working with android N and below

 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

The problem with showing a file using Intent.ACTION_VIEW, is that if you pass the Uri parsing the path. Doesn't work in all cases. To fix that problem, you need to use:

Uri.fromFile(new File(filePath));

Instead of:

Uri.parse(filePath);

Edit

Here is my complete code:

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

Info

MediaFile is my domain class to wrap files from database in objects. MediaFile.getExtension() returns a String with Mimetype for the file extension. Example: "image/png"


Aditional code: needed for showing any file (extension)

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

Let me know if you need more code.

My solution

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

My solution using File Provider

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

The uri must be content uri not file uri, You can get contentUri by FileProvider as

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

Don't forget adding provider in Manifest file.

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