Página Principal

miércoles, 27 de abril de 2016

SGC: Mi primer Proyecto - Parte I

Aquí le presento la primera parte de mi primer App  para android que la tome con seriedad.

Se llama Sistema de Gestión Comercial: Kiosquin. Es un proyecto que desarrolle para la habilitación profesional de mi carrera.
Este vídeo fue el comienzo funcional de mi app, ABM de productos(utilizando tabs fragments y la cam para leer código de barra), Base de datos (SQLite3)

Nota: véanlo desde una PC, porque el vídeo contiene notas, que desde un móvil no se ven.
Aclaración: La app se ve lenta, pero es la grabación


En breve subiré la siguiente parte, donde ya funciona la parte de ventas, con filtros de búsqueda por nombre o código de barra, popups, y con algo de temas y estilo para que visualmente sea mas agradable

un Saludo

lunes, 25 de abril de 2016

Backup de una BD(SQLite) en Android

Aquí mostrare un ejemplo de como generar o restaurar un Backup de una Base de Dato en android.

En principio hay que aclarar algunas cuestiones. Una vez creada la base de datos, tenemos que saber donde se aloja la misma...

/data/data/com.example.app/databases/example.db

Para un ejemplo generico, la BD asi se guardara en nuestra memoria interna.

public class GestionBackup {

    private Context contexto;

    public static final String PACKAGE_NAME = "app.com.kiosquin_v43";
    public static final String DATABASE_NAME = DBhelper.DB_NAME;
    public static final String APP_PATH = "/Kiosquin-v4.3/backup/";

    public static final String RUTA_BACKUP = Environment.getExternalStorageDirectory().
            getAbsolutePath() + APP_PATH;

    /** Contains: /data/data/com.example.app/databases/example.db **/
    private static final String DIR_DB_INTERNA =
                    "/data/" + PACKAGE_NAME +
                    "/databases/" + DATABASE_NAME;

    private static final String DIR_DB_BACKUP =
                    APP_PATH + "myDB.db";

    public GestionBackup(Context c){
        File file = new File(RUTA_BACKUP);
        //creo el directorio donde ira puesto el backup (Sin esto no lo puede generar)
        file.mkdirs();
        contexto=c;
    }

    public void importDB() {
        try {
            File sd = Environment.getExternalStorageDirectory();
            File data = Environment.getDataDirectory();
            if (sd.canWrite()) {

                File backupDB = new File(data, DIR_DB_INTERNA);
                File currentDB = new File(sd, DIR_DB_BACKUP);

                FileChannel src = new FileInputStream(currentDB).getChannel();
                FileChannel dst = new FileOutputStream(backupDB).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
                Mensaje.ver("Import Exitoso!",contexto);

            }
        } catch (Exception e) {

            Mensaje.ver("Import Erroneo!", contexto);

        }
    }

    public void exportDB() {
        try {
            File sd = Environment.getExternalStorageDirectory();
            File data = Environment.getDataDirectory();

            if (sd.canWrite()) {

                File currentDB = new File(data, DIR_DB_INTERNA);
                File backupDB = new File(sd, DIR_DB_BACKUP);

                FileChannel src = new FileInputStream(currentDB).getChannel();
                FileChannel dst = new FileOutputStream(backupDB).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
                Mensaje.ver( "Backup Exitoso!",contexto);

            }
        } catch (Exception e) {

            Mensaje.ver("Backup Erroneo!", contexto);

        }
    }
}

La clase Mensaje para los que les interese, ahí estará mas detallada.

Creo que el ejemplo esta bastante claro de seguir,

* PACKAGE_NAME:
                                  Nombre o dirección del paquete de nuestra app;
* DATABASE_NAME:
                                  Nombre de nuestra Base de Dato;          

* APP_PATH:
                     Direccion donde se alojara nuestra Backup

* RUTA_BACKUP:
     //Se obtiene la direccion completa, No la utilizo. porque al crear el file uso otro constructor
     Environment.getExternalStorageDirectory(). getAbsolutePath() + APP_PATH

* DIR_DB_INTERNA = 
                                 "/data/" + PACKAGE_NAME + "/databases/" + DATABASE_NAME;

* DIR_DB_BACKUP = 
                                 APP_PATH + "myDB.db";

Por ultimo aclarar que lo que hacen estas funciones son copiar y pegar el archivo de la base de dato en el destino que elegimos con el nombre que nosotros definimos al archivo.
Hay otras formas de hacer el backup "Mas Segura" pero esta me parece la mas sencilla y anda bien

Un saludo

La Clase Estatica Mensaje

Bueno esta clase es útil para mantener prolijidad y claridad en nuestro código. Evitar copiar y pegar un código, haciéndolo repetitivo

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.Gravity;
import android.widget.Toast;

import app.com.kiosquin_v43.inicio.LoginActividad;
import app.com.kiosquin_v43.ventas.VendedorActividad;

public class Mensaje {
 
 public static void ver(String mensaje, Context context){
  Toast toast = Toast.makeText(context,
       mensaje, Toast.LENGTH_SHORT);
      toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
      toast.show();
 }

 public static void salir(final Context context){

  new AlertDialog.Builder(context)
    .setIcon(android.R.drawable.ic_dialog_alert)
    .setTitle("Volver al login")
    .setMessage("Estas seguro?")
    .setNegativeButton("No", null)//sin listener
    .setPositiveButton("Si",
      new DialogInterface.OnClickListener() {
       //un listener que al pulsar, cierre la aplicacion
       @Override
       public void onClick(DialogInterface dialog, int which){

        Intent main = new Intent(context, Clase_login_inicial.class)
          .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(main);
       }
      }).show();
 }
}
 

La primer función estática ver tiene dos parámetros, el primero un String que sera el mensaje a mostrar, y el segundo el contexto a donde se quiere mostrar. Lo que hace es muy simple, genera un mensaje Toast bien centrado y lo muestra. Ejemplo:

                                               Mensaje.ver("Muestro mensaje", this);

La segunda función estática salir, básicamente sirve preguntar si quiere salir de una actividad al apretar el botón Back (tienen que configurarlo). Crea un AlertDialog.Builder, con un titulo, un msj y 2 botones. Luego lo muestra

@Override //se agrega en la actividad donde quiere incorporar el cartel
public void onBackPressed() { //Implemento menu para salir al login

            Mensaje.salir(this)
}

domingo, 24 de abril de 2016

Clase Estatica Fecha en Android

Hola gente! Voy a mostrar una clase estática Fecha que les puede ser de utilidad. Importante al momento de tener que trabajar con la clase Date y necesiten guardarlo en una Base de Datos o viceversa.

Para el que desconoce como darle formato a la fecha, debería ver SimpleDateFormat.

los 2 formatos mas utilizado por mi, en un Date completo, es:

SimpleDateFormat("dd/MM/yyyy HH:mm:ss")

donde la HH, en mayúscula, hace referencia a el formato de 24h, el otro formato es:

SimpleDateFormat("dd/MM/yyyy hh:mm:ss a")

donde hh, en minuscula, nos muestra el formato de 12h, y la a, se refiere cambio pm y am.



public class Fecha {

    public static String actual(){
        SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        //SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a");
        return formateador.format(new Date());
    }
    public static Date getDia(String fecha){
        //SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a");
        SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        try {
            return formateador.parse(fecha);
        } catch (ParseException e) {
            return null;
        }
    }
    public static String getDia(Date fecha){
        SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        //SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss a");
        if ( fecha != null )
        {
            return formateador.format(fecha);
        } else {
            return "";
        }
    }

    public static String getDiaSinHora(Date fecha){
        SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
        if ( fecha != null )
        {
            return formateador.format(fecha);
        } else {
            return "";
        }
    }
    public static String getDiaSinHora(String fecha){
        SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
        try {
            return formateador.format(formateador.parse(fecha));
        } catch (ParseException e) {
            return "";
        }
    }
}

No es muy difícil de leer, básicamente funciona como la clase Integer cuando queremos convertir un string a int, solo que dependiendo el formato que busquemos en Date sera la función.

Aquí un ejemplo:

...
editTextFecha.setText("Fecha: "+Fecha.getDia(new Date()));
...

sábado, 23 de abril de 2016

Capturar evento de botón con setOnClickListener

Hola, En esta entrada mostrare algo simple pero útil, que le dará claridad y prolijidad a sus códigos, tanto para ustedes como para el que lo intente seguir, para un posible mantenimiento o lo que sea.

Esto esta apuntado a gente que se esta iniciando en el mundo de programación en android.

Cuando nos enseñaban android por primera vez, nos muestran que para capturar eventos debemos implementar OnClickListener, luego hacer la funcion onClick(View v) y dentro de ella hacer lo que se haga con el botón.. pero ¿que pasa si tenes mas de un botón? hay que degenerar el código con tantos if como botones tenga. O un Switch si son muchísimos.

Esta practica que les pasare a explicar hay que hacerlo para cada botón que vinculemos con el layout.

