ASánchezDíaz

Autoaprendiendo .NET y otras cosas


Cómo cargar una imagen en un control ImageView en Android

En esta ocasión veremos cómo cargar una imagen en un control ImageView seleccionando la imagen desde la galería de Android o usando la cámara para hacer una foto.

Para ello, editaremos el layout de la Activity y añadimos un control ImageView:


activity_main.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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.asanchezdiaz.loadimageinimageview.MainActivity">


    <ImageView
        android:id="@+id/imgFotoPerfil"
        android:scaleType="centerCrop"
        android:layout_width="match_parent"
        android:layout_height="280dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:text="Cargar desde galería"
            android:onClick="seleccionarImagenDesdeGaleria"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <Button
            android:text="Hacer Foto"
            android:onClick="hacerFoto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</LinearLayout>

Esta será la plantilla (layout) que define la interfaz de la Activity. Hemos incluido un control ImageView que será el encargado de mostrar la foto. Además, hemos añadido dos botones para elegir el modo en que queremos cargar la imagen. Ambos controles tienen asignados los eventos onClick con los métodos  seleccionarImagenDesdeGaleria y hacerFoto.

El código de la activity inicial es:

package com.asanchezdiaz.loadimageinimageview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

En principio es el código habitual que genera Android Studio al crear una activity. Tendremos que añadir aún el código necesario para elegir la foto desde la galería o directamente usando la cámara y cargarla en el control.

Además, necesitamos añadir un permiso al archivo AndroidManifest.xml para que podamos leer archivos del almacenamiento externo:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Vamos a implementar ahora los métodos seleccionarImagenDesdeGaleria y hacerFoto en el archivo MainActivity.java.

En ambos casos crearemos un Intent, en función del método, para incluirlo en el método startActivityForResult. Este método lanza una Activity (en este caso del propio sistema, aunque podemos lanzar una Activity propia) y espera que se le devuelva un resultado, que será recibido por el método onActivityResult de la Activity inicial.

Es decir, la Activity inicial, en este caso MainActivity, solicita la intervención de una nueva Activity y espera que la segunda Activity le devuelva un resultado. Los tres parámetros que recibirá la Activity inicial son:

  • int requestCode: que se usa para determinar la solicitud. En nuestro caso, MainActivity puede recibir dos resultados, desde la Activity que gestiona la Galería de Android o desde la que gestiona la Cámara. Es por esto que cuando MainActivity inicia las Activities, les facilita un código o identificador que se devuelve posteriormente mediante requestCode. De esta forma MainActivity sabe qué Activity es la que devuelve el resultado.
  • int resultCode: es un flag que indica cómo ha finalizado la Activity que se inició. Puede que se haya elegido una imagen o hecho una foto (RESULT_OK) o puede que el usuario haya cancelado (RESULT_CANCELED). Mediante este indicador sabemos qué ha ocurrido.
  • Intent data: es el Intent que contiene los datos que solicitamos. En nuestro caso, este Intent contendrá, entre otras cosas, el URI de la imagen, es decir, la ruta a la imagen.

Vamos al código, en primer lugar, este es el aspecto que debe tener MainActivity.java una vez que implementemos los métodos seleccionarImagenDesdeGaleria y hacerFoto:

package com.asanchezdiaz.loadimageinimageview;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    //Request codes
    private static final int REQUEST_IMAGE = 100;
    private static final int REQUEST_IMAGE_CAMERA = 101;

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

    public void seleccionarImagenDesdeGaleria(View view) {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, REQUEST_IMAGE);
    }

    public void hacerFoto(View view) {
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        startActivityForResult(intent, REQUEST_IMAGE_CAMERA);
    }
}
}

Lo primero que hemos hecho es declarar e inicializar las variables:

    //Request codes
    private static final int REQUEST_IMAGE = 100;
    private static final int REQUEST_IMAGE_CAMERA = 101;

Que nos servirán de flags o indicadores.

Cada método crea un Intent predefinido en función de lo que queremos que haga. El método seleccionarImagenDesdeGaleria(View view) crea un Intent con el “action” new Intent(Intent.ACTION_PICK) mientras que hacerFoto(View view) lo hace con el action new Intent(“android.media.action.IMAGE_CAPTURE”) de forma que cuando llamamos al método startActivityForResult el sistema sabe qué Activity abrir.

Al método startActivityForResult le pasamos el Intent que hemso creado y el flag correspondiente para poder identificar la respuesta.

El resultado de ambas activities lo recibiremos en el método onActivityResult, vamos a implementarlo:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    ImageView imgFotoPerfil = (ImageView) findViewById(R.id.imgFotoPerfil);
    
    if(resultCode == Activity.RESULT_OK)
    {
        switch (requestCode) {
            case REQUEST_IMAGE:
                try {
                    Uri selectedImage = data.getData();

                    InputStream imageStream = getContentResolver().openInputStream(selectedImage);
                    final Bitmap bmp = BitmapFactory.decodeStream(imageStream);

                    imgFotoPerfil.setImageBitmap(bmp);

                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;

            case REQUEST_IMAGE_CAMERA:
                try {

                    Bitmap mBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
                    imgFotoPerfil.setImageBitmap(mBitmap);
                    
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}

En primer lugar comprobamos que el resultado de la Activity sea Activity.RESULT_OK y si es así, identificamos mediante un switch qué Activity es la que envía la respuesta. El siguiente paso será generar el Bitmap resultante y en función del modo en que hemos cargado la imagen lo haremos de un modo u otro.

El código completo de mainActivity.java es:

package com.asanchezdiaz.loadimageinimageview;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

import java.io.InputStream;

public class MainActivity extends AppCompatActivity {

    //Request codes
    private static final int REQUEST_IMAGE = 100;
    private static final int REQUEST_IMAGE_CAMERA = 101;

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

    public void seleccionarImagenDesdeGaleria(View view) {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, REQUEST_IMAGE);
    }

    public void hacerFoto(View view) {
        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
        startActivityForResult(intent, REQUEST_IMAGE_CAMERA);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        ImageView imgFotoPerfil = (ImageView) findViewById(R.id.imgFotoPerfil);

        if(resultCode == Activity.RESULT_OK)
        {
            switch (requestCode) {
                case REQUEST_IMAGE:
                    try {
                        Uri selectedImage = data.getData();

                        InputStream imageStream = getContentResolver().openInputStream(selectedImage);
                        final Bitmap bmp = BitmapFactory.decodeStream(imageStream);


                        imgFotoPerfil.setImageBitmap(bmp);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;

                case REQUEST_IMAGE_CAMERA:
                    try {

                        Bitmap mBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
                        imgFotoPerfil.setImageBitmap(mBitmap);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

}

Recuerdo que seguramente (casi seguro) hay mejores formas de hacer esto. Así es como lo hice yo en su momento (y me funcionó). Si sabéis cómo mejorar el código no tenéis más que avisarme.

Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *