Obraz zapisany na karcie SD nie pojawia się w aplikacji Galeria Androida


93

Zapisuję obraz na karcie SD i nie pojawia się on w aplikacji Galeria, dopóki nie wyciągnę karty sd i nie zwrócę jej.

Czy masz pojęcie, dlaczego tak jest?

Wygląda na to, że aplikacja Galeria ma pamięć podręczną, która nie jest aktualizowana podczas zapisywania pliku ...

Właściwie to też chcę otworzyć właśnie zapisany obraz w aplikacji Galeria i bez powodzenia
to jest moje pytanie w tej sprawie.


1
Na to pytanie udzielono odpowiedzi krok po kroku w tym samouczku: stackoverflow.com/questions/30506301/…
Takermania

Odpowiedzi:



86

Prostszym rozwiązaniem jest użycie statycznej wygodnej metody scanFile () :

File imageFile = ...
MediaScannerConnection.scanFile(this, new String[] { imageFile.getPath() }, new String[] { "image/jpeg" }, null);

gdzie thisjest twoja aktywność (lub w jakimkolwiek kontekście), typ MIME jest potrzebny tylko wtedy, gdy używasz niestandardowych rozszerzeń plików, a nulljest dla opcjonalnego wywołania zwrotnego (którego nie potrzebujemy w tak prostym przypadku).


2
Doskonale, metoda nadawania, którą oferują inni (i Google), bardzo rzadko działa).
Chris.Jenkins

2
To działało dla mnie we wcześniejszych wersjach Androida ~ 4.0, ale teraz w 4.3+ nie wydaje się działać. Obrazy nie pojawiają się w aplikacji Galeria.
hooby3dfx

Idealny ! Możesz uzyskać kontekst za pomocą: Android.App.Application.Context
dzban

Pracował w ptasie mleczko
Hitesh Sahu

66

Moja odpowiedź na pierwotne pytanie i dla każdego, kto może mieć ten problem:

Miałem ten sam problem, obrazy w mojej aplikacji, które ludzie zapisywali na karcie SD, nie pojawiały się natychmiast w ich Galerii. Po kilku poszukiwaniach znalazłem ten jeden wiersz kodu wstawiony po moim kodzie `` zapisz na sdcard '', który rozwiązał problem:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

czy musimy używać skanera multimediów, aby móc korzystać z tej transmisji? używam innej metody wyświetlania obrazów w mojej galerii. Kiedy używam powyższego przycisku sendBroadcast przy zapisywaniu kliknij, moja galeria nie jest aktualizowana o nowy obraz!
zmiana

4
Jest stary, ale może komuś pomóc - bardziej szczegółowa ścieżka: sendBroadcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); Ta metoda (ta odpowiedź, nie tylko mój komentarz) nie działa na emulatorze. Przetestuj na prawdziwym urządzeniu.

Uważam, że zaakceptowana odpowiedź to właściwy sposób. Ale jeśli próbujesz obsługiwać API <= 7, jest to miła opcja zastępcza.
Amr Mostafa

Twoja odpowiedź jest pomocna w przypadku innych urządzeń. Nie działa na HTC, kiedy próbuję przeskanować folder aplikacji. Nie wyświetla nowo dodanego obrazu.
MobileEvangelist

6
Wygląda na to, że nie jest już obsługiwane w systemie Android 4.4 lub nowszym. W takim przypadku zostanie zgłoszony wyjątek dotyczący uprawnień.
rsp1984

13

Możesz również dodać obraz do galerii multimediów celowo, spójrz na przykładowy kod, aby zobaczyć, jak to się robi:

ContentValues image = new ContentValues();

image.put(Images.Media.TITLE, imageTitle);
image.put(Images.Media.DISPLAY_NAME, imageDisplayName);
image.put(Images.Media.DESCRIPTION, imageDescription);
image.put(Images.Media.DATE_ADDED, dateTaken);
image.put(Images.Media.DATE_TAKEN, dateTaken);
image.put(Images.Media.DATE_MODIFIED, dateTaken);
image.put(Images.Media.MIME_TYPE, "image/png");
image.put(Images.Media.ORIENTATION, 0);

 File parent = imageFile.getParentFile();
 String path = parent.toString().toLowerCase();
 String name = parent.getName().toLowerCase();
 image.put(Images.ImageColumns.BUCKET_ID, path.hashCode());
 image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
 image.put(Images.Media.SIZE, imageFile.length());

 image.put(Images.Media.DATA, imageFile.getAbsolutePath());

 Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);