Así es como nos enseñan por primera vez




public class LoginActividad extends Activity implements OnClickListener{
 
 TextView tvUsuarioRegistro;
 EditText etNombre, etPass;
 Button bEntrar;
 Usuario usuario;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.ini_login);
  
  tvUsuarioRegistro = (TextView) findViewById(R.id.tvUsuarioRegistroClic);
  etNombre = (EditText) findViewById(R.id.etUsuarioNombre);
  etPass = (EditText) findViewById(R.id.etUsuarioPass);
  bEntrar = (Button) findViewById(R.id.btUsuarioEntrar);

  bEntrar.setOnClickListener(this);
  tvUsuarioRegistro.setOnClickListener(this);
  
  
 
  @Override
  public void onClick(View v) {
    if(v.getId()==findViewById(R.id.btUsuarioEntrar).getId()){
     
     //Aqui va lo que el boton debe hacer, una vez presionado  
    }
    if(v.getId()==findViewById(R.id.tvUsuarioRegistroClic).getId()){
     
     Intent actividad = new Intent(LoginActividad.this, RegistroActividad.class);
    startActivity(actividad);  
    }
           
  }  
 }
}
 

Y así es deberia;



public class LoginActividad extends Activity {
 
 TextView tvUsuarioRegistro;
 EditText etNombre, etPass;
 Button bEntrar;
 Usuario usuario;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.ini_login);
  
  tvUsuarioRegistro = (TextView) findViewById(R.id.tvUsuarioRegistroClic);
  etNombre = (EditText) findViewById(R.id.etUsuarioNombre);
  etPass = (EditText) findViewById(R.id.etUsuarioPass);
  bEntrar = (Button) findViewById(R.id.btUsuarioEntrar);

  bEntrar.setOnClickListener(new OnClickListener() {
 
   @Override
   public void onClick(View v) {
    
    //Aqui va lo que el boton debe hacer, una vez presionado       
   }  
  }); 
  tvUsuarioRegistro.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Intent actividad = new Intent(LoginActividad.this, RegistroActividad.class);
    startActivity(actividad); 
   }  
  });
 }
}

No es que sea mas sencillo, ni nos ahorraremos de escribir, pero la claridad y prolijidad suma a la hora de mantener un código

Espero que les sirva o no, dependerá de como se sienta mas cómodo cada uno.
Un saludo

miércoles, 30 de marzo de 2016

Objetos Parcelable en Android


Si llegaron aquí, se encontraron con el problema de ¿Cómo paso objetos complejos a través de las actividades? Bueno cabe aclarar que según sé, no es la única forma (en JAVA podríamos serializar objetos). Pero, Android nativamente nos provee de esta nueva clase extendida llamada Parcelable.

No voy a comparar ni evaluar cuál es mejor, pero asumo que ésta última se integra mejor, especialmente por estar creada para Android.

Vamos a crear el típico ejemplo de objeto Persona como si fuera java pero implementando Parcelable. Se vera de esta forma:


public class Persona implements Parcelable 
{
 SimpleDateFormat formateador;
 
    String nombre;
    int edad;
    Date fechaNacimiento;
 
    public Persona() {
        super();
  formateador = new SimpleDateFormat("dd/MM/yyyy");
    }
 
    public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    public int getEdad() {
        return edad;
    }
 
    public void setEdad(int edad) {
        this.edad = edad;
    }
 
    public String getFechaNacimiento() {
        if ( fechaNacimiento!= null )
  {
   return formateador.format(fechaNacimiento);
  }
  else
  {
   return "";
  } 
    }
 
    public void setFechaNacimiento(Date fecha_Nacimiento) {
        try
  {
   this.fechaNacimiento = formateador.parse(fecha_Nacimiento);
  }
  catch (ParseException e)
  {
   this.fechaNacimiento = null;
  }
    }
 

NOTA: La fecha de nacimiento solo se guarda como Date, pero esta manejada como String y no Date. Esto es porque en Android y más precisamente si utilizamos SQLite, solo habrá TEXT. Entonces como puse en el ejemplo, será la mejor forma de capturar y formatear el objeto

Ahora bien, hasta aquí creamos un objeto común y corriente. Pero cuando implementan Parcelable les exigirá que coloquen al menos dos nuevos métodos (writeToParcel() y describeContents()). El segundo no lo utilizaras. El primero si es importante ya que nos permitirá escribir nuestro objeto en un Parcel.


@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.nombre);
    dest.writeInt(this.edad);
    dest.writeString(formateador.format(fechaNacimiento));
}
 

