Зображення, збережене на SD-картці, не відображається в програмі Галерея Android


93

Я зберігаю зображення на SD-картці, і воно не з’являється в програмі „Галерея”, доки я не зніму його і не поверну назад.

Ви уявляєте, чому це так?

Здається, програма Галерея має певний кеш, який не оновлюється при збереженні файлу ...

Насправді, я також хочу відкрити щойно збережене зображення у програмі Gallery і не маю успіху, оскільки
це моє запитання щодо цієї проблеми.


1
Це питання було дано відповіді крок за кроком в цьому підручнику: stackoverflow.com/questions/30506301 / ...
Takermania

Відповіді:


45

Під час встановлення система сканує SD-карту, щоб знайти будь-які нові файли зображень (та інші). Якщо ви програмно додаєте файл, ви можете використовувати цей клас:

http://developer.android.com/reference/android/media/MediaScannerConnection.html


4
Примітка: Незважаючи на те, що питання стосується додавання файлів, MediaScannerConnection не надає рішення для видалення файлу - навіть під час запиту на сканування батьківської папки видаленого файлу.
AlikElzin-kilaka

86

Більш простим рішенням є використання статичного зручного методу scanFile () :

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

де thisваша діяльність (або будь-який інший контекст), mime-тип необхідний лише в тому випадку, якщо ви використовуєте нестандартні розширення файлів, а nullдля необов’язкового зворотного виклику (що нам не потрібно в такому простому випадку).


2
Spot on, метод трансляції, який пропонують інші (і Google), дуже рідко працює).
Кріс Дженкінс,

2
Це працювало для мене у попередніх версіях для Android ~ 4.0, але зараз у версії 4.3+, схоже, не працює. Зображення не відображаються в програмі галереї.
hooby3dfx

Ідеально! Ви можете отримати контекст за допомогою: Android.App.Application.Context
липень

Працював у зефірі
Хітеш Саху

66

Моя відповідь на вихідне запитання та на всіх, хто може мати цю проблему:

У мене була та сама проблема, зображення в моєму додатку, які люди, збережені на SD-карті, не відображались у їх галереї відразу. Після деяких пошуків я знайшов цей рядок коду, вставлений після мого коду "зберегти на SDCard", який вирішив проблему:

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

нам потрібно використовувати сканер мультимедіа, щоб мати можливість використовувати цю трансляцію? я використовую інший метод для відображення зображень у своїй галереї. Коли я використовую вище sendBroadcast на кнопку збереження, клацніть мою галерею не оновлено з новим зображенням!
зміна

4
Він старий, але це може комусь допомогти - більш конкретний шлях: sendBroadcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); Цей метод (ця відповідь, а не лише мій коментар) не працює на емуляторі. Тест на реальному пристрої.

Я вважаю, що прийнята відповідь пропонує правильний спосіб це зробити. Але якщо ви намагаєтесь підтримати API <= 7, то це приємний запасний варіант.
Амр Мостафа

Ваша відповідь корисна для інших пристроїв. Це не працює на HTC, коли я намагаюся відсканувати папку своїх програм. Не відображається нещодавно додане зображення.
MobileEvangelist

6
Здається, це більше не підтримується на Android 4.4 та новіших версіях. У цьому випадку буде видано виняток з дозволу.
rsp1984

13

Ви також можете додати зображення до медіа-галереї за наміром, подивіться на приклад коду, щоб побачити, як це робиться:

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

Привіт. Цей метод додає зображення до MediaStore, я підтвердив це, перевіривши повернене, Uriале проблема полягає в тому, що вставлене зображення не відображається в галереї. Я перевірив і на початку, і в кінці галереї. Чи можете ви запропонувати будь-який спосіб, щоб вставлене зображення негайно відображалося в галереї?
Shajeel Afzal

12

Оновлення галереї, включаючи 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())));
}

Код, що знаходиться в першій умові з оператором "IF", прекрасно працює для мене в KitKat (Android 4.4.4, API 19).
Олексій

8

Ось код для MediaScannerConnection:

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

newfile - це об'єкт File вашого нового / збереженого файлу.


