Listado completo de tutoriales

50 - Tomar una foto y grabarla en un archivo (mediante Intent)


La forma más sencilla de capturar una foto en Android es mediante el software que provee el sistema operativo Android. Invocamos la aplicación de tomar fotos mediante la clase Intent.

Tiene como ventaja que la interfaz le es familiar al usuario, ya que muchas aplicaciones utilizan esta característica y nos facilita mucho la codificación.

Problema:

Confeccionaremos una aplicación que permita ingresar un nombre de archivo con extensión jpg en un EditText. Luego al presionar un botón lanzar el Activity que proporciona Android para tomar una foto. Grabar el archivo en la memoria externa del dispositivo. Disponer un segundo botón para recuperar un archivo jpg almacenado en el dispositivo.

Finalmente crearemos un segundo Activity para mostrar en un ListView todos los nombres de archivos de imágenes almacenados por la aplicación y al presionar uno de ellos procederemos a mostrarlo en un ImageView.

Crear un proyecto llamado "Proyecto055".

Lo primero que haremos es modificar el archivo AndroidManifest.xml para permitir a la aplicación almacenar archivos en la memoria externa:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tutorialesprogramacionya.proyecto055">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Es decir agregamos la línea:

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

La interfaz visual de la ventana principal es:

Tomar foto

Disponemos un EditText, 3 botones y un objeto de la clase ImageView. El archivo "activity_main.xml" que implementa la interfaz visual es:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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"
    tools:context="com.tutorialesprogramacionya.proyecto055.MainActivity">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editText"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:text="foto1.jpg" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tomar Foto"
        android:id="@+id/button"
        android:layout_below="@+id/editText"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:onClick="tomarFoto" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Recuperar Foto"
        android:id="@+id/button2"
        android:layout_below="@+id/editText"
        android:layout_centerHorizontal="true"
        android:onClick="recuperarFoto" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Ver"
        android:id="@+id/button3"
        android:layout_alignBottom="@+id/button2"
        android:layout_toRightOf="@+id/button2"
        android:layout_toEndOf="@+id/button2"
        android:onClick="ver" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:layout_below="@+id/button"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:src="@mipmap/ic_launcher" />
</RelativeLayout>

La imagen inicial del ImageView la definimos en la propiedad src y disponemos el recurso por defecto propuesto en el proyecto (luego en tiempo de ejecución la modificamos con las imágenes de las fotos que sacamos):

        android:src="@mipmap/ic_launcher" />

Los tres botones tienen cargadas la propiedad onClick con el método respectivo:

        android:onClick="tomarFoto" />


        android:onClick="recuperarFoto" />

        y

        android:onClick="ver" />

El código java asociado a esta vista se encuentra en el archivo "MainActivity.java" y es el siguiente:

package com.tutorialesprogramacionya.proyecto055;

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

import java.io.File;

public class MainActivity extends AppCompatActivity {

    private ImageView imagen1;
    private EditText et1;

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

        imagen1=(ImageView)findViewById(R.id.imageView);
        et1=(EditText)findViewById(R.id.editText);
    }

    public void tomarFoto(View v) {
        Intent intento1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File foto = new File(getExternalFilesDir(null), et1.getText().toString());
        intento1.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(foto));
        startActivity(intento1);
    }

    public void recuperarFoto(View v) {
        Bitmap bitmap1 = BitmapFactory.decodeFile(getExternalFilesDir(null)+"/"+et1.getText().toString());
        imagen1.setImageBitmap(bitmap1);
    }

    public void ver(View v) {
        Intent intento1=new Intent(this,Actividad2.class);
        startActivity(intento1);
    }
}

Definimos las variables et1 e imagen1:

    private ImageView imagen1;
    private EditText et1;

En el método onCreate obtenemos la referencia de los objetos definidos en el archivo XML:

        imagen1=(ImageView)findViewById(R.id.imageView);
        et1=(EditText)findViewById(R.id.editText);

Cuando se presiona el botón para tomar la foto creamos un objeto de la clase Intent y pasamos como dato la constante ACTION_IMAGE_CAPTURE definida en la clase MediaStore:

        Intent intento1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

