Otwórz obraz przy użyciu identyfikatora URI w domyślnej przeglądarce obrazów galerii Androida

84

Wyodrębniłem obraz uri, teraz chciałbym otworzyć obraz za pomocą domyślnej przeglądarki obrazów Androida. Lub jeszcze lepiej, użytkownik może wybrać program, którego ma użyć do otwarcia obrazu. Coś w rodzaju eksploratorów plików oferuje ci, jeśli spróbujesz otworzyć plik.

Badr Hari
źródło

Odpowiedzi:

168

Zaakceptowana odpowiedź nie działa dla mnie,

Co zadziałało:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + "/sdcard/test.jpg"), "image/*");
startActivity(intent);
Vikas
źródło
4
tak, ale jak uniknąć w Androidzie 2.2 i 2.3 tego 10-sekundowego czarnego ekranu, podczas gdy galeria mówi, że wyszukuje nowe zdjęcia i albumy?
max4ever
@ max4ever: Czy znalazłeś rozwiązanie swojego problemu?
Code_Life
4
tak,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 wyświetli obraz, jeśli podasz tylko „image / *”. To nie zadziała na Androidzie 2.3. MUSISZ określić typ MIME: „image / jpeg”.
AndroidDev,
6
Ta odpowiedź kończy się file:///sdcard...- czy to zamierzone?
Danyal Aytekin,
38

Jeśli Twoja aplikacja jest przeznaczona dla systemu Android N (7.0) lub nowszego, nie powinieneś używać powyższych odpowiedzi (metody „Uri.fromFile”), ponieważ to nie zadziała.

Zamiast tego należy użyć ContentProvider.

Na przykład, jeśli plik obrazu znajduje się w folderze zewnętrznym, możesz użyć tego (podobnie do kodu, który tutaj utworzyłem ):

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

oczywisty:

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

Jeśli twój obraz znajduje się w prywatnej ścieżce aplikacji, powinieneś utworzyć własny ContentProvider, ponieważ utworzyłem „OpenFileProvider” w linku.

programista Androida
źródło
Tak, tylko to działa i rozwiązało mój problem z Androidem N i Oreo. Bardzo dziękuję. Masz absolutną rację!
Serg Burlaka
Wielkie dzięki!! tylko to rozwiązanie działa dla nowszych wersji Androida
Divakar Rajesh
Czy dotyczy to również plików zapisanych w przestrzeni współdzielonej (karta SD)?
Albert221
@ Albert221 Powinno, ale nie sądzę, żebym to testował. Spróbuj i daj mi znać.
programista Androida
Nie działa na Androida 10 w przypadku, gdy mam Uri do obrazu zapisanego w Galerii
rommex
29

Zadaj sobie pytanie, odpowiedz sobie również:

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

Zapyta również, jakiego programu użyć do wyświetlenia pliku.

Badr Hari
źródło
2
Cześć hari, Twój kod jest przydatny do otwierania obrazu. Czy możesz mieć rozwiązanie, aby otworzyć folder galerii. oto moje pytanie stackoverflow.com/questions/6519024/…
djk
@djk Po prostu odpowiadam na to zadanie tutaj stackoverflow.com/questions/6074270/ ... zobacz, czy ma to związek z twoim pytaniem.
PiyushMishra
Na wypadek, gdyby ktoś inny utknął przy tym samym problemie co ja - dodałem intent.setType ("image / png") (wiedziałem, że obraz będzie plikiem png) i uniemożliwiło to otwarcie galerii! Tak więc .setType przynosi tutaj efekt przeciwny do zamierzonego :)
Daniel
Ponadto możesz użyć, intent.setDataAndType(uri, "image/*");aby zmusić Androida do korzystania z aplikacji do przeglądania obrazów.
Diego Stiehl
Czy można użyć tej metody, aby uniknąć tworzenia nowego układu tylko po to, aby wyświetlić obraz?
Marek
21

Spróbuj go użyć:

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);
Eugene
źródło
To jest doskonałe! Otwiera wyskakujące okienko / układ oparty na systemie operacyjnym Android, dzięki czemu użytkownik może wybrać gracza lub przeglądarkę na podstawie wyboru użytkownika. na przykład, aby pokazać obraz, muzykę, wideo, aplikację lub nawet dowolny plik.
Pratik Saluja
Pojawił się błąd „ujawniony poza aplikacją poprzez Intent.getData ()”.
Ramiz Ansari
Jeśli otrzymujesz błąd „ujawniony poza aplikacją przez Intent.getData ()”, możesz sprawdzić ten link, aby rozwiązać problem stackoverflow.com/a/45751453/10619147
Wojuola Ayotola
18

Na podstawie odpowiedzi Vikas, ale z niewielką modyfikacją: Uri jest odbierany przez parametr:

