A imagem, salva no sdcard, não aparece no aplicativo Galeria do Android


92

Eu salvo uma imagem no sdcard e ela não aparece no aplicativo Gallery até que eu retire o sdcard e o devolva.

Você tem alguma ideia do porquê?

Parece que o aplicativo Gallery tem algum cache que não é atualizado ao salvar o arquivo ...

Na verdade, também quero abrir a imagem que acabei de salvar no aplicativo Gallery e não tenho sucesso com isso,
essa é a minha dúvida sobre esse assunto.


1
Esta pergunta foi respondida passo a passo neste tutorial: stackoverflow.com/questions/30506301/…
Takermania

Respostas:


45

O sistema verifica o cartão SD quando ele é montado para encontrar novos arquivos de imagem (e outros). Se você estiver adicionando um arquivo programaticamente, poderá usar esta classe:

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


4
Observação lateral: embora a pergunta se refira à adição de arquivo, o MediaScannerConnection não fornece uma solução para exclusão de arquivo - nem mesmo ao solicitar a verificação da pasta pai de um arquivo excluído.
AlikElzin-kilaka de

85

Uma solução mais simples é usar o método de conveniência estático scanFile () :

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

onde thisestá sua atividade (ou qualquer contexto), o tipo mime só é necessário se você estiver usando extensões de arquivo não padrão e nullé para o retorno de chamada opcional (que não precisamos para um caso tão simples).


2
Spot on, o método de transmissão que outros (e o Google) fornecem, muito raramente funciona).
Chris.Jenkins de

2
Isso estava funcionando para mim nas versões anteriores do Android ~ 4.0, mas agora no 4.3+ não parece estar funcionando. As imagens não estão aparecendo no aplicativo de galeria.
hooby3dfx

Perfeito! Você pode obter contexto com: Android.App.Application.Context
jarro

Trabalhou em marshmallow
Hitesh Sahu

66

Minha resposta para a pergunta original e para qualquer outra pessoa que possa ter esse problema:

Eu estava tendo o mesmo problema, as imagens em meu aplicativo que as pessoas salvavam no cartão SD não apareciam na Galeria imediatamente. Depois de alguma pesquisa, encontrei esta linha de código inserida após o meu código 'salvar no cartão SD' que corrigiu o problema:

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

precisamos usar o scanner de mídia para poder usar esta transmissão? estou usando outro método para exibir imagens na minha galeria. Quando estou usando o sendBroadcast acima no botão Salvar, clique em minha galeria não é atualizada com a nova imagem!
mudar de

4
É antigo, mas pode ajudar alguém - um caminho mais específico: sendBroadcast (new Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_PICTURES)))); Este método (esta resposta, não apenas meu comentário) não funciona no emulador. Teste em um dispositivo real.

Acredito que a resposta aceita oferece a maneira correta de fazer isso. Mas se você está tentando suportar API <= 7, então este é um bom substituto.
Amr Mostafa

Sua resposta é útil para outros dispositivos. Não está funcionando no HTC, quando tento escanear minha pasta de aplicativos. Não mostra a imagem adicionada recentemente.
MobileEvangelist de

6
Isso parece não ser mais compatível com Android 4.4 ou superior. Uma exceção de permissão será lançada neste caso.
rsp1984

13

Você também pode adicionar uma imagem à Galeria de mídia por intenção, dê uma olhada no código de exemplo para ver como isso é feito:

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

Oi. Este método adiciona a imagem ao MediaStore, eu confirmei verificando o retornado, Urimas o problema é que a imagem inserida não está aparecendo na galeria. Eu verifiquei tanto no início quanto no final da galeria. Você pode sugerir algum método para que a imagem inserida apareça na galeria imediatamente?
Shajeel Afzal

12

Atualização da galeria incluindo 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())));
}

O código que está dentro da primeira condição dentro da instrução "IF" funciona bem para mim no KitKat (Android 4.4.4, API 19).
Alex

8

Aqui está o código para o MediaScannerConnection:

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

newfile é o objeto Arquivo de seu arquivo novo / salvo.


