sql >> Base de Datos >  >> RDS >> SQLite

¿Cómo iniciar la aplicación con SQLite darabase en el emulador de Android Studio?

Como tiene dificultades, el siguiente es un tutorial elaborado apresuradamente junto con el código.

  1. Cree la base de datos y las tablas en una herramienta SQLite, agregue datos según sea necesario y luego guárdelo.

  2. Cierre la base de datos y vuelva a abrirla para verificar que las tablas y los datos sean los esperados. Si no, haga cambios y luego repita 2 hasta que esté seguro de que la base de datos guardada coincide.

  3. Obtenga el nombre de archivo de la base de datos guardada y regístrelo, incluida la extensión del archivo.

  4. Si aún no ha creado un proyecto para la aplicación, hágalo y guarde el proyecto.

  5. Fuera del IDE, navegue a la carpeta de proyectos app/src/main y cree una carpeta llamada assets si aún no existe.

  6. Copie el archivo de la base de datos en la carpeta de activos.

  7. Abra el Proyecto en Android Studio.

  8. Cree una nueva clase Java llamada DatabaseHelper con SuperClass como SQLiteOpenHelper (se resolverá en android.database.sqlite.SQLiteOpenHelper ) y marque Mostrar anulaciones seleccionadas Casilla de diálogo. Haga clic en Aceptar.

Debería verse como:-

public class DatabaseHelper extends SQLiteOpenHelper {
    public Databasehelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
  1. Agregue una línea, como variable de clase, después de public class DatabaseHelper extends SQLiteOpenHelper { eso es como :-

    public static final String DBNAME = "my_dic.db";
    
    • Tenga en cuenta que es importante que el valor entre comillas sea exactamente el mismo que el nombre del archivo que se copió en la carpeta de activos.

.

  1. Agregue las siguientes variables de clase

:-

public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
  • Tenga en cuenta que los valores entre comillas deben coincidir con los nombres de las tablas/columnas restantes que se definieron en la base de datos para TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE y COl_BOOKMARK_DATE.
    • DBVERSION será el número de versión almacenado en el campo user_version de la base de datos.
    • SQliteDatabase mDB es una declaración de una variable para contener SQLiteDatabase cuando se ha abierto. NOTA actualmente su valor es nulo hasta que se haya establecido.

.

  1. Cambie el constructor de la clase Databasehelper de :-

    Public DatabaseHelper (contexto de contexto, nombre de cadena, fábrica SQLiteDatabase.CursorFactory, versión int) {super (contexto, nombre, fábrica, versión); }

a :-

public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
}
  • Esto hace que se pueda crear una instancia de la clase Databasehelper con solo un parámetro, el contexto. Los otros valores se han definido o, en el caso de la fábrica, no se usará ninguno, por lo que nulo significa esto.

.

  1. Agregue un método, ifDBExists a la clase DatabaseHelper para verificar si la base de datos existe (solo desea copiarla del archivo de activos una vez)

:-

private boolean ifDBExists(Context context) {
    String dbparent = context.getDatabasePath(DBNAME).getParent();
    File f = context.getDatabasePath(DBNAME);
    if (!f.exists()) {
        Log.d("NODB MKDIRS","Database file not found, making directories."); //<<<< remove before the App goes live.
        File d = new File(dbparent);
        d.mkdirs();
        //return false;
    }
    return f.exists();
}
  • Además de comprobar que el archivo de la base de datos existe (tenga en cuenta que se supone que es un archivo de base de datos válido),
  • Además, si la base de datos no existe, es posible que el directorio de la base de datos no exista, esto lo creará si no existe.

.

  1. Agregue otro método copyDBFromAssets para copiar el archivo de activos a la base de datos

:-

private boolean copyDBFromAssets(Context context) {
    Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
    String DBPATH = context.getDatabasePath(DBNAME).getPath();
    InputStream is;
    OutputStream os;
    int length = 8192;
    long bytes_read = 0;
    long bytes_written = 0;
    byte[] buffer = new byte[length];

    try {

        is = context.getAssets().open(DBNAME);
    } catch (IOException e) {
        Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
        e.printStackTrace();
        return false;
    }

    try {
        os = new FileOutputStream(DBPATH);
    } catch (IOException e) {
        Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
        e.printStackTrace();
        return false;
    }
    Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
    while (length >= 8192) {
        try {
            length = is.read(buffer,0,length);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - RD ASSET",
                    "Failed while reading in data from the Asset. " +
                            String.valueOf(bytes_read) +
                            " bytes read ssuccessfully."
            );
            e.printStackTrace();
            return false;
        }
        bytes_read = bytes_read + length;
        try {
            os.write(buffer,0,length);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                    DBPATH +
                    ". " +
            String.valueOf(bytes_written) +
                    " bytes written successfully.");
            e.printStackTrace();
            return false;

        }
        bytes_written = bytes_written + length;
    }
    Log.d("CPYDBINFO",
            "Read " + String.valueOf(bytes_read) + " bytes. " +
                    "Wrote " + String.valueOf(bytes_written) + " bytes."
    );
    try {
        os.flush();
        is.close();
        os.close();
    } catch (IOException e ) {
        Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                String.valueOf(bytes_read) +
                " bytes read." +
                String.valueOf(bytes_written) +
                " bytes written."
        );
        e.printStackTrace();
        return false;
    }
    return true;
}
  • Tenga en cuenta que esto es intencionalmente extenso, de modo que cualquier falla pueda identificarse con precisión.