private void showPhoto(Uri photoUri){
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    intent.setDataAndType(photoUri, "image/*");
    startActivity(intent);
}
Joaquin Iurchuk
źródło
1
Pokazuje tylko jeden wybrany obraz, a nie inne obrazy w tym samym folderze (aby użytkownik mógł przesuwać palcem w lewo / w prawo, aby zobaczyć inne obrazy). Masz pomysł, jak to osiągnąć?
Atul
@Atul w takim przypadku przypadek użycia jest zupełnie inny. OP chce wyświetlić obraz X przy użyciu swojego URI. Wygląda na to, że chcesz a) otworzyć galerię w określonej pozycji lub b) otworzyć w galerii podzbiór zdjęć, których masz URI. Poszukaj informacji w sieci lub zadaj nowe pytanie, ponieważ Twój przypadek użycia jest zupełnie inny.
Joaquin Iurchuk
Dziękuję za szybką odpowiedź. Muszę osiągnąć to samo, o co prosił OP. Twoja (i Vikas) odpowiedź osiąga to bardzo dobrze, jedyną rzeczą jest to, że gdy pokazuje obraz, nie pozwala na przewijanie innych obrazów w tym samym folderze (gdy użytkownik przesuwa palcem w lewo lub w prawo). Widziałem wiele aplikacji (np. WhatsApp) wyświetlających obraz w przeglądarce galerii (tak jak to, co robisz), ale pozwalają one również użytkownikowi przewijać lewe prawe obrazy w tym samym folderze.
Atul
@Atul OP chce otworzyć jeden obraz z Galerią, podając jej identyfikator URI. Implementacja WhatsApp jest zupełnie inna. Nie wiem, czy Galeria obsługuje odbieranie intencji z wieloma identyfikatorami URI. W każdym razie, spójrz na to, może ci to pomóc.
Joaquin Iurchuk
Widziałem już link, który podałeś. W każdym razie dzięki. Ale odkryłem, że ktoś już opublikował pytanie o to, czego chcę. Jednak jego odpowiedź jest zbyt krótka, aby ją zrozumieć.
Atul
11

Ta rzecz może pomóc, jeśli pracujesz z Androidem N i starszymi

 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
źródło
FLAG_GRANT_READ_URI_PERMISSION pomógł w wyświetlaniu obrazu za pomocą Intent.ACTION_VIEW
Pavan
Pracował dla mnie. Pamiętaj tylko, jeśli używasz „intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);” następnie musisz dodać „intent.setFlags (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);” potem… Dzięki za świetne rozwiązanie.
snehal agrawal
6

O wiele czystsza i bezpieczniejsza odpowiedź na ten problem (naprawdę nie powinieneś twardo kodować ciągów znaków):

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

Wszystko, co musisz zrobić, to dołączyć identyfikator obrazu na końcu ścieżki dla EXTERNAL_CONTENT_URI . Następnie uruchom Intent za pomocą akcji View i Uri.

Identyfikator obrazu pochodzi z zapytania o program rozpoznawania treści.

Christopher Perry
źródło
Czy umożliwia użytkownikowi przesuwanie i przewijanie innych obrazów w tym samym folderze?
Atul
4

Wszystkie powyższe odpowiedzi nie otwierają obrazka ... kiedy drugi raz próbuję go otworzyć, pokaż galerię, a nie obraz.

Otrzymałem rozwiązanie z różnych odpowiedzi 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);

Ten działał tylko dla mnie.

Ranjith Kumar
źródło
4

Problem z wyświetlaniem pliku za pomocą Intent.ACTION_VIEWjest taki, że jeśli przejdziesz Uriparsowanie ścieżki. Nie działa we wszystkich przypadkach. Aby rozwiązać ten problem, musisz użyć:

Uri.fromFile(new File(filePath));

Zamiast:

Uri.parse(filePath);

Edytować

Oto mój pełny kod:

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

Informacje

MediaFileto moja klasa domeny do zawijania plików z bazy danych w obiekty. MediaFile.getExtension()zwraca Stringz Mimetypejako rozszerzenie pliku. Przykład:"image/png"


Kod dodatkowy: potrzebny do pokazania dowolnego pliku (rozszerzenia)

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

Daj mi znać, jeśli potrzebujesz więcej kodu.

IgniteCoders
źródło
3

Używam tego, to działa dla mnie

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), 1);
Muhammad Aamir Ali
źródło
2

Moje rozwiązanie przy użyciu dostawcy plików

    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
źródło
0

Prawie BRAK szansy na użycie aplikacji do zdjęć lub galerii (może taka istnieje), ale możesz wypróbować przeglądarkę treści.

Proszę kasy inną odpowiedź na podobne pytanie tutaj

TeeTracker
źródło
0

Moje rozwiązanie

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
źródło