Obter / escolher uma imagem do aplicativo Gallery interno do Android programaticamente

271

Estou tentando abrir uma imagem / imagem no aplicativo interno da Galeria de dentro do meu aplicativo.

Eu tenho um URI da imagem (a imagem está localizada no cartão SD).

Você tem alguma sugestão?

Michael Kessler
fonte
Atualizei minha resposta para fornecer mais código de teste para garantir que você recupere os resultados corretamente.
Anthony Forloney
olhe minha resposta, é uma atualização para o código hcpl e funciona para o gerenciador de arquivos astro e oi também.
louco
15
Alguém deve atualizar a pergunta "Obter / escolher uma imagem do Android ...". A pergunta atual interpreta que tenho imagem e quero mostrá-la pelo aplicativo de galeria padrão.
Vikas 31/07
@ Vikas, parece que você está certo. Não me lembro exatamente o que eu tentei realizar mais do que um ano atrás e por todas as respostas (incluindo o que eu selecionei como uma solução) realmente responder a uma pergunta diferente ...
Michael Kessler
Na verdade, não sei se é certo mudar completamente a questão. Há 36 pessoas que adicionaram a questão aos seus favoritos ...
Michael Kessler

Respostas:

351

Esta é uma solução completa. Acabei de atualizar este código de exemplo com as informações fornecidas na resposta abaixo por @mad. Verifique também a solução abaixo em @Khobaib, explicando como lidar com imagens do Picasa.

Atualizar

Acabei de revisar minha resposta original e criei um projeto Android Studio simples, que você pode fazer checkout no github e importar diretamente em seu sistema.

https://github.com/hanscappelle/SO-2169649

(observe que a seleção de vários arquivos ainda precisa de trabalho)

Seleção de imagem única

Com suporte para imagens de exploradores de arquivos, graças ao usuário louco.

public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.Button01)
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                String path = cursor.getString(column_index);
                cursor.close();
                return path;
            }
            // this is our fallback here
            return uri.getPath();
    }

}

Selecionando várias imagens

Como alguém solicitou essas informações em um comentário, é melhor ter informações coletadas.

Defina um parâmetro extra EXTRA_ALLOW_MULTIPLEcom a intenção:

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

E na manipulação de resultados, verifique esse parâmetro:

if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    if( list != null ) {
       for (Parcelable parcel : list) {
         Uri uri = (Uri) parcel;
         // TODO handle the images one by one here
       }
   }
} 

Observe que isso é suportado apenas pela API nível 18+.

hcpl
fonte
Não funciona quando uso o gerenciador de arquivos Astro. Alguma idéia do porquê?
Rohith Nandakumar
@ hcpl Obrigado pela resposta. Você pode me dizer como obter várias imagens ...?
Noby
28
Obter uma única imagem não parece mais funcionar com a versão mais recente do Android 4.4 (KitKat). A coluna _data da consulta retorna um valor nulo.
precisa
1
@hcpl Você não quis dizer 'Intent.hasExtra', você quis dizer 'data.hasExtra' - assumindo que os dados sejam o parâmetro Intent em onActivityResult ().
IgorGanapolsky
2
Esse código está funcionando perfeitamente no preKitkat, mas a partir de então há fornecedores de documentos. Na minha resposta, escrevo sobre o que fazer em kitkat.
Abbath
135

Aqui está uma atualização para o código fino que o hcpl postou. mas isso funciona com o gerenciador de arquivos OI, o gerenciador de arquivos astro E a galeria de mídia também (testada). então eu acho que ele funcionará com todos os gerenciadores de arquivos (existem muitos outros além dos mencionados?). fez algumas correções no código que ele escreveu.

public class BrowsePicture extends Activity {

