Página Principal

viernes, 25 de marzo de 2016

Guardar imagenes con SQLite

Hola amigos!
Estoy iniciando mis primeros pasos en este mundo de los blogger. Así que sepan disculpar lo desordenado...

Llevo tiempo programando en android, primero en eclipse y ahora en Android Studio cada vez mas, pero me sucedió que buscando información, vídeos, código reciclable, lo que sea sobre como tratar las imágenes con una base de datos SQLite y no encontré nada que me cerrara, por eso decidí volcar algo de contenido sobre este tema. Si bien encontré sugerencias, diferencia entre guardar la imagen en la base de datos o solo una ruta a la memoria, que es mejor, y porque. Me parece que les puedo aportar algo de luz

Mi idea y luego de leer algunos foros, nada es definitivo, pero me intereso mas guardar la imagen en la SDcard, en alguna carpeta destino, y conservar la ruta de esa imagen en la base de dato en forma de String.

En esta entrada voy a explicar todo mediante una actividad que primero te permita tomar una foto, se crea todo el proceso de archivo, se guarda en la SDcard y se extrae la dirección completa, para luego guardarla en una Base de datos.

En el siguiente ejemplo muestro la actividad principal.


   
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import app.com.databasefull.database.SQLcontrolador;

public class MiActivity extends AppCompatActivity {

    //ruta base de la SDcard: /storage/sdcard0/...
    private final String ruta_fotos = Environment.getExternalStorageDirectory().
                                            getAbsolutePath() +"/Kiosquito/com/imagenes/";
    private File file = new File(ruta_fotos);
    private Button botonTomarFoto, botonVerListaDeFotos;
    private TextView textview;
    SQLcontrolador sqlcontrol;

    Uri uri;
    File mi_foto;

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

        //Inicializo y abro la base;
        sqlcontrol = new SQLcontrolador(this);
        sqlcontrol.abrirBaseDeDatos();

        //======== codigo nuevo ========
        botonTomarFoto = (Button) findViewById(R.id.btnTomaFoto);
        botonVerListaDeFotos = (Button) findViewById(R.id.buttonVerFotos);
        textview = (TextView) findViewById(R.id.textView);

        //Si no existe crea la carpeta donde se guardaran las fotos
        file.mkdirs();
        //accion para el boton para tomar una foto;
        botonTomarFoto.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            String file = ruta_fotos + getCode() + ".png";
            mi_foto = new File( file );
            try {
            mi_foto.createNewFile();
            } catch (IOException ex) {
                    Log.e("ERROR ", "Error:" + ex);
                    }
                //
                uri = Uri.fromFile( mi_foto );
                //Abre la camara para tomar la foto
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                //Guarda imagen
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                //Retorna a la actividad
                startActivityForResult(cameraIntent, 0);

                }
        });
        //Boton que ejecuta una actividad con un listview que muestra las imagenes (*)-1
        botonVerListaDeFotos.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent imagenesIntent = new Intent(getApplicationContext(),VerFotos.class);
                startActivity(imagenesIntent);
            }
        });
        //====== codigo nuevo:end ======
        }
        /**
        * Metodo privado que genera un codigo unico segun la hora y fecha del sistema
     * * @return photoCode
     * */
            @SuppressLint("SimpleDateFormat")
    private String getCode() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date() );
        String photoCode = "pic_" + date;
        return photoCode;
        }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_tomar_foto, menu);
        return true;
        }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // Comprobamos si el resultado de la segunda actividad es "RESULT_CANCELED".
        if (resultCode == RESULT_CANCELED) {
            // Si es así mostramos mensaje de cancelado por pantalla.
            Toast.makeText(this, "Resultado cancelado", Toast.LENGTH_SHORT)
                    .show();
        } else {
            //este es un text que solo muestra la dir en la actividad;
            textview.setText("dir:"+ uri.getPath());
            //Insertamos la direccion y nombre de la imagen en la base de datos (*)-2
            sqlcontrol.insertarImagen(uri.getPath(),mi_foto.getName());
            }
        }
    }
   


(*)-1 Para mostrar la imagen en un ListView tienen que usar un Adaptador base, que son los mas personalizable. Un pequeño problema que van a tener es que la foto que sacan tiene una gran resolución, y cuando las enlistar por medio del adaptador en mi dispositivo mas de 4 fotos estallaba.

Rápidamente leí que para mostrar fotos como una especie de galería, lo mejor era mostrar la miniatura de la imagen. Encontré un códigos para reciclar y obtener la imagen miniatura pero no supe hacerlo andar.
Luego de buscar bastante encontré una función que redimenciona la foto dinámicamente en java.

Aqui paso a mostrar el getView() del BaseAdapter junto con la función de redimencionarImagen. Sepan que al adaptador lo creo pasandole un ArrayList de un objeto imagen q tiene 3 atributos (id,nombre y ruta)



 @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Declare Variables
        TextView txtTitle;
        ImageView imgImg;

        //http://developer.android.com/intl/es/reference/android/view/LayoutInflater.html
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View itemView = inflater.inflate(R.layout.item_lista_img, parent, false);

        // Locate the TextViews in listview_item.xml
        txtTitle = (TextView) itemView.findViewById(R.id.tv_titulo_single_post_circuito);
        imgImg = (ImageView) itemView.findViewById(R.id.imagen_single_post_circuito);

        //Aqui creo un File con la ruta de la imagen
        File imageFile = new  File(listaObjeto.get(position).getRutaImagen());
        if(imageFile.exists()){
            //muestro el nombre de la imagen
            txtTitle.setText(listaObjeto.get(position).getNombreImagen().substring(0,18));
            //Aqui decodifico, genero y guardo en bitmap lo que esta en la direccion
            Bitmap bm=BitmapFactory.decodeFile(imageFile.getAbsolutePath());
            //Antes de mostrar la imagen en el ImageView la redimenciono
            imgImg.setImageBitmap(redimensionarImagenMaximo(bm,50,50));
        }

        return itemView;
    }

    public Bitmap redimensionarImagenMaximo(Bitmap mBitmap, float newWidth, float newHeigth){
        //Redimensionamos
        int width = mBitmap.getWidth();
        int height = mBitmap.getHeight();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeigth) / height;
        // create a matrix for the manipulation
        Matrix matrix = new Matrix();
        // resize the bit map
        matrix.postScale(scaleWidth, scaleHeight);
        // recreate the new Bitmap
        return Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, false);
    }
 

(*)-2 Les mostrare las 2 funciones que utilizo para insertar y leer las rutas y nombres de las imagenes dentro de nuestra base de datos



public void insertarImagen(String ruta, String nombre){

        ContentValues cv = new ContentValues();
        cv.put(DBhelper.IMAGEN_NOMBRE, nombre);
        cv.put(DBhelper.IMAGEN_RUTA, ruta);
        long id= database.insert(DBhelper.IMAGEN_TABLA, null, cv);
    }

    public ArrayList<ImagenObjeto> leerImagenes() {

        Cursor c = database.rawQuery("SELECT _id, nombre,ruta FROM imagenbd", null);

        ArrayList<ImagenObjeto> listImagen= new ArrayList<ImagenObjeto>();
        ImagenObjeto unImagenObj; //creo un objeto Imagen

        while(c.moveToNext()){
            unImagenObj= new ImagenObjeto();
            unImagenObj.setIdImagen(c.getInt(0));
            unImagenObj.setNombreImagen(c.getString(1));
            unImagenObj.setRutaImagen(c.getString(2));
            listImagen.add(unImagenObj); //Agrego a la lista el objeto
        }
        return listImagen;

    }
 

Bueno esto seria todo lo básico que se necesita para manejar imágenes con una base de datos SQLite.
En breve mostrare un vídeo con la App andando para que vean como funciona
Espero que les sirva y cualquier cosa pregunten.

Un saludo;

3 comentarios:

  1. Muy buena la información, me gustaría ver el video a ver como funciona seria lo ideal antes de implementarlo..

    Gracias....

    ResponderEliminar
    Respuestas
    1. Si en este momento estoy termiando un proyecto donde lo implemento, en breve subire mas info y videos sobre el tema

      Eliminar
  2. Hola Muy Buna ayuda pero Me saca error en app.com.databasefull.database.SQLcontrolador;

    ResponderEliminar