Creamos un objeto de la clase File indicando en el primer parámetro el path donde se creará el archivo y lo obtenemos llamando al método getExternalFilesDir(null), y como segundo parámetro indicamos el nombre de archivo donde se guardará la foto:

        File foto = new File(getExternalFilesDir(null), et1.getText().toString());

Pasamos al otro Activity la referencia del archivo que debe crear:

        intento1.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(foto));

Finalmente lanzamos el Activity que permite tomar la foto:

        startActivity(intento1);

Para recuperar una foto almacenada en la memoria externa procedemos a crear un objeto de la clase Bitmap llamando al método estático decodeFile de la clase BitmapFactory. Debemos pasar como referencia el path donde se encuentra el archivo jpg a recuperar:

        Bitmap bitmap1 = BitmapFactory.decodeFile(getExternalFilesDir(null)+"/"+et1.getText().toString());

Para visualizar la imagen en el ImageView llamamos al método setImageBitmap:

        imagen1.setImageBitmap(bitmap1);

Cuando se presiona el botón ver procedemos a crear un Activity que seguidamente procederemos a crear:

        Intent intento1=new Intent(this,Actividad2.class);
        startActivity(intento1);

Ahora procederemos a crear la segunda actividad. Para esto presionamos el botón derecho del mouse sobre el nombre del paquete de nuestro proyecto y en el menú que aparece seleccionamos New -> Activity -> Empty Activity:

Tomar foto

En el diálogo que aparece procedemos a cargar en "Activity Name" el valor "Actividad2":

Tomar foto

Luego de presionar "Finish" ya tenemos los dos archivos : XML y java de nuestra aplicación.

En el archivo activity_actividad2.xml procedemos a crear la siguiente interfaz:

Tomar foto

El contenido para crear esta pantalla está en el archivo activity_actividad2.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_actividad2"
    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"
    tools:context="com.tutorialesprogramacionya.proyecto055.Actividad2">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/listView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher" />

    </LinearLayout>
    
    
</RelativeLayout>

El archivo java asociado a esta actividad se llama "Actividad2.java" y su contenido es:

package com.tutorialesprogramacionya.proyecto055;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;

import java.io.File;

public class Actividad2 extends AppCompatActivity {

    private ListView lv1;
    private ImageView iv1;
    private String[] archivos;
    private ArrayAdapter<String> adaptador1;

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

        File dir=getExternalFilesDir(null);
        archivos=dir.list();
        adaptador1=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,archivos);
        lv1=(ListView)findViewById(R.id.listView1);
        lv1.setAdapter(adaptador1);

        iv1=(ImageView)findViewById(R.id.imageView1);

        lv1.setOnItemClickListener(new AdapterView.OnItemClickListener(){

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                                    long arg3) {
                Bitmap bitmap1 = BitmapFactory.decodeFile(getExternalFilesDir(null)+"/"+archivos[arg2]);
                iv1.setImageBitmap(bitmap1);
            }});

    }
}

Definimos cuatro variables:

    private ListView lv1;
    private ImageView iv1;
    private String[] archivos;
    private ArrayAdapter<String> adaptador1;

Recuperamos la lista de todos los archivos almacenados en la memoria externa y los guardamos en un vector:

        File dir=getExternalFilesDir(null);
        archivos=dir.list();

Creamos el ArrayAdapter con todos los nombres de archivos y los visualizamos en el ListView:

        adaptador1=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,archivos);
        lv1=(ListView)findViewById(R.id.listView1);
        lv1.setAdapter(adaptador1);

Mostramos en un ImageView el contenido de la foto que seleccionamos del ListView:

            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                                    long arg3) {
                Bitmap bitmap1 = BitmapFactory.decodeFile(getExternalFilesDir(null)+"/"+archivos[arg2]);
                iv1.setImageBitmap(bitmap1);
            }});

Otra parte muy importante para probar esta aplicación con el emulador de Android es su correcta configuración. Entremos a la opción AVD Manager:

Tomar foto

En este diálogo entremos a modificar la configuración del emulador que estemos utilizando:

Tomar foto

Y activamos la cámara:

Tomar foto

Este proyecto lo puede descargar en un zip desde este enlace: proyecto055.zip


Retornar