    //YOU CAN EDIT THIS TO WHATEVER YOU WANT
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;
    //ADDED
    private String filemanagerstring;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
        .setOnClickListener(new OnClickListener() {

            public void onClick(View arg0) {

                // in onCreate or any event where your want the user to
                // select a file
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);
            }
        });
    }

    //UPDATED
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();

                //OI FILE Manager
                filemanagerstring = selectedImageUri.getPath();

                //MEDIA GALLERY
                selectedImagePath = getPath(selectedImageUri);

                //DEBUG PURPOSE - you can delete this if you want
                if(selectedImagePath!=null)
                    System.out.println(selectedImagePath);
                else System.out.println("selectedImagePath is null");
                if(filemanagerstring!=null)
                    System.out.println(filemanagerstring);
                else System.out.println("filemanagerstring is null");

                //NOW WE HAVE OUR WANTED STRING
                if(selectedImagePath!=null)
                    System.out.println("selectedImagePath is the right one for you!");
                else
                    System.out.println("filemanagerstring is the right one for you!");
            }
        }
    }

    //UPDATED!
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }
louco
fonte
1
Como recupero a imagem Bitmap do caminho da OI?
Vikas
2
veja o código. nas linhas com o comentário // AGORA NÓS TÊMOS A NOSSA QUANTIDADE QUERIDA ... isso é tudo que você precisa. em seguida, usar a classe BitmapFactory para recuperar um bitmap de um caminho
louco
Obrigado! Você tem um bom argumento, nunca tentou outros gerenciadores de arquivos :).
hcpl
2
Eu também gostaria de fechar o cursor :)
pgsandstrom
7
Também poderia mudar else return null;no getPath(Uri uri)para return uri.getPath();e livrar-se do primeiro filemanagerstring = selectedImageUri.getPath();cheque. Dessa forma, basta fazer uma chamada getPath(Uri)e recuperar o caminho (não importa se foi a Galeria ou um gerenciador de arquivos que foi usado).
ashughes
24

Os métodos do hcpl funcionam perfeitamente antes do KitKat, mas não funcionam com a API DocumentsProvider. Para isso, basta seguir o tutorial oficial do Android para documentproviders: https://developer.android.com/guide/topics/providers/document-provider.html -> abrir um documento, seção Bitmap.

Simplesmente usei o código hcpl e o estendi: se o arquivo com o caminho recuperado para a imagem gerar uma exceção, chamo esta função:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
             getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
}

Testado no Nexus 5.

abadia
fonte
Resposta realmente útil, deve ser usada para selecionar imagens do aplicativo "Fotos".
Arun Badole #
Eu tentei isso nos arquivos locais e do servidor, trabalhei para ambos.
Arun Badole #
11

Com base no código acima, eu refleti o código como abaixo, pode ser mais adequado:

public String getPath(Uri uri) {
    String selectedImagePath;
    //1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor != null){
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        selectedImagePath = cursor.getString(column_index);
    }else{
        selectedImagePath = null;
    }

    if(selectedImagePath == null){
        //2:OI FILE Manager --- call method: uri.getPath()
        selectedImagePath = uri.getPath();
    }
    return selectedImagePath;
}
szhln
fonte
11

Passei pela solução de @hcpl & @mad. A solução da hcpl suporta bem a imagem local na galeria e a mad forneceu uma solução melhor - além de ajudar a carregar a imagem OI / Astro / Dropbox. Mas, no meu aplicativo, enquanto trabalhava na biblioteca do Picasa agora integrada à Galeria do Android, ambas as soluções falham.

Pesquisei e analisei um pouco e, eventualmente, viemos com uma solução melhor e elegante que supera essa limitação. Agradeço a Dimitar Darazhanski por seu blog, que me ajudou neste caso, modifiquei um pouco para facilitar a compreensão. Aqui está a minha solução -

public class BrowsePicture extends Activity {

//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;

private String selectedImagePath;
//ADDED
private String filemanagerstring;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ((Button) findViewById(R.id.Button01))
    .setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {

            // in onCreate or any event where your want the user to
            // select a file
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
        }
    });
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
            selectedImagePath = getPath(selectedImageUri);

            if(selectedImagePath!=null){         
                // IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
                // OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE 
                // IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
                System.out.println("local image"); 
            }
            else{
                System.out.println("picasa image!");
                loadPicasaImageFromGallery(selectedImageUri);
            }
        }
    }
}


// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
    String[] projection = {  MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
        if (columnIndex != -1) {
            new Thread(new Runnable() {
                // NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
                // IF CALLED IN UI THREAD 
                public void run() {
                    try {
                        Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                        // THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
    cursor.close();
}


public String getPath(Uri uri) {
    String[] projection = {  MediaColumns.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
        //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
        String filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }
    else 
        return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
}

Verifique e informe-me se houver algum problema. Eu testei e funciona bem em todos os casos.

Espero que isso ajude a todos.

Khobaib
fonte
10

Supondo que você tenha uma pasta de imagens no diretório do cartão SD apenas para imagens.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*"); 
startActivityForResult(intent, 1);

Em seguida, você pode decidir com o que gostaria de fazer com o conteúdo de volta em sua atividade.

Este foi um exemplo para recuperar o nome do caminho da imagem, teste-o com seu código apenas para garantir que você possa lidar com os resultados que retornam. Você pode alterar o código conforme necessário para melhor atender às suas necessidades.

protected final void onActivityResult(final int requestCode, final int
                     resultCode, final Intent i) {
    super.onActivityResult(requestCode, resultCode, i);

  // this matches the request code in the above call
  if (requestCode == 1) {
      Uri _uri = i.getData();

    // this will be null if no image was selected...
    if (_uri != null) {
      // now we get the path to the image file
     cursor = getContentResolver().query(_uri, null,
                                      null, null, null);
     cursor.moveToFirst();
     String imageFilePath = cursor.getString(0);
     cursor.close();
     }
   }

Meu conselho é tentar obter as imagens funcionando corretamente, acho que o problema é o conteúdo de acessar as imagens no cartão SD. Dê uma olhada em Exibindo imagens no cartão SD .

Se você conseguir colocar isso em funcionamento, provavelmente pelo exemplo que fornece um provedor correto, você poderá descobrir uma solução alternativa para o seu código.

Mantenha-me atualizado atualizando esta pergunta com seu progresso. Boa sorte

Anthony Forloney
fonte
@ Anthony, obrigado pela sua resposta. Infelizmente, isso não funciona para mim. Recebo o próximo erro: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }
Michael Kessler
Você precisa ligar startActivityforResulte fornecer uma atividade. Isso é o que eu estava me referindo sobre decidir o que fazer em seguida, meu mal.
Anthony Forloney
Ainda não funciona ... Verifico se a pasta existe e se existe um arquivo de imagem dentro da pasta. Eu ligo startActivityForResult(intent, 1);e ainda recebo esse erro ... Esse código está localizado fora da Activity, mas tenho uma referência à atividade e chamo o startActivityForResultmétodo nessa referência - talvez seja esse o motivo?
Michael Kessler
Nah, não deveria ser a razão, qual é 1a sua passagem? TenteIMAGE_PICK
Anthony Forloney
1
O segundo parâmetro é apenas algo para mim, não é? Este é apenas um int que será passado de volta para mim junto com o resultado. Tentei também o em Intent.ACTION_PICKvez de Intent.ACTION_GET_CONTENT. Como assim IMAGE_PICK? Não existe tal constante. Eu também tentei intent.setData(Uri.fromFile(new File("/sdcard/image/")));. Tentei todas as combinações possíveis de estes e nada parece funcionar ...
Michael Kessler
10

esta é a minha revisão deste tópico, reunindo todas as informações aqui, além de outras questões relevantes sobre estouro de pilha. Ele retorna imagens de algum provedor, enquanto lida com condições de falta de memória e rotação da imagem. Ele suporta gerenciadores de galeria, picasa e arquivos, como caixa de depósito. O uso é simples: como entrada, o construtor recebe o resolvedor de conteúdo e a uri. A saída é o bitmap final.

/**
 * Creates resized images without exploding memory. Uses the method described in android
 * documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
 * close to some expected size. This is required because the android standard library is unable to
 * create a reduced size image from an image file using memory comparable to the final size (and
 * loading a full sized multi-megapixel picture for processing may exceed application memory budget).
 */

public class UserPicture {
    static int MAX_WIDTH = 600;
    static int MAX_HEIGHT = 800;
    Uri uri;
    ContentResolver resolver;
    String path;
    Matrix orientation;
    int storedHeight;
    int storedWidth;

    public UserPicture(Uri uri, ContentResolver resolver) {
        this.uri = uri;
        this.resolver = resolver;
    }

    private boolean getInformation() throws IOException {
        if (getInformationFromMediaDatabase())
            return true;

        if (getInformationFromFileSystem())
            return true;

        return false;
    }

    /* Support for gallery apps and remote ("picasa") images */
    private boolean getInformationFromMediaDatabase() {
        String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
        Cursor cursor = resolver.query(uri, fields, null, null, null);

        if (cursor == null)
            return false;

        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(Media.DATA));
        int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
        this.orientation = new Matrix();
        this.orientation.setRotate(orientation);
        cursor.close();

        return true;
    }

    /* Support for file managers and dropbox */
    private boolean getInformationFromFileSystem() throws IOException {
        path = uri.getPath();

        if (path == null)
            return false;

        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                               ExifInterface.ORIENTATION_NORMAL);

        this.orientation = new Matrix();
        switch(orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                /* Identity matrix */
                break;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                this.orientation.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                this.orientation.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                this.orientation.setScale(1, -1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                this.orientation.setRotate(90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                this.orientation.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                this.orientation.setRotate(-90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                this.orientation.setRotate(-90);
                break;
        }

        return true;
    }

    private boolean getStoredDimensions() throws IOException {
        InputStream input = resolver.openInputStream(uri);
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        /* The input stream could be reset instead of closed and reopened if it were possible
           to reliably wrap the input stream on a buffered stream, but it's not possible because
           decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
           mark(1024) on the stream). */
        input.close();

        if (options.outHeight <= 0 || options.outWidth <= 0)
            return false;

        storedHeight = options.outHeight;
        storedWidth = options.outWidth;

        return true;
    }

    public Bitmap getBitmap() throws IOException {
        if (!getInformation())
            throw new FileNotFoundException();

        if (!getStoredDimensions())
            throw new InvalidObjectException(null);

        RectF rect = new RectF(0, 0, storedWidth, storedHeight);
        orientation.mapRect(rect);
        int width = (int)rect.width();
        int height = (int)rect.height();
        int subSample = 1;

        while (width > MAX_WIDTH || height > MAX_HEIGHT) {
            width /= 2;
            height /= 2;
            subSample *= 2;
        }

        if (width == 0 || height == 0)
            throw new InvalidObjectException(null);

        Options options = new Options();
        options.inSampleSize = subSample;
        Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        Bitmap picture;
        if (!orientation.isIdentity()) {
            picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
                                          orientation, false);
            subSampled.recycle();
        } else
            picture = subSampled;

        return picture;
    }
}

Referências:

hdante
fonte
9

Existem dois tutoriais úteis sobre o seletor de imagens com código-fonte para download aqui:

Como criar o Seletor de imagens do Android

Como selecionar e cortar imagem no Android

No entanto, o aplicativo será forçado a fechar em algum momento. Você pode corrigi-lo adicionando o atributo android: configChanges na atividade principal do arquivo Manifest, como:

<activity android:name=".MainActivity"
                  android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" >

Parece que a API da câmera perdeu o controle com orientação, o que ajudará. :)

thanhbinh84
fonte
7

Abaixo, o trabalho da solução para 2.3 (Gingerbread) -4.4 (Kitkat), 5.0 (Lollipop) e 6.0 (Marshmallow) também: -

Etapa 1 Código para abrir a galeria para selecionar fotos:

public static final int PICK_IMAGE = 1;
private void takePictureFromGalleryOrAnyOtherFolder() 
{
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}

Etapa 2 Código para obter dados em onActivityResult:

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK) {
               if (requestCode == PICK_IMAGE) {
                    Uri selectedImageUri = data.getData();
                    String imagePath = getRealPathFromURI(selectedImageUri);
                   //Now you have imagePath do whatever you want to do now
                 }//end of inner if
             }//end of outer if
      }

 public String getRealPathFromURI(Uri contentUri) {
        //Uri contentUri = Uri.parse(contentURI);

        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = null;
        try {
            if (Build.VERSION.SDK_INT > 19) {
                // Will return "image:x*"
                String wholeID = DocumentsContract.getDocumentId(contentUri);
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";

                cursor = context.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, sel, new String[] { id }, null);
            } else {
                cursor = context.getContentResolver().query(contentUri,
                        projection, null, null, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String path = null;
        try {
            int column_index = cursor
                    .getColumnIndex(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            path = cursor.getString(column_index).toString();
            cursor.close();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return path;
    }
Pankaj
fonte
Está funcionando para mim. Estou usando o Nexus 5 com Marshmallow. Qual telefone você está usando.
Pankaj
im também usng Google Nexus mas faled para obter o nome da imagem ou o caminho da minha galeria selecionada imagem im ficando nula
Erum
java.lang.SecurityException: permissão negada: lendo o conteúdo de uri com.android.providers.media.MediaProvider: // media / external / images / media de pid = 31332, uid = 11859 requer android.permission.READ_EXTERNAL_STORAGE ou grantUriPermission () obtendo este erro #
315
Você tem a permissão add que sua exibiçãoREAD_EXTERNAL_STORAGE
Pankaj
Sim, eu já adicionou permissão no manifesto, mas eu não adicionar qualquer permissão em arquivos java em tempo de execução
Erum
6

Para exibir imagens e vídeos, tente o seguinte:

    Intent intent = new Intent();
    intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 1);
    startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);
michkra
fonte
5

Apenas no caso de ajudar; Eu faço isso para obter o Bitmap:

InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
Ferran Maylinch
fonte
Essa é a resposta mais fácil (e a única que funcionou para mim). Tão bem feito!
Derlin
5

As respostas acima estão corretas. Eu enfrentei um problema diferente: no HTC M8, meu aplicativo falha ao selecionar uma imagem da galeria. Estou recebendo valor nulo para o caminho da imagem. Corrigi e otimizei com a seguinte solução. no método onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == RESULT_LOAD_IMAGE) && (resultCode == RESULT_OK)) {
     if (data != null) {

            Uri selectedImageUri = null;
            selectedImageUri = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };

            Cursor imageCursor = mainActivity.getContentResolver().query(
                    selectedImageUri, filePathColumn, null, null, null);

            if (imageCursor == null) {
                return;
            }

            imageCursor.moveToFirst();
            int columnIndex = imageCursor.getColumnIndex(filePathColumn[0]);
            picturePath = imageCursor.getString(columnIndex);
            if (picturePath == null) {
                picturePath = selectedImageUri.getPath();
                String wholeID = DocumentsContract
                        .getDocumentId(selectedImage);

                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];

                String[] column = { MediaStore.Images.Media.DATA };

                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";

                Cursor cursor = mainActivity.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[] { id }, null);

                columnIndex = cursor.getColumnIndex(column[0]);

                if (cursor.moveToFirst()) {
                    picturePath = cursor.getString(columnIndex);
                }

                cursor.close();
            }
            picturePathAbs = new File(picturePath).getAbsolutePath();
            imageCursor.close();
        }

}

Afsal B Bavummal
fonte
Enfrento um problema semelhante e o picturePath é sempre nulo. Eu tento sua solução, mas não funciona, além de que getDocumentId requer> API 19
Stoycho Andreev
3
package com.ImageConvertingDemo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageView;

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        EditText tv = (EditText)findViewById(R.id.EditText01);
        ImageView iv = (ImageView)findViewById(R.id.ImageView01);
        FileInputStream in;
        BufferedInputStream buf;
            try 
            {
                in = new FileInputStream("/sdcard/smooth.png");
                buf = new BufferedInputStream(in,1070);
                System.out.println("1.................."+buf);
                byte[] bMapArray= new byte[buf.available()];
                tv.setText(bMapArray.toString());
                buf.read(bMapArray);
                Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

                /*for (int i = 0; i < bMapArray.length; i++) 
                {
                System.out.print("bytearray"+bMapArray[i]);
                }*/
                iv.setImageBitmap(bMap);
                //tv.setText(bMapArray.toString());
                //tv.setText(buf.toString());
                if (in != null) 
                {
                    in.close();
                }
                if (buf != null) 
                {
                    buf.close();
                }

            } 
            catch (Exception e) 
            {
                Log.e("Error reading file", e.toString());
            }
    }
}
Nikunj Patel
fonte
1
Você não entendeu a pergunta antes de responder. Além disso, você não incluiu nenhuma descrição sobre o que você tenta fazer. Além disso, seu código quebra alguns padrões de programação Java bem estabelecidos.
precisa
3
public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            // this is our fallback here
            return uri.getPath();
    }

}
Muhammad Usman Ghani
fonte
3

