Obtenga / elija una imagen de la aplicación Galería integrada de Android mediante programación

271

Estoy tratando de abrir una imagen / imagen en la aplicación integrada de la Galería desde mi aplicación.

Tengo un URI de la imagen (la imagen se encuentra en la tarjeta SD).

¿Tienes alguna sugerencia?

Michael Kessler
fuente
He actualizado mi respuesta para proporcionar más código de prueba para garantizar que recupere los resultados correctamente.
Anthony Forloney el
mira mi respuesta, es una actualización del código de hcpl y también funciona para el administrador de archivos astro y el administrador de archivos oi.
loco
15
Alguien debería actualizar la pregunta "Obtener / elegir una imagen de Android ...". La pregunta actual interpreta que tengo una imagen y quiero mostrarla a través de la aplicación de galería predeterminada.
Vikas
@Vikas, parece que tienes razón. No recuerdo qué es exactamente lo que intenté lograr hace más de un año y por qué todas las respuestas (incluida la que he seleccionado como solución) realmente responden a una pregunta diferente ...
Michael Kessler
En realidad, no sé si es correcto cambiar la pregunta por completo. Hay 36 personas que han agregado la pregunta a sus favoritos ...
Michael Kessler

Respuestas:

351

Esta es una solución completa. Acabo de actualizar este código de ejemplo con la información proporcionada en la respuesta a continuación por @mad. También verifique la solución a continuación de @Khobaib que explica cómo lidiar con las imágenes picasa.

Actualizar

Acabo de revisar mi respuesta original y creé un proyecto simple de Android Studio que puede pagar desde github e importar directamente en su sistema.

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

(tenga en cuenta que la selección de archivos múltiples todavía necesita trabajo)

Selección de imagen única

Con soporte para imágenes de exploradores de archivos gracias al usuario loco.

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

}

Seleccionar varias imágenes

Dado que alguien solicitó esa información en un comentario y es mejor tener información recopilada.

Establezca un parámetro adicional EXTRA_ALLOW_MULTIPLEen la intención:

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Y en la comprobación de manejo de resultados para ese 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
       }
   }
} 

Tenga en cuenta que esto solo es compatible con el nivel API 18+.

hcpl
fuente
No funciona cuando uso el administrador de archivos Astro. Alguna idea de por qué?
Rohith Nandakumar
@hcpl Gracias por la respuesta. ¿Me puede decir cómo obtener varias imágenes ...?
Noby
28
Obtener una sola imagen ya no parece funcionar en la versión más reciente de Android 4.4 (KitKat). La columna _data de la consulta devuelve un valor nulo.
Christopher Masser
1
@hcpl No quiso decir 'Intent.hasExtra', quiso decir 'data.hasExtra', suponiendo que los datos son su parámetro Intent en onActivityResult ().
IgorGanapolsky
2
Este código funciona perfectamente preKitkat, pero a partir de entonces hay proveedores de documentos. En mi respuesta escribo sobre qué hacer en kitkat.
abbath
135

Aquí hay una actualización del código fino que hcpl publicó. pero esto funciona con el administrador de archivos OI, el administrador de archivos astro Y la galería de medios también (probado). así que supongo que funcionará con todos los administradores de archivos (¿hay muchos más que los mencionados?). hizo algunas correcciones al código que escribió.

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;
    }
enojado
fuente
1
¿Cómo recupero la imagen de mapa de bits de la ruta OI?
Vikas
2
Mira el código. en las líneas con el comentario // AHORA TENEMOS NUESTRA CADENA DESEADA ... esto es todo lo que necesitas. luego use la clase BitmapFactory para recuperar un mapa de bits de una ruta
loco
¡Gracias! Tienes un buen punto, nunca probé con otros administradores de archivos :).
hcpl
2
También me gustaría cerrar el cursor :)
pgsandstrom
77
También podría cambiar else return null;en getPath(Uri uri)a return uri.getPath();y deshacerse de la primera filemanagerstring = selectedImageUri.getPath();comprobación. De esta manera, solo debe hacer una llamada getPath(Uri)y recuperar la ruta (no importa si se utilizó la Galería o un administrador de archivos).
Ashughes
24

