Откройте изображение с помощью URI в программе просмотра изображений галереи Android по умолчанию

85

Я извлек изображение uri, теперь я хотел бы открыть изображение с помощью программы просмотра изображений Android по умолчанию. Или, что еще лучше, пользователь мог выбрать, какую программу использовать для открытия изображения. Что-то вроде File Explorer предлагает вам, если вы попытаетесь открыть файл.

Бадр Хари
источник

Ответы:

168

Принятый ответ не работал у меня,

Что сработало:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + "/sdcard/test.jpg"), "image/*");
startActivity(intent);
Викас
источник
4
да, но как избежать 10 секунд ожидания черного экрана на Android 2.2 и 2.3, пока галерея сообщает, что ищет новые фотографии и альбомы?
max4ever
@ max4ever: Нашли решение вашей проблемы?
Code_Life 08
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
1
Android 4.1 покажет вам изображение, если вы укажете только «image / *». Это не будет работать на Android 2.3. Вы ДОЛЖНЫ указать тип пантомимы: "image / jpeg".
AndroidDev
6
Этот ответ заканчивается вопросом file:///sdcard...- это намеренно?
Даньял Айтекин
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
источник
Да, только это работает и решает мою проблему с Android N и Oreo. Спасибо большое. Вы абсолютно правы!
Серг Бурлака
Большое спасибо!! только это решение работает для более новых версий Android
Divakar Rajesh
Относится ли это также к файлам, сохраненным в общем пространстве (SD-карта)?
Albert221
@ Albert221 Должен, но не думаю, что я это проверял. Пожалуйста, дайте мне знать.
разработчик Android
Не работает на Android 10, если у меня есть Uri для изображения, сохраненного в галерее
rommex
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
На всякий случай, если кто-то застрянет в той же проблеме, что и я - я добавил intent.setType ("image / png") (я знал, что изображение будет файлом png), и это помешало галерее открыть изображение! Так что .setType здесь контрпродуктивен :)
Дэниел
Кроме того, вы можете использовать, intent.setDataAndType(uri, "image/*");чтобы заставить Android использовать приложение для просмотра изображений.
Diego Stiehl
Можно ли использовать этот метод, чтобы избежать создания нового макета только для просмотра изображения?
Марек
21

Попробуйте использовать это:

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, так что пользователь может выбрать игрока или зрителя на основе выбора пользователя. Например, чтобы показать изображение, музыку, видео, приложение или даже любой файл.
Pratik Saluja 06
У меня возникла ошибка «Открыто за пределами приложения через Intent.getData ()».
Ramiz Ansari
Если вы получаете сообщение об ошибке «За пределами приложения через 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 в этом случае вариант использования совершенно другой. OP хочет отобразить изображение X, используя свой URI. Похоже, вы хотите: а) открыть галерею в определенном месте или б) открыть в галерее подмножество фотографий, для которых у вас есть URI. Поищите в Интернете или задайте новый вопрос, так как ваш вариант использования совершенно другой.
Хоакин Юрчук
Спасибо за ваш быстрый ответ. Мне нужно добиться того же, о чем просил OP. Ваш (и Викас) ответ очень хорошо справляется с этим. Единственное, что когда он показывает изображение, он не позволяет прокручивать другие изображения в той же папке (когда пользователь проводит пальцем влево или вправо). Я видел, как многие приложения (например, WhatsApp) отображают изображения в средстве просмотра галереи (точно так же, как и вы), но они также позволяют пользователю прокручивать левые и правые изображения в той же папке.
Атул
@Atul OP хочет открыть одно изображение с помощью Gallery, учитывая его URI. Реализация WhatsApp совершенно другая. Я не знаю, поддерживает ли Галерея получение намерений со многими URI. В любом случае, проверьте это, это может вам помочь.
Хоакин Юрчук
Я уже видел ссылку, которую вы дали. В любом случае спасибо. Но я обнаружил, что кто-то уже разместил вопрос о том, что я хочу. Однако его ответ слишком краток, чтобы его можно было понять.
Атул
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
Baswaraj
источник
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); после этого .. Спасибо за отличное решение.
снехал агравал
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);
}

Все, что вам нужно сделать, это добавить идентификатор изображения в конец пути для EXTERNAL_CONTENT_URI . Затем запустите Intent с действием View и Uri.

Идентификатор изображения поступает из запроса преобразователя контента.

Кристофер Перри
источник
Позволяет ли он пользователю пролистывать и пролистывать другие изображения в той же папке?
Атул
4

Все приведенные выше ответы не открывают изображение ... когда я второй раз пытаюсь открыть его, отображается галерея, а не изображение.

Я получил решение из смеси различных ответов 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);

Этот работал только у меня ..

Ранджит Кумар
источник
4

Проблема с отображением файла using 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()возвращает Stringс 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();
    }
}

Дайте мне знать, если вам понадобится больше кода.

IgniteCoders
источник
3

Я использую это работает для меня

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), 1);
Мухаммад Аамир Али
источник
2

Мое решение с использованием поставщика файлов

    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);
}
creativecoder
источник
0

Практически НЕТ возможности использовать приложение для фотографий или галереи (может существовать), но вы можете попробовать программу просмотра контента.

Пожалуйста, ознакомьтесь с другим ответом на аналогичный вопрос здесь

TeeTracker
источник
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);
Knightcube
источник