Recuperar um tipo específico de arquivo

Este exemplo obterá uma cópia da imagem.

static final int REQUEST_IMAGE_GET = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_GET);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
        Bitmap thumbnail = data.getParcelable("data");
        Uri fullPhotoUri = data.getData();
        // Do work with photo saved at fullPhotoUri
        ...
    }
}

Abra um tipo específico de arquivo

Ao executar no 4.4 ou superior, você solicita a abertura de um arquivo gerenciado por outro aplicativo

static final int REQUEST_IMAGE_OPEN = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.setType("image/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
    startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
        Uri fullPhotoUri = data.getData();
        // Do work with full size photo saved at fullPhotoUri
        ...
    }
}

Fonte original

Tobrun
fonte
2

Além das respostas anteriores, se você está tendo problemas para obter o caminho certo (como o AndroZip), pode usar o seguinte:

  public String getPath(Uri uri ,ContentResolver contentResolver) {
        String[] projection = {  MediaStore.MediaColumns.DATA};
        Cursor cursor;
        try{
            cursor = contentResolver.query(uri, projection, null, null, null);
        } catch (SecurityException e){
            String path = uri.getPath();
            String result = tryToGetStoragePath(path);
            return  result;
        }
        if(cursor != null) {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            String filePath = cursor.getString(columnIndex);
            cursor.close();
            return filePath;
        }
        else
            return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
    }

    private String tryToGetStoragePath(String path) {
        int actualPathStart = path.indexOf("//storage");
        String result = path;

        if(actualPathStart!= -1 && actualPathStart< path.length())
            result = path.substring(actualPathStart+1 , path.length());

        return result;
    }