Los métodos de hcpl funcionan perfectamente antes de KitKat, pero no funcionan con la API DocumentsProvider. Para eso, simplemente siga el tutorial oficial de Android para proveedores de documentos: https://developer.android.com/guide/topics/providers/document-provider.html -> abra un documento, sección Bitmap.

Simplemente usé el código de hcpl y lo extendí: si el archivo con la ruta recuperada a la imagen arroja una excepción, llamo a esta función:

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

Probado en Nexus 5.

el baño
fuente
Respuesta realmente útil, debe utilizarse para seleccionar imágenes de la aplicación "Fotos".
Arun Badole
Intenté esto en archivos locales y de servidor, trabajé para ambos.
Arun Badole
11

base con el código anterior, reflejé el código como a continuación, puede ser más adecuado:

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
fuente
11

Revisé la solución de @hcpl y @mad. La solución de hcpl admite bien la imagen local en la galería y mad proporcionó una mejor solución además de eso: también ayuda a cargar la imagen OI / Astro / Dropbox. Pero en mi aplicación, mientras trabajaba en la biblioteca picasa que ahora está integrada en la Galería de Android, ambas soluciones fallan.

Busqué y analicé un poco y finalmente encontré una solución mejor y elegante que supera esta limitación. Gracias a Dimitar Darazhanski por su blog, que me ayudó en este caso, modifiqué un poco para que sea más fácil de entender. Aquí está mi solución:

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
}

Compruébalo y avísame si hay algún problema con él. Lo he probado y funciona bien en todos los casos.

Espero que esto ayude a todos.

Khobaib
fuente
10

Suponiendo que tiene una carpeta de imágenes en el directorio de su tarjeta SD solo para imágenes.

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

Luego, puede decidir qué le gustaría hacer con el contenido en su actividad.

Este fue un ejemplo para recuperar el nombre de la ruta de la imagen, pruébelo con su código solo para asegurarse de que puede manejar los resultados que regresan. Puede cambiar el código según sea necesario para adaptarse mejor a sus necesidades.

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

Mi consejo es intentar recuperar las imágenes funcionando correctamente, creo que el problema es el contenido de acceder a las imágenes en la tarjeta SD. Eche un vistazo a Visualización de imágenes en la tarjeta SD .

Si puede ponerlo en funcionamiento, probablemente con el ejemplo que proporciona un proveedor correcto, debería ser capaz de encontrar una solución para su código.

Mantenme actualizado actualizando esta pregunta con tu progreso. Buena suerte

Anthony Forloney
fuente
@ Anthony, gracias por tu respuesta. Lamentablemente no me funciona. Me sale el siguiente error: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }
Michael Kessler
Necesita llamar startActivityforResulty suministrar una actividad. A eso me refería para decidir qué hacer a continuación, mi mal.
Anthony Forloney el
Todavía no funciona ... Compruebo que la carpeta existe y que hay un archivo de imagen dentro de la carpeta. Llamo startActivityForResult(intent, 1);y sigo recibiendo este error ... Este código se encuentra fuera de la Actividad, pero tengo una referencia a la actividad y llamo al startActivityForResultmétodo en esa referencia, ¿tal vez esta es la razón?
Michael Kessler
No, no debería ser la razón, ¿qué es lo 1que estás pasando? ProbarIMAGE_PICK
Anthony Forloney
1
El segundo parámetro es algo para mí, ¿no? Este es solo un int que me será devuelto junto con el resultado. Intenté también el en Intent.ACTION_PICKlugar de Intent.ACTION_GET_CONTENT. ¿Qué quieres decir con IMAGE_PICK? No hay tal constante. También lo intenté intent.setData(Uri.fromFile(new File("/sdcard/image/")));. Probé todas las combinaciones posibles de estos y nada parece funcionar ...
Michael Kessler
10

Esta es mi visita a este tema, reuniendo toda la información aquí, además de otras preguntas relevantes de desbordamiento de pila. Devuelve imágenes de algún proveedor, mientras maneja condiciones de falta de memoria y rotación de imágenes. Es compatible con la galería, picasa y administradores de archivos, como el cuadro desplegable. El uso es simple: como entrada, el constructor recibe la resolución de contenido y la uri. La salida es el mapa de bits 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;
    }
}

Referencias

hdante
fuente
9

