SQLite
 sql >> Datenbank >  >> RDS >> SQLite

Wie starte ich eine App mit SQLite Darabase auf dem Android Studio-Emulator?

Da Sie Schwierigkeiten haben, ist das Folgende ein hastig zusammengestelltes Tutorial zusammen mit Code.

  1. Erstellen Sie die Datenbank und die Tabellen in einem SQLite-Tool, fügen Sie Daten nach Bedarf hinzu und speichern Sie sie dann.

  2. Schließen Sie die Datenbank und öffnen Sie sie erneut, um zu überprüfen, ob die Tabellen und Daten wie erwartet sind. Wenn nicht, nehmen Sie Änderungen vor und wiederholen Sie Schritt 2, bis Sie sicher sind, dass die gespeicherte Datenbank übereinstimmt.

  3. Rufen Sie den Dateinamen der gespeicherten Datenbank ab und notieren Sie ihn einschließlich der Dateierweiterung.

  4. Wenn Sie noch kein Projekt für die App erstellt haben, tun Sie dies und speichern Sie das Projekt.

  5. Navigieren Sie außerhalb der IDE zum Ordner app/src/main des Projekts und erstellen Sie einen Ordner mit dem Namen assets falls es noch nicht existiert.

  6. Kopieren Sie die Datenbankdatei in den Assets-Ordner.

  7. Öffnen Sie das Projekt in Android Studio.

  8. Erstellen Sie eine neue Java-Klasse namens DatabaseHelper mit SuperClass als SQLiteOpenHelper (wird in android.database.sqlite.SQLiteOpenHelper aufgelöst ) und kreuzen Sie Ausgewählte Überschreibungen anzeigen an Dialog-Kontrollkästchen. Klicken Sie dann auf OK.

Es sollte so aussehen:-

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. Fügen Sie eine Zeile als Klassenvariable hinzu, nachdem public class DatabaseHelper extends SQLiteOpenHelper { das ist wie :-

    public static final String DBNAME = "my_dic.db";
    
    • Beachten Sie, dass es wichtig ist, dass der Wert in den Anführungszeichen genau mit dem Dateinamen übereinstimmt, der in den Assets-Ordner kopiert wurde.

.

  1. Fügen Sie die folgenden Klassenvariablen hinzu

:-

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;
  • Beachten Sie, dass die Werte in Anführungszeichen mit den entsprechenden Tabellen-/Spaltennamen übereinstimmen müssen, die in der Datenbank für TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE und COl_BOOKMARK_DATE definiert wurden.
    • DBVERSION ist die Versionsnummer, die im Feld user_version der Datenbank gespeichert ist.
    • SQliteDatabase mDB ist eine Deklaration für eine Variable, die die SQLiteDatabase enthält, wenn sie geöffnet wurde. HINWEIS:Derzeit ist sein Wert null, bis er festgelegt wurde.

.

  1. Ändern Sie den Konstruktor für die Databasehelper-Klasse von:-

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

zu :-

public DatabaseHelper(Context context) {
    super(context, DBNAME, null, DBVERSION);
}
  • Dadurch kann eine Instanz der Databasehelper-Klasse mit nur einem Parameter, dem Kontext, erstellt werden. Die anderen Werte wurden definiert oder im Falle der Fabrik werden keine verwendet, also bedeutet null dies.

.

  1. Fügen Sie eine Methode hinzu, ifDBExists an die DatabaseHelper-Klasse, um zu prüfen, ob die Datenbank existiert (Sie wollen sie nur einmal aus der Assets-Datei kopieren)

:-

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();
}
  • Zusätzlich zur Überprüfung, ob die Datenbankdatei existiert (beachten Sie, dass es sich um eine gültige Datenbankdatei handelt),
  • Außerdem, wenn die Datenbank nicht existiert, kann es sein, dass das Datenbankverzeichnis nicht existiert, dies wird es erstellen, wenn es nicht existiert.

.

  1. Fügen Sie eine weitere Methode copyDBFromAssets hinzu um die Asset-Datei in die Datenbank zu kopieren

:-

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;
}
  • Beachten Sie, dass dies absichtlich langatmig ist, damit jeder Fehler lokalisiert werden kann.

Die vollständige DatabaseHelper-Klasse wäre jetzt :-

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. Ändern Sie den Konstruktor, um copyDBFromAssets auszuführen Methode, wenn/falls die Datenbank nicht existiert (unter Verwendung der ifDBExists Methode)

:-

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();
}
  • Beachten Sie, wenn beim Kopieren der Datenbank ein Problem aufgetreten ist, wird die App aufgrund der RunTimeExcpetion gestoppt ausgestellt.

.

  1. Ändern Sie zuletzt die onCreate-Methode einer Aktivität (normalerweise die Hauptaktivität), um eine Instanz der DatabaseHelper-Klasse zu erstellen. Führen Sie dann die App aus (wenn die App ausgeführt wurde, ist es am besten, die Daten der App vorher zu löschen, nur für den Fall, dass eine möglicherweise leere Datenbank erstellt wurde.)

Der folgende Code enthält auch eine Abfrage, die Ihnen mitteilt, welche Tabellen in der Datenbank vorhanden sind:-

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();
    }
}

Basierend auf dem Screenshot und einer Datenbankdatei namens my_dic.db . Die Ausgabe im Log ist :-

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
  • Dies zeigt an, dass :-
    • Die Datenbank existierte nicht und das Datenbankverzeichnis wurde erstellt (d.h. data/data/<package name>/databases )
    • 12288 Bytes wurden von der Asset-Datei in die Datenbankdatei kopiert (d. h. es wurde eine erfolgreiche Kopie erstellt).
    • Die resultierende Datenbank hat drei Einträge in der sqlite_master-Tabelle, der BookMark-Tabelle, einer Tabelle namens android_metadata (eine automatisch vom SDK für Android-Geräte erstellte Tabelle, die das Gebietsschema speichert) und einen automatisch generierten Index für die BookMark-Tabelle.
    • li>

Folgeausgabe

Grundsätzlich hat das Objekt keine Methode namens getClass, sondern Sie müssen die geerbte getClass-Methode des Fragments verwenden. Daher müssen Sie das zurückgegebene Fragment in Klammern einschließen.

Also statt :-

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

Sie könnten :-

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

Alternativ könnten Sie :-

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

zusammen mit der Verwendung von:-

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

statt if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ...... zu verwenden