bugraoral
fonte
É preciso conhecer o URI da imagem aqui? E se eu quiser apenas escolher uma imagem arbitrária da galeria?
IgorGanapolsky
A intenção que você receberá da galeria fornecerá o URL
bugraoral
1

Encontre a resposta para a seleção de uma única imagem da galeria

import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class PickImage extends Activity {

    Button btnOpen, btnGet, btnPick;
    TextView textInfo1, textInfo2;
    ImageView imageView;

    private static final int RQS_OPEN_IMAGE = 1;
    private static final int RQS_GET_IMAGE = 2;
    private static final int RQS_PICK_IMAGE = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_pick);
        btnOpen = (Button)findViewById(R.id.open);
        btnGet = (Button)findViewById(R.id.get);
        btnPick = (Button)findViewById(R.id.pick);
        textInfo1 = (TextView)findViewById(R.id.info1);
        textInfo2 = (TextView)findViewById(R.id.info2);
        imageView = (ImageView) findViewById(R.id.image);

        btnOpen.setOnClickListener(btnOpenOnClickListener);
        btnGet.setOnClickListener(btnGetOnClickListener);
        btnPick.setOnClickListener(btnPickOnClickListener);
    }

    View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, RQS_PICK_IMAGE);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {


            if (requestCode == RQS_OPEN_IMAGE ||
                    requestCode == RQS_GET_IMAGE ||
                    requestCode == RQS_PICK_IMAGE) {

                imageView.setImageBitmap(null);
                textInfo1.setText("");
                textInfo2.setText("");

                Uri mediaUri = data.getData();
                textInfo1.setText(mediaUri.toString());
                String mediaPath = mediaUri.getPath();
                textInfo2.setText(mediaPath);

                //display the image
                try {
                    InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
                    Bitmap bm = BitmapFactory.decodeStream(inputStream);

                   ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    byte[] byteArray = stream.toByteArray();

                    imageView.setImageBitmap(bm);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Krishh
fonte
0

A maneira mais rápida de abrir uma imagem da galeria ou câmera.

Referência original: obter imagem da galeria no android programaticamente

O método a seguir receberá a imagem da galeria ou da câmera e a exibirá em um ImageView. A imagem selecionada será armazenada internamente.

código para xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.exampledemo.parsaniahardik.uploadgalleryimage.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Capture Image and upload to server" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Below image is fetched from server"
        android:layout_marginTop="5dp"
        android:textSize="23sp"
        android:gravity="center"
        android:textColor="#000"/>

    <ImageView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/iv"/>

</LinearLayout>

Classe JAVA

import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.androidquery.AQuery;
import org.json.JSONException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity implements AsyncTaskCompleteListener{

    private ParseContent parseContent;
    private Button btn;
    private ImageView imageview;
    private static final String IMAGE_DIRECTORY = "/demonuts_upload_camera";
    private final int CAMERA = 1;
    private AQuery aQuery;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        parseContent = new ParseContent(this);
        aQuery = new AQuery(this);

        btn = (Button) findViewById(R.id.btn);
        imageview = (ImageView) findViewById(R.id.iv);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, CAMERA);
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) {
            return;
        }
        if (requestCode == CAMERA) {
            Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
            String path = saveImage(thumbnail);
            try {
                uploadImageToServer(path);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private void uploadImageToServer(final String path) throws IOException, JSONException {

        if (!AndyUtils.isNetworkAvailable(MainActivity.this)) {
            Toast.makeText(MainActivity.this, "Internet is required!", Toast.LENGTH_SHORT).show();
            return;
        }

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("url", "https://demonuts.com/Demonuts/JsonTest/Tennis/uploadfile.php");
        map.put("filename", path);
        new MultiPartRequester(this, map, CAMERA, this);
        AndyUtils.showSimpleProgressDialog(this);
    }

    @Override
    public void onTaskCompleted(String response, int serviceCode) {
        AndyUtils.removeSimpleProgressDialog();
        Log.d("res", response.toString());
        switch (serviceCode) {

            case CAMERA:
                if (parseContent.isSuccess(response)) {
                    String url = parseContent.getURL(response);
                    aQuery.id(imageview).image(url);
                }
        }
    }

    public String saveImage(Bitmap myBitmap) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
        File wallpaperDirectory = new File(
                Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
        // have the object build the directory structure, if needed.
        if (!wallpaperDirectory.exists()) {
            wallpaperDirectory.mkdirs();
        }

        try {
            File f = new File(wallpaperDirectory, Calendar.getInstance()
                    .getTimeInMillis() + ".jpg");
            f.createNewFile();
            FileOutputStream fo = new FileOutputStream(f);
            fo.write(bytes.toByteArray());
            MediaScannerConnection.scanFile(this,
                    new String[]{f.getPath()},
                    new String[]{"image/jpeg"}, null);
            fo.close();
            Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());

            return f.getAbsolutePath();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return "";
    }
}
Parsania Hardik
fonte
0

Aqui está o meu exemplo, pode não ser exatamente o seu caso.


supondo que você obtenha o formato base64 do seu provedor de API, atribua a ele um nome e uma extensão de arquivo, salve-o em um determinado local no sistema de arquivos.

public static void shownInBuiltInGallery(final Context ctx, String strBase64Image, final String strFileName, final String strFileExtension){

new AsyncTask<String, String, File>() {
    @Override
    protected File doInBackground(String... strBase64Image) {

        Bitmap bmpImage = convertBase64StringToBitmap(strBase64Image[0], Base64.NO_WRAP);

        if(bmpImage == null) {
            cancel(true);
            return null;
        }

        byte[] byImage = null;

        if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_JPG) == 0) {
            byImage = convertToJpgByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_PNG) == 0){
            byImage = convertToPngByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_BMP) == 0){
            byImage = convertToBmpByte(bmpImage); // convert bitmap to binary for latter use
        } else {
            cancel(true);
            return null;
        }

        if(byImage == null) {
            cancel(true);
            return null;
        }

        File imageFolder = ctx.getExternalCacheDir();

        if(imageFolder.exists() == false){
            if(imageFolder.mkdirs() == false){
                cancel(true);
                return null;
            }
        }

        File imageFile = null;

        try {
            imageFile = File.createTempFile(strFileName, strFileExtension, imageFolder);
        } catch (IOException e){
            e.printStackTrace();
        }

        if(imageFile == null){
            cancel(true);
            return null;
        }

        if (imageFile.exists() == true) {
            if(imageFile.delete() == false){
                cancel(true);
                return null;
            }
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(imageFile.getPath());
            fos.write(byImage);
            fos.flush();
            fos.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        } finally {
            fos = null;
        }

        return imageFile;
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);

            String strAuthority = ctx.getPackageName() + ".provider";
            Uri uriImage = FileProvider.getUriForFile(ctx, strAuthority, file);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uriImage, "image/*");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            ctx.startActivity(intent);

    }
}.execute(strBase64Image);}

Não se esqueça de configurar um provedor de arquivos adequado em primeiro lugar no AndroidManifest.xml

        <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>

onde o caminho do arquivo é um xml em ... / res / xml / file_path.xml

<?xml version="1.0" encoding="utf-8"?>

<external-files-path name="external_files" path="Accessory"/>

<external-path name="ex_Download" path="Download/" />
<external-path name="ex_Pictures" path="Pictures/" />

<external-files-path name="my_Download" path="Download/" />
<external-files-path name="my_Pictures" path="Pictures/" />
<external-cache-path name="my_cache" path="." />

<files-path name="private_Download" path="Download/" />
<files-path name="private_Pictures" path="Pictures/" />
<cache-path name="private_cache" path="." />


Para encurtar a história, tenha o provedor de arquivos pronto no início, passe Uri para Intent para obter uma fonte de imagem conhecida e acessível; caso contrário, salve a imagem no local desejado e depois passe o local (como Uri) para Intent.

a-chhiong
fonte