Aquí hay dos tutoriales útiles sobre el selector de imágenes con código fuente descargable:

Cómo crear un selector de imágenes de Android

Cómo seleccionar y recortar imagen en Android

Sin embargo, la aplicación se verá obligada a cerrar en algún momento, puede solucionarla agregando el atributo android: configChanges en la actividad principal en el archivo de manifiesto como:

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

Parece que la API de la cámara perdió el control con la orientación, por lo que esto lo ayudará. :)

thanhbinh84
fuente
7

El siguiente trabajo de solución para 2.3 (Gingerbread) -4.4 (Kitkat), 5.0 (Lollipop) y 6.0 (Marshmallow) también: -

Paso 1 Código para abrir la galería para seleccionar 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);
}

Paso 2 Código para ingresar datos 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
fuente
Me está funcionando. Estoy usando Nexus 5 con Marshmallow. Qué teléfono estás usando.
Pankaj
im también USNG Google Nexus pero faled para obtener nombre de la imagen o la ruta de mi galería de imágenes seleccionadas im conseguir nula
Erum
java.lang.SecurityException: denegación de permisos: lectura com.android.providers.media.MediaProvider uri content: // media / external / images / media from pid = 31332, uid = 11859 requiere android.permission.READ_EXTERNAL_STORAGE, o grantUriPermission () obteniendo este error
Erum
Tiene permiso adicional que se muestraREAD_EXTERNAL_STORAGE
Pankaj
sí, ya he agregado permiso en manifiesto, pero no
agregué
6

Para mostrar imágenes y videos intente esto:

    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
fuente
5

Por si acaso ayuda; Hago esto para obtener el mapa de bits:

InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
Ferran Maylinch
fuente
Esta es la respuesta más fácil (y la única que funcionó para mí). ¡Muy bien hecho!
Derlin
5

Las respuestas anteriores son correctas. Me enfrenté a un problema diferente en el que en HTC M8 mi aplicación se bloquea al seleccionar una imagen de la galería. Estoy obteniendo un valor nulo para la ruta de la imagen. Lo arreglé y optimicé con la siguiente solución. en el 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
fuente
Me enfrento a un problema similar y picturePath siempre es nulo. Intento su solución pero no funciona, además de que getDocumentId requiere> 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
fuente
1
No entendiste la pregunta antes de responder. Además, no incluyó ninguna descripción sobre lo que intenta hacer. Además, su código rompe algunos estándares de programación Java bien establecidos.
Torben
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
fuente
3

Recuperar un tipo específico de archivo

Este ejemplo obtendrá una copia de la imagen.

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
        ...
    }
}

Abrir un tipo específico de archivo

Cuando se ejecuta en 4.4 o superior, solicita abrir un archivo administrado por otra aplicación

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
        ...
    }
}

Fuente original

Tobrun
fuente
2

Además de las respuestas anteriores, si tiene problemas para obtener el camino correcto (como AndroZip) puede usar esto:

  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
fuente
¿Se necesita saber la uri de la imagen aquí? ¿Qué sucede si solo quiero elegir una imagen arbitraria de la galería?
IgorGanapolsky
La intención que recibirá de la galería le proporcionará la URL
bugraoral
1

Encuentre la respuesta para seleccionar una sola imagen de la galería

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
fuente
0

La forma más rápida de abrir imágenes desde la galería o la cámara.

Referencia original: obtenga la imagen de la galería en Android mediante programación

El siguiente método recibirá una imagen de la galería o cámara y la mostrará en un ImageView. La imagen seleccionada se almacenará 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>

Clase 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
fuente
0

Aquí está mi ejemplo, podría no ser exactamente como su caso.


suponiendo que obtenga el formato base64 de su proveedor de API, dele un nombre de archivo y una extensión de archivo, guárdelo en cierta ubicación en el sistema de archivos.

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

No olvide configurar un proveedor de archivos adecuado en primer lugar en 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>

donde la ruta del archivo es un xml en ... / 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 resumir, tenga al proveedor de archivos listo al principio, pase Uri a Intent para obtener una fuente de imagen conocida y accesible, de lo contrario, guarde la imagen en la ubicación deseada y luego pase la ubicación (como Uri) a Intent.

a-chhiong
fuente