La clase completa de DatabaseHelper ahora sería:-

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "my_dic.db"; // <<<< VERY IMPORTANT THAT THIS MATCHES DATABASE FILE NAME
    public static final int DBVERSION = 1;
    public static final String TB_BOOKMARK = "Bookmark";
    public static final String COL_BOOKMARK_KEY = "key";
    public static final String COL_BOOKMARK_VALUE = "value";
    public static final String COL_BOOKMARK_DATE = "date";
    SQLiteDatabase mDB;

    public DatabaseHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        if (!ifDBExists(context)) {
            if (!copyDBFromAssets(context)) {
                throw new RuntimeException("Failed to Copy Database From Assets Folder");
            }
        }
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    private boolean ifDBExists(Context context) {
        String dbparent = context.getDatabasePath(DBNAME).getParent();
        File f = context.getDatabasePath(DBNAME);
        if (!f.exists()) {
            Log.d("NODB MKDIRS","Database file not found, making directories.");
            File d = new File(dbparent);
            d.mkdirs();
            //return false;
        }
        return f.exists();
    }

    private boolean copyDBFromAssets(Context context) {
        Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
        String DBPATH = context.getDatabasePath(DBNAME).getPath();
        InputStream is;
        OutputStream os;
        int length = 8192;
        long bytes_read = 0;
        long bytes_written = 0;
        byte[] buffer = new byte[length];

        try {

            is = context.getAssets().open(DBNAME);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
            e.printStackTrace();
            return false;
        }

        try {
            os = new FileOutputStream(DBPATH);
        } catch (IOException e) {
            Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
            e.printStackTrace();
            return false;
        }
        Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
        while (length >= 8192) {
            try {
                length = is.read(buffer,0,length);
            } catch (IOException e) {
                Log.e("CPYDB FAIL - RD ASSET",
                        "Failed while reading in data from the Asset. " +
                                String.valueOf(bytes_read) +
                                " bytes read ssuccessfully."
                );
                e.printStackTrace();
                return false;
            }
            bytes_read = bytes_read + length;
            try {
                os.write(buffer,0,length);
            } catch (IOException e) {
                Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
                        DBPATH +
                        ". " +
                String.valueOf(bytes_written) +
                        " bytes written successfully.");
                e.printStackTrace();
                return false;

            }
            bytes_written = bytes_written + length;
        }
        Log.d("CPYDBINFO",
                "Read " + String.valueOf(bytes_read) + " bytes. " +
                        "Wrote " + String.valueOf(bytes_written) + " bytes."
        );
        try {
            os.flush();
            is.close();
            os.close();
        } catch (IOException e ) {
            Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
                    String.valueOf(bytes_read) +
                    " bytes read." +
                    String.valueOf(bytes_written) +
                    " bytes written."
            );
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

.

  1. Cambie el constructor para ejecutar copyDBFromAssets método cuando/si la base de datos no existe (usando el ifDBExists método)

:-

public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
    if (!ifDBExists(context)) {
        if (!copyDBFromAssets(context)) {
            throw new RuntimeException("Failed to Copy Database From Assets Folder");
        }
    }
    mDB = this.getWritableDatabase();
}
  • Tenga en cuenta que si hubo un problema al copiar la base de datos, la aplicación se detendrá debido a la RunTimeExcpetion emitido.

.

  1. Última modificación del método onCreate de una actividad (normalmente sería la actividad principal) para crear una instancia de la clase DatabaseHelper. Luego ejecute la aplicación (si la aplicación se ha ejecutado, sería mejor eliminar los datos de la aplicación antes de hacerlo, en caso de que se haya creado una base de datos, quizás vacía).

El siguiente código también incluye una consulta que le dirá qué tablas existen en la base de datos:-

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DatabaseHelper mDBHlpr = new DatabaseHelper(this);
        Cursor csr = mDBHlpr.getWritableDatabase().query(
                "sqlite_master",
                null,null,null,null,null,null
        );
        while (csr.moveToNext()) {
            Log.d("DB TABLES", csr.getString(csr.getColumnIndex("name")));
        }
        csr.close();
    }
}

Basado en la captura de pantalla y un archivo de base de datos llamado my_dic.db . La salida en el Registro es:-

06-16 02:28:45.208 4467-4467/? D/NODB MKDIRS: Database file not found, making directories.
06-16 02:28:45.208 4467-4467/? D/CPYDBINFO: Starting attemtpt to cop database from the assets file.
    Initiating copy from asset filemy_dic.db to /data/data/com.mydictionaryapp.mydictionaryapp/databases/my_dic.db
    Read 12288 bytes. Wrote 12288 bytes.
06-16 02:28:45.224 4467-4467/? D/DB TABLES: Bookmark
    sqlite_autoindex_Bookmark_1
    android_metadata
  • Esto indica que:-
    • La base de datos no existía y se creó el directorio de bases de datos (es decir, data/data/<package name>/databases )
    • Se copiaron 12288 bytes del archivo de recursos al archivo de la base de datos (es decir, se realizó una copia correcta).
    • La base de datos resultante tiene tres entradas en la tabla sqlite_master, la tabla BookMark, una tabla llamada android_metadata (una tabla creada automáticamente para dispositivos Android por el SDK que almacena la configuración regional) y un índice generado automáticamente para la tabla BookMark.

Problema posterior

Básicamente, el objeto no tiene un método llamado getClass, sino que debe usar el método getClass heredado de Fragment. Por lo tanto, debe encerrar el fragmento devuelto entre paréntesis.

Así que en lugar de :-

String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();

Podrías usar:-

String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();

Alternativamente, podría usar :-

Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);

junto con el uso de :-

if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code

en lugar de usar if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......