Відкрийте зображення за допомогою URI у типовому засобі перегляду зображень галереї Android


84

Я витягнув зображення 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
так, але як уникнути на Android 2.2 та 2.3 того 10-секундного чорного екрану, який чекає, поки галерея каже, що шукає нові фотографії та альбоми?
max4ever

@ max4ever: Ви знайшли рішення своєї проблеми?
Code_Life

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. Ви ПОВИННІ вказати тип mime: "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 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, щоб застосувати програму перегляду зображень.
Дієго Стіл

Чи можна цим методом уникнути створення нового макета лише для перегляду зображення?
Марек

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, так що користувач може вибрати плеєр або переглядач на основі вибору користувача. наприклад, щоб показати зображення, музику, відео, програму або навіть будь-який файл.
Pratik Saluja

Я отримав помилку "виставлено за межі програми через Intent.getData ()".
Раміз Ансарі

Якщо ви отримуєте «викрив за додаток через Intent.getData ()» помилки ви можете перевірити це посилання , щоб вирішити проблему stackoverflow.com/a/45751453/10619147
Wojuola Ayotola

18

На основі відповіді Vikas, але з невеликими змінами: 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. Здається, ви хочете a) Відкрити галерею у визначеному положенні або b) Відкрити в галереї підмножину фотографій, для яких у вас є URI. Проведіть дослідження в Інтернеті або задайте нове запитання, оскільки ваш варіант використання зовсім інший.
Хоакін Ірчук

Дякуємо за швидку відповідь. Мені потрібно досягти того самого, що просив ОП. Ваша відповідь (і відповідь Вікаса) досягає цього дуже добре. Тільки справа, коли воно показує зображення, воно не дозволяє прокручувати інші зображення в тій же папці (коли користувач проводить пальцем ліворуч або праворуч). Я бачив, як багато програм (наприклад, WhatsApp) показують зображення в засобі перегляду галереї (як і те, що ви робите), але вони також дозволяють користувачеві прокручувати ліві праві зображення в тій самій папці.
Атул

@Atul OP хоче відкрити одне зображення в галереї з урахуванням її 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

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);" після цього .. Дякую за чудове рішення.
snehal agrawal

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

Проблема показу файлу за допомогою 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();
    }
}

Повідомте мене, якщо вам потрібен додатковий код.


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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.