Nota: Otra ventaja de manejar la fecha como String es que tanto para escribir como leer un Parcel no reconoce la clase Date.

También es necesario crear un constructor que reciba un parámetro tipo Parcel, el cual nos permitirá crear nuestro objeto desde allí.


public Producto(Parcel in){
  super();
  formateador = new SimpleDateFormat("dd/MM/yyyy");
  readFromParcel(in);
}

private void readFromParcel(Parcel in) {

  this.nombre = in.readString();
  this.edad = in.readInt();
  try
  {
   this.fechaNacimiento = formateador.parse(in.readString());
  }
  catch (ParseException e)
  {
   this.fechaNacimiento = null;
  }    
    }

Nota Importante: Como se puede observar, tanto para leer como escribir un Parcel, no existe key o una posición o algo que nos indique que dato extraemos, por lo que en este caso el orden si altera el producto, será importante siempre escribir o leer los datos en el mismo orden o generara un error o mínimo se intercambiaran los atributos.

Ahora para generar las instancias de nuestra clase parcelable necesitamos un objeto Parcelable.Creator, el cual se verá así:


public static final Parcelable.Creator<Persona> CREATOR = new Parcelable.Creator<Persona>() {
    public Persona createFromParcel(Parcel source) {
        return new Persona(source);
    }
 
    public Persona[] newArray(int size) {
        return new Persona[size];
    }
};

Una vez hecho esto, ya tendríamos el objeto funcional. Bien ahora les mostrare como darle uso práctico en el traspaso de actividades por medio de Intent...


//En Main
 
 Persona unaPersona= new Persona();
 
 EditText nombreEdittext = (EditText) findViewById(R.id.nombreEditText);
        EditText edadEditText = (EditText) findViewById(R.id.edadEditText);
        TextView fechaTextView = (TextView) findViewById(R.id.fechaTextView);

 unaPersona.setNombre(nombreEdittext.getText().toString());
 unaPersona.setEdad(edadEditText.getText().toString());
 unaPersona.setFechaNacimiento(fechaTextView.getText().toString());
 
 Intent intent = new Intent(this, Activity2.class);     
        intent.putExtra("OBJETO_PERSONA", persona);
        startActivity(intent);
 
//En la Activity2
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity2);
 
    Bundle b = getIntent().getExtras();
    Persona persona = b.getParcelable("OBJETO_PERSONA");
 
    EditText editTextNombre = (EditText)findViewById(R.id.editTextNombre);
    EditText editTextEdad = (EditText)findViewById(R.id.editTextEdad);
    EditText editTextFecha = (EditText)findViewById(R.id.editTextFecha);
 
    editTextNombre.setText(persona.getNombre());
    editTextEdad.setText(String.valueOf(persona.getEdad()));
    editTextFecha.setText(persona.getFechaNacimiento());
 

Cualquier duda comenten
Un saludo, Cidius

domingo, 27 de marzo de 2016

EditText con Botones símil WhatsApps

Hola gente:


Acá en esta entrega voy a explicar cómo hacer que un EditText de Android se “vea” como si tuviera botones dentro de él, como en WhatsApp...


En principio, desconociendo si verdaderamente la gente que diseño este formato lo hace de otra forma. Debo decirles que esto es solamente un efecto visual, por eso antes escribí  el “vea”.

Si amigos, lo que debemos hacer es trabajar a nivel XML. Primero debemos insertar un EditText y tantos botones (dependiendo nuestro diseño serán ImageButton) quedáramos dentro de un componente layout con orientación horizontal (Para que estén uno al lado del otro).


Lo siguiente es tan simple como modificar el estilo al layout contenedor con esta línea:
style="@android:style/Widget.EditText"

Quedando de esta forma…



 <LinearLayout
        style="@android:style/Widget.EditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" 
        android:layout_marginTop="10dp">

        <EditText
            android:id="@+id/editProductoBuscar"
            android:layout_width="210dp"
            android:layout_height="wrap_content"
            android:background="@null" >
        </EditText>

        <ImageButton
            android:id="@+id/buttonProductoBusqueda"
            android:layout_width="38dp"
            android:layout_height="38dp"
            android:src="@drawable/lupitas" />

        <ImageButton
            android:id="@+id/imageButtonProductoCam"
            android:layout_width="40dp"
            android:layout_height="38dp"
            android:layout_marginLeft="2dp"
            android:src="@android:drawable/ic_menu_camera" />
    </LinearLayout>
 



Así es como se vería el diseño final de ese layout mostrado:


Espero que les sirva
Un saludo, Cidius


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;