¿Cómo elegir una imagen de la galería (tarjeta SD) para mi aplicación?

Resuelto Praveen asked hace 54 años • 10 respuestas

Esta pregunta se hizo originalmente para Android 1.6.

Estoy trabajando en las opciones de fotos en mi aplicación.

Tengo un botón y un ImageView en mi Actividad. Cuando hago clic en el botón, se redirigirá a la galería y podré seleccionar una imagen. La imagen seleccionada aparecería en mi ImageView.

Praveen avatar Jan 01 '70 08:01 Praveen
Aceptado

Respuesta actualizada, casi 5 años después:

El código en la respuesta original ya no funciona de manera confiable, ya que las imágenes de varias fuentes a veces regresan con un URI de contenido diferente, es decir, content://en lugar de file://. Una mejor solución es simplemente usar context.getContentResolver().openInputStream(intent.getData()), ya que devolverá un InputStream que puede manejar como desee.

Por ejemplo, BitmapFactory.decodeStream()funciona perfectamente en esta situación, ya que también puede usar el campo Opciones e inSampleSize para reducir la resolución de imágenes grandes y evitar problemas de memoria.

Sin embargo, cosas como Google Drive devuelven URI a imágenes que aún no se han descargado. Por lo tanto, debe ejecutar el código getContentResolver() en un hilo en segundo plano.


Respuesta original:

Las otras respuestas explicaron cómo enviar la intención, pero no explicaron bien cómo manejar la respuesta. Aquí hay un código de muestra sobre cómo hacerlo:

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

    switch(requestCode) { 
    case REQ_CODE_PICK_IMAGE:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};

            Cursor cursor = getContentResolver().query(
                               selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);
            cursor.close();


            Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
        }
    }
}

Después de esto, tienes la imagen seleccionada almacenada en "yourSelectedImage" para hacer lo que quieras con ella. Este código funciona obteniendo la ubicación de la imagen en la base de datos ContentResolver, pero eso por sí solo no es suficiente. Cada imagen tiene alrededor de 18 columnas de información, que van desde la ruta del archivo hasta la "fecha de la última modificación" y las coordenadas GPS del lugar donde se tomó la foto, aunque muchos de los campos en realidad no se utilizan.

Para ahorrar tiempo, ya que en realidad no necesita los otros campos, la búsqueda con el cursor se realiza con un filtro. El filtro funciona especificando el nombre de la columna que desea, MediaStore.Images.Media.DATA, que es la ruta, y luego dando esa cadena [] a la consulta del cursor. La consulta del cursor regresa con la ruta, pero no sabes en qué columna se encuentra hasta que usas el columnIndexcódigo. Eso simplemente obtiene el número de la columna según su nombre, el mismo que se usa en el proceso de filtrado. Una vez que lo tengas, finalmente podrás decodificar la imagen en un mapa de bits con la última línea de código que te proporcioné.

Steve Haley avatar Mar 24 '2010 13:03 Steve Haley
private static final int SELECT_PHOTO = 100;

Intención de inicio

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);    

Resultado del proceso

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
        }
    }
}

Alternativamente, también puedes reducir la resolución de tu imagen para evitar errores de OutOfMemory.

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 140;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
               || height_tmp / 2 < REQUIRED_SIZE) {
                break;
            }
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);

    }
siamii avatar Feb 23 '2011 03:02 siamii

Tienes que iniciar la intención de la galería para obtener un resultado.

Intent i = new Intent(Intent.ACTION_PICK,
               android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE); 

Luego en onActivityForResult, llame intent.getData()para obtener el Uri de la Imagen. Luego necesita obtener la imagen del ContentProvider.

Robby Pond avatar Mar 24 '2010 13:03 Robby Pond

Aquí hay un código probado para imágenes y videos. También funcionará para todas las API menores de 19 y mayores de 19.

Imagen:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("image/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 10);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 10);
                    }

Video:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("video/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 20);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 20);
                    }    

.

     @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {               
            if (requestCode == 10) {
                Uri selectedImageUri = data.getData();
                String selectedImagePath = getRealPathFromURI(selectedImageUri);
            } else if (requestCode == 20) {
                Uri selectedVideoUri = data.getData();
                String selectedVideoPath = getRealPathFromURI(selectedVideoUri);
            }
        }
     }

     public String getRealPathFromURI(Uri uri) {
            if (uri == null) {
                return null;
            }
            String[] projection = {MediaStore.Images.Media.DATA};
            Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null) {
                int column_index = cursor
                        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            return uri.getPath();
        }
Muhammad Umair Shafique avatar Dec 18 '2015 05:12 Muhammad Umair Shafique

Haga esto para iniciar la galería y permitir que el usuario elija una imagen:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMAGE_PICK);

Luego, onActivityResult()utilice el URI de la imagen que se devuelve para configurar la imagen en su ImageView.

Mark B avatar Mar 24 '2010 13:03 Mark B