Cześć. Ta metoda dodaje obraz do MediaStore, potwierdziłem to, sprawdzając zwrócony, Uriale problem polega na tym, że wstawiony obraz nie jest wyświetlany w galerii. Sprawdziłem zarówno na początku, jak i na końcu galerii. Czy może Pan zaproponować jakąś metodę, aby wstawiony obraz od razu pojawił się w galerii?
Shajeel Afzal

12

Odświeżenie galerii, w tym Android KITKAT

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
}
else
{
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}

Kod znajdujący się w pierwszym warunku z wyrażeniem „IF” działa dobrze dla mnie w KitKat (Android 4.4.4, API 19).
Alex

8

Oto kod MediaScannerConnection:

MyMediaConnectorClient client = new MyMediaConnectorClient(newfile);
MediaScannerConnection scanner = new MediaScannerConnection(context, client);
client.setScanner(scanner);
scanner.connect();

nowy plik to obiekt File nowego / zapisanego pliku.


2
Dziękuję za Twoją odpowiedź. Właściwie to już dawno skończyłem ten projekt ... Nawet nie pamiętam, jakie rozwiązanie zastosowałem. Inni użytkownicy mogą znaleźć swoje rozwiązanie pomocne, jeśli chcesz również zapewnić realizację MyMediaConnectorClient...
Michael Kessler

tak - w tej chwili mam z tym prawdziwy ból głowy. Proszę pisać :)
Steve

Tak, nie bardzo wiem, jak powinien wyglądać przepływ -Popraw mnie tam, gdzie się mylę Mogę użyć MediaScannerConnection do zaktualizowania informacji SDCAARD, więc robię zdjęcie aparatem i przekazuję nowy plik do MSC i teraz mam dostęp do pliku z klientem skanera połączeń?
Steve

Przepływ jest następujący: robisz zdjęcie, zapisujesz je na karcie sd, a następnie aktualizujesz skaner, aby system plików został zaktualizowany, aby zobaczyć zapisane zdjęcie w galerii urządzeń. Jeśli nie zrobisz tego za pomocą skanera, zobaczysz swoje zdjęcie po ponownym uruchomieniu urządzenia w galerii.
3dmg

7

w emulatorze jest aplikacja z napisem „Dev Tools”

kliknij na to i wybierz „Skanowanie multimediów”. Wszystkie obrazy zostaną zeskanowane


wspaniale wiedzieć, jedyny sposób, w jaki wiedziałem, zanim powiedziałeś, to ponowne uruchomienie telefonu :)
mishkin

6

Pozwól swojej aktywności zaimplementować 'MediaScannerConnectionClient' i dodaj to do swojej aktywności:

private void startScan() 
{ 
    if(conn!=null) conn.disconnect();  
    conn = new MediaScannerConnection(YourActivity.this,YourActivity.this); 
    conn.connect(); 
} 

@Override 
public void onMediaScannerConnected() { 
    try{
        conn.scanFile(yourImagePath, "image/*");
       } catch (java.lang.IllegalStateException e){
       }
}

@Override 
public void onScanCompleted(String path, Uri uri) { 
    conn.disconnect(); 
} 

Cześć! A co jeśli znamy Urizdjęcie, na przykład:content://media/external/images/media/1231778
Shajeel Afzal

6

ta praca ze mną

File file = ..... // Save file

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

4
 File folderGIF = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/newgif2");    //path where gif will be stored
success = folderGIF.mkdir();    //make directory
 String finalPath = folderGIF + "/test1.gif";  //path of file
.....
/* changes in gallery app if any changes in done*/
 MediaScannerConnection.scanFile(this,
                    new String[]{finalPath}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);
                        }
                    });

Chcę zapisać animowany plik gif, który znajduje się w pamięci zewnętrznej i mam ścieżkę tj. / Storage / emulated / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif. Teraz chcę zapisać / skopiować ten plik do galerii obrazów i pokazać tam. Jak to zrobić.
Zia Ur Rahman

3

