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;
Muy buena la información, me gustaría ver el video a ver como funciona seria lo ideal antes de implementarlo..
ResponderEliminarGracias....
Si en este momento estoy termiando un proyecto donde lo implemento, en breve subire mas info y videos sobre el tema
EliminarHola Muy Buna ayuda pero Me saca error en app.com.databasefull.database.SQLcontrolador;
ResponderEliminar