2
Obrigado pela sua resposta. Na verdade, já terminei esse projeto há muito tempo ... Nem me lembro qual foi a solução que usei. Outros usuários podem achar sua solução útil se você também fornecer a implementação de MyMediaConnectorClient...
Michael Kessler

sim - estou tendo fortes dores de cabeça com isso no momento. Por favor, poste :)
Steve

Sim, não tenho certeza de como o fluxo deve ser - Corrija-me onde estou errado. Posso usar o MediaScannerConnection para atualizar as informações do SDCAARD, então tiro uma foto com a câmera e passo o novo arquivo para o MSC e agora posso acessar o arquivo com um cliente de scanner de conexão?
Steve

O fluxo é: você tira uma foto, salva em seu sdcard e, em seguida, faz a atualização do scanner, para que o sistema de arquivos seja atualizado para ver sua foto salva na galeria do dispositivo. Se você não fizer isso com o scanner, verá sua foto após o próximo dispositivo reiniciar na galeria.
3dmg 01 de

7

há um aplicativo no emulador que diz - 'Ferramentas de Desenvolvimento'

clique nele e selecione 'Media Scanning' .. todas as imagens serão digitalizadas


ótimo saber, a única maneira que eu conhecia antes de você dizer isso é reiniciando o telefone :)
mishkin

6

Deixe sua atividade implementar 'MediaScannerConnectionClient' e adicione isso à sua atividade:

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

Oi! E se soubermos o Urida imagem, por exemplo:content://media/external/images/media/1231778
Shajeel Afzal

6

este trabalho comigo

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

Quero salvar o arquivo gif animado que está localizado no armazenamento externo e tenho o caminho, isto é, / storage / emulated / 0 / Android / data / <PackageName> / files / <FolderName> /xyz.gif. Agora quero salvar / copiar este arquivo para a Galeria de imagens e mostrar lá. Como fazer isso.
Zia Ur Rahman

3

Aqui estou compartilhando o código que pode carregar a imagem em forma de bitmap e salvar essa imagem na galeria sdcard na pasta de nome do aplicativo. Você deve seguir estas etapas

  1. Baixe o bitmap de imagem primeiro



     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. Forneça também a seguinte permissão em seu arquivo AndroidManifest.xml.


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


  1. Aqui está todo o código escrito em Activty no qual queremos realizar esta tarefa.



     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. Espero que isso possa resolver todo o seu problema.

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

Não parece funcionar no KITKAT. Ele lança exceção de negação de permissão e trava o aplicativo. Então, para isso, fiz o seguinte,

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

Espero que ajude.


2

Use isto depois de salvar a imagem

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

3
Isso funciona, mas não é a melhor solução. Você está enganando o sistema fazendo-o pensar que o cartão SD seria (remontado) e possivelmente forçando a nova varredura de todo o cartão SD. MediaScanner.scanFile (..) é a melhor solução quando você agora o arquivo que deseja adicionar.
pocmo

1
Esta busca por todas as imagens. E envolve muito processamento de dados desnecessário que pode ser irrelevante quando temos apenas uma única imagem para ser exibida na galeria.
Rahul Rastogi

2

Meu código para 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

Você precisa dar permissões para o aplicativo Gallery. Basta pressionar longamente o ícone do aplicativo da galeria na tela inicial e tocar em 'APP INFO' que aparece no topo da tela. Fazer isso irá mostrar as configurações do aplicativo da galeria. Agora vá na guia Permissões e habilite o armazenamento, as permissões da câmera, alternando-o. Agora vá para o aplicativo de galeria nativa e você obterá as imagens salvas.


0

Isso também resolverá seu problema se sua imagem na galeria não estiver aparecendo, em vez disso, eles podem mostrar um bitmap do tipo 404 no meio. por favor, adicione as tags que estão em meu código com a sua imagem porque deve haver alguns metadados para mostrar a imagem na galeria.

      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

Experimente este, ele transmitirá sobre uma nova imagem criada, para que sua imagem fique visível. dentro de uma galeria. photoFile substitui pelo caminho real do arquivo da imagem recém-criada

private void galleryAddPicBroadCast() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photoFile);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.