2
Спасибі за вашу відповідь. Власне, я вже давно закінчив цей проект ... Навіть не пам’ятаю, яке рішення я використовував. Інші користувачі можуть знайти ваше рішення корисним, якщо ви також надасте імплементацію MyMediaConnectorClient...
Майкл Кесслер,

так - у мене зараз справді болить голова. Будь ласка, повідомте :)
Стів

Так, я не зовсім зрозумів, яким повинен бути потік - Виправте мене, де я помиляюся, я можу використовувати MediaScannerConnection для оновлення інформації SDCAARD, тому я фотографую камерою і передаю новий файл в MSC, і тепер я можу отримати доступ до файлу з клієнтом сканера підключення?
Стів

Потік такий: ви робите знімок, зберігаєте його на своїй SD-картці, а потім оновлюєте сканер, щоб файлова система оновлювалася, щоб побачити збережену картинку в галереї пристрою. Якщо ви цього не зробите зі сканером, ви побачите свою фотографію після наступного перезапуску пристрою в галереї.
3dmg

7

в емуляторі є додаток із написом - 'Dev Tools'

клацніть на ньому та виберіть "Сканування носія". Усі зображення будуть відскановані


чудово знати, єдиний спосіб, який я знав до того, як ти сказав, - це перезавантажити телефон :)
mishkin

6

Нехай ваша діяльність реалізує 'MediaScannerConnectionClient' і додайте це до своєї діяльності:

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

Привіт! Що, якби ми знали Uriзображення, наприклад:content://media/external/images/media/1231778
Shajeel Afzal


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

Я хочу зберегти анімований файл GIF, який знаходиться у зовнішній пам'яті, і у мене є шлях, тобто / storage / emulated / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif. Тепер я хочу зберегти / скопіювати цей файл у Галерею зображень і показати там. Як це зробити.
Zia Ur Rahman

3

Тут я ділюсь кодом, який може завантажувати зображення у вигляді растрового зображення та зберігати це зображення в галереї SDCard у папці імені програми. Вам слід виконати ці кроки

  1. Спочатку завантажте растрове зображення



     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. Будь ласка, надайте наступний дозвіл у своєму файлі AndroidManifest.xml.


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


  1. Ось цілий код, який написаний на Activty, в якому ми хочемо виконати це завдання.



     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. Сподіваюся, що це може вирішити всю вашу проблему.

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

Здається, не працює на KITKAT. Він видає виняток про відмову в дозвілі та аварійно завершує роботу програми. Отже, для цього я зробив наступне,

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

Сподіваюся, це допоможе.


2

Використовуйте це після збереження зображення

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

3
Це працює, але це не найкраще рішення. Ви обманюєте систему, думаючи, що SD-карта буде (пере) встановлена, і, можливо, змусить повторно сканувати всю SD-карту. MediaScanner.scanFile (..) - найкраще рішення, коли ви тепер додаєте файл, який хочете додати.
pocmo

1
Це пошук усіх зображень. І це передбачає багато непотрібної обробки даних, що може бути несуттєвим, коли ми маємо лише одне зображення, яке буде показано в галереї.
Рахул Растогі,

2

Мій код для 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

Вам потрібно надати дозволи додатку Галерея. Просто натисніть і утримуйте піктограму програми галереї на головному екрані та натисніть "ІНФОРМАЦІЯ ПРО ДОДАТОК", яка з’явиться у верхній частині екрана. Виконання цього покаже налаштування програми галереї. Тепер перейдіть на вкладку «Дозволи» та ввімкніть сховище, дозволи камери, перемикаючи його. Тепер перейдіть до рідної програми галереї, і ви отримаєте збережені зображення.


0

Це також вирішить вашу проблему, якщо ваше зображення в галереї не відображається, натомість може відображатися растрове зображення типу 404 в midle. Будь ласка, додайте до вашого зображення теги, які містяться в моєму коді, оскільки для показу зображення в галереї потрібно мати кілька метаданих.

      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

Спробуйте цей, він транслюватиме нове створене зображення, щоб ваше зображення було видимим. всередині галереї. photoFile замінити фактичним шляхом до файлу новоствореного зображення

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.