Bases de Datos en aplicaciones Android

En esta entrada hablaré sobre el uso de una base de datos en una aplicación Android. Para ello nos ayudaremos de la clase SQLiteOpenHelper. En mi caso la necesidad de usarla surge al realizar un “juego de preguntas”. En vez de hacer una serie de actividades con preguntas y respuestas, se opta por hacer una actividad donde 5 botones recogen información sobre una pregunta y sus 4 respuestas de la base de datos. Así, si hay que modificar alguna pregunta o añadir más sólo habría que modificar la base de datos, sin tener que añadir nuevas actividades con nuevas preguntas y respuestas.

Empezaremos por ver la estructura de la base de datos: para ello (en mi caso) trabajaremos con la herramienta Squilteman. En la base de datos “bd_futbol_preguntas” crearé una nueva tabla llamada “questions_table” con los siguientes campos:

  • id: campo para identificar cada pregunta
  • type: tipo para distinguir entre preguntas planas o con imágenes
  • question: pregunta que se mostrará al usuario
  • right_anser: respuesta correcta
  • wrong_anser_1: respuesta mala 1
  • wrong_anser_2: respuesta mala 2
  • wrong_anser_3: respuesta mala 3
  • url_video: enlace  hacia un video o web explicando la respuesta

 

Hay que decir que esta estructura es para este caso, cada aplicación se adaptará a sus necesidades.

En mi caso, se vería así, con 6 preguntas ya almacenadas.

 

Con la base de datos creada, nos vamos a nuestro proyecto en Andorid Studio. Creamos la clase DBHelper (extends de SQLiteOpenHelper): declaramos los distintos campos y leemos la tabla y cargamos las preguntas (que hemos guardado en la carpeta “raw” de nuestro proyecto):

 

public class DBHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;
    private static String DATABASE_PATH = "";
    private static final String DATABASE_NAME = "bd_futbol_preguntas";
    private static final String TABLE_QUESTIONS = "questions_table";

    private static final String KEY_ID = "id";
    private static final String KEY_TYPE = "type";
    private static final String KEY_QUESTION = "question";
    private static final String KEY_R_ANSW = "right_answer";
    private static final String KEY_W_ANSW_1 = "wrong_answer_1";
    private static final String KEY_W_ANSW_2 = "wrong_answer_2";
    private static final String KEY_W_ANSW_3 = "wrong_answer_3";
    private static final String KEY_URL_VIDEO = "url_video";

    private SQLiteDatabase questions_db;
    private Context context;

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;

        if(android.os.Build.VERSION.SDK_INT >= 17){
            DATABASE_PATH = context.getApplicationInfo().dataDir + "/databases/";
        }
        else
        {
            DATABASE_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        }
    }


    public void createDataBase() throws IOException{
        boolean dbExist = checkDataBase();

        if(!dbExist){
            this.getReadableDatabase();

            try{
                copyDataBase();
            }catch(IOException e ){
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkDataBase(){
        SQLiteDatabase checkDB = null;

        try{
            String myPath = DATABASE_PATH + DATABASE_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        }catch(SQLiteException e){
            e.printStackTrace();
        }

        if(checkDB !=null)
            checkDB.close();

        return checkDB !=null ? true : false;
    }


    private void copyDataBase() throws IOException{

        InputStream myInput = context.getResources().openRawResource(R.raw.bd_futbol_preguntas);
        String outFileName = DATABASE_PATH + DATABASE_NAME;

        OutputStream myOutput = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }

        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    public void openDataBase() throws SQLException{
        String myPath = DATABASE_PATH + DATABASE_NAME;
        questions_db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    }

    @Override
    public synchronized void close(){
        if(questions_db!=null)
            questions_db.close();

        super.close();
    }

Question getQuestion(int id){
    Cursor cursor = questions_db.query(TABLE_QUESTIONS, new String[]{KEY_ID, KEY_TYPE, KEY_QUESTION, KEY_R_ANSW, KEY_W_ANSW_1, KEY_W_ANSW_2, KEY_W_ANSW_3, KEY_URL_VIDEO}, KEY_ID + "=?",
            new String[]{String.valueOf(id)}, null, null, null, null);

    if(cursor!=null)
        cursor.moveToFirst();

    ArrayList<String> wrong_answers = new ArrayList<>();
    wrong_answers.add(cursor.getString(4));
    wrong_answers.add(cursor.getString(5));
    wrong_answers.add(cursor.getString(6));

    Question question = new Question(Integer.parseInt(cursor.getString(0)), Integer.parseInt(cursor.getString(1)), cursor.getString(2), cursor.getString(3), wrong_answers);

    if(cursor.getString(7) != null)
        question.setUrl_video(cursor.getString(7));

    return question;
} 
}


 

Seguimos con la funcionalidad de las distintas actividades para cargar los datos de la tabla.  Primero, en nuestro layout, para las preguntas y respuestas tendremos los IDs text_question, text_option1, text_option2,  text_option3 y  text_option4. Para identificarlos y rellenarlos con los datos usaremos las funciones initQuestionView y addTextQuestion:

private void initQuestionView() {
    textView = (TextView) findViewById(R.id.text_question);
    opcion1 = (Button) findViewById(R.id.text_option1);
    opcion2 = (Button) findViewById(R.id.text_option2);
    opcion3 = (Button) findViewById(R.id.text_option3);
    opcion4 = (Button) findViewById(R.id.text_option4);
}

private void addTextQuestion() {
    textView.setText(question.getQuestion());

    ArrayList<String> answers = new ArrayList<>();
    answers = question.getWrong_answers();
    answers.add(question.getRight_answer());

    // Shuffle the arraylist
    long seed = System.nanoTime();
    Collections.shuffle(answers, new Random(seed));

    opcion1.setText(answers.get(0));
    opcion2.setText(answers.get(1));
    opcion3.setText(answers.get(2));
    opcion4.setText(answers.get(3));

    pos_right_answer = answers.indexOf(question.getRight_answer());
}

Vemos como se “barajan” las respuestas para que cambien de botón y almacenamos la respuesta correcta en la variable pos_right_anser.

question será un objeto de la clase Questión (que se ha creado con la estructura de una pregunta: pregunta, respuesta correcta e incorrectas…).

Y el método que las llamará será updateQuestion (que se llamará en onCreate y cada vez que queramos cambiar de pregunta):

private void updateQuestion(){
    question = db.getQuestion(id_questions.get(i_question));
    i_question++;

    addTextQuestion();
}

i_question será una variable para llevar el control del número de preguntas que llevamos.

Esta última parte es orientativa, cada aplicación tendrá su estructura y distintas funcionalidades para cargar los datos. En esta entrada pongo una parte de dichas funcionalidades de mi aplicación: las que hacen uso de la base de datos creada y que pueden ser de más ayuda.

Finálmente, quedaría asi:

dpbfp9qg

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s