Tutaj udostępniam kod, który może załadować obraz w postaci mapy bitowej z i zapisać ten obraz w galerii sdcard w folderze nazwy aplikacji. Powinieneś wykonać następujące kroki

  1. Najpierw pobierz obraz bitmapowy



     private Bitmap loadBitmap(String url) {
        try {
            InputStream in = new java.net.URL(url).openStream();
            return BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
       }


  1. Podaj również następujące uprawnienia w pliku AndroidManifest.xml.


    uses-permission android:name="android.permission.INTERNET" 
    uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"


  1. Oto cały kod napisany w Activty, w którym chcemy wykonać to zadanie.



     void saveMyImage(String appName, String imageUrl, String imageName) {

            Bitmap bmImg = loadBitmap(imageUrl);
            File filename;
            try {
                String path1 = android.os.Environment.getExternalStorageDirectory()
                        .toString();
                File file = new File(path1 + "/" + appName);
                if (!file.exists())
                    file.mkdirs();
                filename = new File(file.getAbsolutePath() + "/" + imageName
                        + ".jpg");
                FileOutputStream out = new FileOutputStream(filename);
                bmImg.compress(Bitmap.CompressFormat.JPEG, 90, out);
                out.flush();
                out.close();
                ContentValues image = new ContentValues();
                image.put(Images.Media.TITLE, appName);
                image.put(Images.Media.DISPLAY_NAME, imageName);
                image.put(Images.Media.DESCRIPTION, "App Image");
                image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
                image.put(Images.Media.MIME_TYPE, "image/jpg");
                image.put(Images.Media.ORIENTATION, 0);
                File parent = filename.getParentFile();
                image.put(Images.ImageColumns.BUCKET_ID, parent.toString()
                        .toLowerCase().hashCode());
                image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName()
                        .toLowerCase());
                image.put(Images.Media.SIZE, filename.length());
                image.put(Images.Media.DATA, filename.getAbsolutePath());
                Uri result = getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
                Toast.makeText(getApplicationContext(),
                        "File is Saved in  " + filename, Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }


  1. Mam nadzieję, że może rozwiązać cały twój problem.

3
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

Wydaje się, że nie działa na KITKAT. Zgłasza wyjątek odmowy uprawnień i powoduje awarię aplikacji. W tym celu wykonałem następujące czynności:

String path = mediaStorageDir.getPath() + File.separator
                    + "IMG_Some_name.jpg";
CameraActivity.this.sendBroadcast(new Intent(
                             Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
                            .parse("file://" + path)));

Mam nadzieję, że to pomoże.


2

Użyj tego po zapisaniu obrazu

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

3
To działa, ale nie jest to najlepsze rozwiązanie. Oszukasz system, myśląc, że karta SD zostanie (ponownie) zamontowana i prawdopodobnie wymusisz ponowne przeskanowanie całej karty SD. MediaScanner.scanFile (..) jest najlepszym rozwiązaniem w przypadku pliku, który chcesz dodać.
pocmo

1
To wyszukiwanie wszystkich obrazów. I wiąże się z dużą ilością niepotrzebnego przetwarzania danych, które mogą być nieistotne, gdy mamy tylko jeden obraz do pokazania w galerii.
Rahul Rastogi

2

Mój kod dla MyMediaConnectorClient:

public class MyMediaConnectorClient implements MediaScannerConnectionClient {

    String _fisier;
    MediaScannerConnection MEDIA_SCANNER_CONNECTION;

    public MyMediaConnectorClient(String nume) {
        _fisier = nume;
    }

    public void setScanner(MediaScannerConnection msc){
        MEDIA_SCANNER_CONNECTION = msc;
    }

    @Override
    public void onMediaScannerConnected() {
        MEDIA_SCANNER_CONNECTION.scanFile(_fisier, null);
    }

    @Override
    public void onScanCompleted(String path, Uri uri) {
        if(path.equals(_fisier))
            MEDIA_SCANNER_CONNECTION.disconnect();
    }
}

0

Musisz nadać uprawnienia aplikacji Galeria. Po prostu naciśnij i przytrzymaj ikonę aplikacji galerii na ekranie głównym i dotknij opcji „INFORMACJE O APLIKACJI”, która pojawi się u góry ekranu. Spowoduje to wyświetlenie ustawień aplikacji Galeria. Teraz przejdź do zakładki Uprawnienia i włącz przechowywanie, uprawnienia kamery, przełączając je. Teraz przejdź do swojej natywnej aplikacji galerii, a otrzymasz zapisane obrazy.


0

To również rozwiąże problem, jeśli obraz w galerii nie jest wyświetlany, zamiast tego może wyświetlać bitmapę typu 404 w środku. dodaj tagi, które są w moim kodzie z twoim obrazem, ponieważ muszą istnieć metadane, aby wyświetlić obraz w galerii.

      String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+ 
      getString(R.string.directory) + System.currentTimeMillis() + ".jpg";

       new File(resultPath).getParentFile().mkdir();

        try {
            OutputStream fileOutputStream = new FileOutputStream(resultPath);
            savedBitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        savedBitmap.recycle();

        File file = new File(resultPath);
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "Photo");
        values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis ());
        values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put(MediaStore.Images.ImageColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
        values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
        values.put("_data", resultPath);

        ContentResolver cr = getContentResolver();
        cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);




        return  resultPath;

0

Wypróbuj ten, będzie emitować informacje o utworzonym nowym obrazie, dzięki czemu Twój obraz będzie widoczny. wewnątrz galerii. PhotoFile zastąp rzeczywistą ścieżką pliku nowo utworzonego obrazu

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.