android sqlite t2_wowomnom_Fotolia_85154667

Android SQLite Datenbank Tutorial – Teil 2: Integrieren einer SQLite Datenbank in Android


Nun wünschen wir euch viel Spaß bei dem zweiten Teil unseres Android SQLite Datenbank Tutorials. Los geht’s!

1. Was ist das SQLite Datenbanksystem und wie ist SQLite in das Android System integriert?

Android Apps Programmieren Online-Kurs

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

SQLite ist eine Programmbibliothek, welche ein relationales Datenbanksystem enthält.

Das Open Source Datenbanksystem unterstützt eine Vielzahl der SQL-Sprachbefehle und wurde vor allem für den Einsatz in eingebetteten Umgebungen entworfen.

Besonders häufig wird das Datenbanksystem SQLite auf Betriebssystemen für Smartphones und Tablets eingesetzt, bspw. Symbian OS oder Android.

Der große Vorteil des SQLite Datenbanksystems ist der minimale Aufbau der Bibliothek.

Die gesamte SQLite-Bibliothek ist nur einige hundert Kilobyte groß und lässt sich direkt in die Android Anwendung integrieren. Es wird keine weitere Server-Software benötigt.

Durch das Einbinden der SQLite-Bibliothek wird eine Android App um sehr nützliche Datenbankfunktionen erweitert, ohne auf externe Software angewiesen zu sein.

Die SQLite-Datenbank besteht aus einer einzigen Datei, die alle Tabellen, Indizes usw. enthält.


Für die Kommunikation mit dem Datenbanksystem wird die spezielle Kommandosprache SQL verwendet, mit der folgende Operationen durchgeführt werden können:

  • Definition der Tabellenstruktur
  • Anlegen und Löschen von Tabellen
  • Einfügen, Ändern und Löschen von Datensätzen, die eigentlich Tabellenzeilen sind
  • Suchen von Daten aus einer oder mehreren Tabellen mit Hilfe von Suchkriterien

SQLite unterstützt die drei Datentypen TEXT, INTEGER und REAL. In Java würden diese Datentypen den Typen String, Long bzw. Double am ehesten entsprechen. Alle anderen Datentypen müssen in einen dieser drei Typen konvertiert werden, bevor sie in der Datenbank abgespeichert werden können.

Weiterhin prüft SQLite nicht, ob der Datentyp des zu speichernden Eintrags tatsächlich dem Datentyp der zugewiesenen Spalte entspricht. SQLite erzwingt somit keine Typsicherheit. Fehlerhafte Eingaben werden in der Regel akzeptiert und in Zeichenketten umgewandelt.

Weitere Informationen über SQLite findet ihr an folgenden Stellen im Internet:

1.1 Was ist eine relationale Datenbank?

Eine Datenbank im Allgemeinen ist ein Konstrukt zum Ablegen von Daten. Die Daten werden in Tabellen abgelegt und organisiert. Eine Tabelle besteht aus einer vorgegebenen Anzahl an Spalten und Zeilen.

Die Daten verschiedener Tabellen können sich gegenseitig referenzieren und dadurch Beziehungen (Relationen) aufweisen. Dann haben wir es mit relationalen Datenbanken zu tun.

In den beiden unten aufgeführten Tabellen sind Benutzer- und Rechnungsdaten abgelegt und organisiert. Jede Zeile einer Tabelle bildet einen sog. Datensatz und setzt sich aus den Werten mehrerer Spalten (Felder) zusammen.

Benutzerdaten
User-ID Benutzername
1 Fred The Red
2 Fritzle
3 Brian The Lion
4 Attila
Rechnungsdaten
Rechnungs-Nr Betrag Status User-ID
2308 120 € offen 3
2309 79 € offen 3
2310 10 € bezahlt 2
2311 199 € offen 4

Beide Tabellen besitzen jeweils eine Spalte, deren Werte innerhalb der Tabelle eindeutig sind. In den Spalten User-ID bzw. Rechnungs-Nr. gleicht kein Wert dem anderen, sie werden als Primärschlüssel bezeichnet.

In der rechten Tabelle (Rechnungsdaten) wird neben der Primärschlüssel-Spalte Rechnungs-Nr. zusätzlich die Primärschlüssel-Spalte User-ID der linken Tabelle verwendet. In diesem Fall spricht man von einem Fremdschlüssel. Somit wird die Spalte User-ID als Fremdschlüssel-Spalte in der Tabelle Rechnungsdaten verwendet.

Über den Fremdschlüssel kann eine Verbindung von einem Datensatz einer Tabelle zu einem anderen Datensatz einer anderen Tabelle hergestellt werden. So kann über den Fremdschlüssel von der Tabelle Rechnungsdaten auf die Datensätze der Tabelle Benutzerdaten verwiesen werden.

1.2 Wie ist das SQLite Datenbanksystem in Android integriert

In Android ist das SQLite Datenbanksystem fester Bestandteil der Laufzeitumgebung. Dadurch kann jede Android App sehr einfach und effizient Daten in Form einer Datenbank ablegen und auslesen.

Das Einrichten und die Administration der Datenbank wird von Android übernommen. Wir müssen nur mit Hilfe von SQL-Anweisungen die Datenbank anlegen und updaten. Anschließend wird die Datenbank automatisch vom Android System verwaltet.

Die Klassen, die für das Einbinden einer SQLite-Datenbank in einer Android App benötigt werden, sind in dem Package android.database.sqlite zusammengefasst. Wir werden in diesem Android SQLite Tutorial die Klasse SQLiteOpenHelper verwenden und dabei näher kennenlernen.

Wenn wir in unserer Android App eine Datenbank erzeugen, wird diese standardmäßig in dem Verzeichnis DATA/data/PACKAGE_NAME/databases/FILENAME/ angelegt. Dabei sind die folgenden drei Platzhalter variabel:

  • DATA – ist der Pfad der App-Umgebung, kann mit Environment.getDataDirectory() ausgegeben werden.
  • PACKAGE_NAME – ist der Name des Packages unserer Android Anwendung.
  • FILENAME – ist der Dateiname der Datenbank, den wir in unserem Code vorgeben.

Der Pfad zu unserer Datenbank wird folgendermaßen aussehen:

/data/data/de.codeyourapp.shoppinglist/databases/shopping_list.db

2. Einsatz der SQLite Datenbank in unserer Android App

Es gibt verschiedene Wege eine SQLite-Datenbank in einer Android App zu verwenden. Dabei besitzt jeder Ansatz seine eigenen Vor- und auch Nachteile.

Wir wählen für dieses SQLite Tutorial den Mittelweg, der einen einfachen und übersichtlichen Zugriff auf die SQLite Datenbank ermöglicht, dabei aber nicht zu komplex ist.

Für unseren Ansatz werden wir drei Klassen verwenden, die im gemeinsamen Zusammenspiel das Speichern und Auslesen von Daten aus der SQLite-Datenbank übernehmen.

Die drei Java-Klassen werden wir jeweils in einem eigenen Abschnitt ausführlich vorstellen. In diesem Abschnitt stehen die Beziehungen der drei Klassen untereinander im besonderen Fokus.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

In der unteren Liste sind die drei benötigten Klassen aufgeführt:

  • ShoppingMemo – Instanzen dieser Klasse können die Daten eines SQLite-Datensatzes aufnehmen. Sie repräsentieren die Datensätze im Code. Wir werden mit Objekten dieser Klasse den ListView füllen.

  • ShoppingMemoDbHelper – Sie ist eine Hilfsklasse mit deren Hilfe wir die SQLite-Datenbank erstellen lassen. Sie enthält weiterhin wichtige Konstanten, die wir für die Arbeit mit der Datenbank benötigen, wie den Tabellennamen, die Datenbankversion oder die Namen der Spalten.

  • ShoppingMemoDataSource – Diese Klasse ist unser Data Access Object und für das Verwalten der Daten verantwortlich. Es unterhält die Datenbankverbindung und ist für das Hinzufügen, Auslesen und Löschen von Datensätzen zuständig. Außerdem wandelt es Datensätze in Java-Objekte für uns um, so dass der Code unserer Benutzeroberfläche nicht direkt mit den Datensätzen arbeiten muss.

Wie aus den Beschreibungen zu den drei Klassen schon hervorgeht, ist jede Klasse auf die andere angewiesen. Die Grundlage bildet die Klasse ShoppingMemo, die wir für das Arbeiten mit den Datensätzen verwenden. Sie ist sozusagen das Datenobjekt und einem Datensatz unserer Datenbank nachgebildet.

Unsere Arbeiterklasse ist die ShoppingMemoDataSource-Klasse, die alle Verwaltungsaufgaben an der Datenbank übernimmt. Sie lässt mit Hilfe der Helper-Klasse die Datenbank erzeugen und hält die Verbindung zur Datenbank aufrecht. Durch sie können wir auf die Datensätze der Tabelle in unserer Datenbank zugreifen und diese verändern. Sie ist unser Zugriff auf die Daten, eben ein Data Access Object (DAO).

Alle wichtigen, konstanten Informationen über unsere Datenbank, wie Tabellenname, Versionsnummer, Spaltennamen oder SQL-Befehle sind in der Hilfsklasse ShoppingMemoDbHelper gesammelt. Sie ist von der Klasse SQLiteOpenHelper abgeleitet und kann daher eine Datenbank erzeugen.

Mit der DAO-Klasse ShoppingMemoDataSource nutzen wir die Helper-Klasse und lassen uns über sie eine Datenbank erzeugen und auch wieder schließen.

Steuern werden wir die ganzen Datenbankzugriffe von der MainActivity aus, die eine Instanz der ShoppingMemoDataSource-Klasse besitzen wird. Somit müssen wir dem Data Access Object nur mitteilen welche Operationen an der Datenbank ausgeführt werden sollen.

Die tatsächliche Durchführung übernimmt dann das DAO für uns.

In der unteren Abbildung sind die vier Klassen unserer Android SQLite-App dargestellt. Die Darstellung entspricht keiner Norm, sie zeigt einfach nur die Beziehungen der einzelnen Klassen zueinander.

android sqlite datenbank

Beziehungen der Klassen unserer SQLite-App untereinander

In der Abbildung entspricht die Klasse DataSource unserer Klasse ShoppingMemoDataSource, die Klasse DbHelper entspricht ShoppingMemoDbHelper und die Klasse DataObject entspricht ShoppingMemo. Die unterschiedlichen Klassennamen wurden aus Platzgründen gewählt.

In den nächsten Abschnitten werden wir die drei zu erstellenden Klassen genauer vorstellen. Dabei gehen wir auch auf die speziellen Aufgaben ein, welche die jeweilige Klasse bei der Integration der SQLite Datenbank in unsere Android App übernimmt.

3. Die Klasse ShoppingMemo – Mit ihr repräsentieren wir die Datensätze unserer SQLite Datenbank

Wir werden nun die Klasse ShoppingMemo in unserem Android Studio Projekt neu anlegen.

Diese Klasse entspricht den Datensätzen in der Tabelle unserer SQLite Datenbank. Jeder Datensatz besteht aus einer eindeutigen id, dem Namen des Produkts product und der benötigten Menge quantity.

Diesen Datensatz-Aufbau werden wir mit der neuen Klasse ShoppingMemo nachbilden, so dass Instanzen dieser Klasse die Daten eines SQLite-Datensatzes in sich aufnehmen können.

Um die Datenmodell-Klasse ShoppingMemo anzulegen, muss eine neue Java Klassendatei in dem Package-Ordner unseres Projekts erstellt werden. Dafür gibt es zwei Vorgehensweisen: über die obere Menüleiste oder über den Package-Ordner in der Project-Ansicht. Wir werden den zweiten Weg wählen, da er intuitiver und weniger fehleranfällig ist.

Als Erstes muss dafür die Project-Ansicht unseres Projekts so aufgeklappt werden, dass der Package-Ordner sichtbar wird. In diesen Package-Ordner werden wir nun die neue Klassendatei mit Hilfe des Create New Class-Dialog von Android Studio anlegen lassen.

Die Klassendatei ShoppingMemo.java unseres Datenmodells legen wir nun folgendermaßen an:

  1. Mit der rechten Maustaste auf den Package-Ordner de.codeyourapp.shoppinglist klicken.
  2. Anschließend den Eintrag New des Kontext-Menüs anklicken.
  3. Danach auf den Eintrag Java Class klicken.
android_sqlite_data_object_create

Die neue Klasse ShoppingMemo in Android Studio anlegen

Anschließend öffnet sich der Create New Class-Dialog, der uns bei der Erstellung der neuen Java Klasse unterstützt. Wir müssen nur einige Felder des Dialogs ausfüllen.

In dem Create New Class-Dialog nehmen wir nun die folgenden Einstellungen vor:

  1. Als Klassennamen tragen wir in das Feld Name ShoppingMemo ein.
  2. Den Wert für Kind lassen wir auf Class stehen.
  3. Die Felder Superclass und Interface(s) lassen wir leer.
  4. Als Package sollte bereits automatisch unser Package-Ordner de.codeyourapp.shoppinglist eingetragen sein.
  5. Alle anderen Einstellungen übernehmen wir unverändert.
  6. Den Dialog bestätigen wir mit einem Klick auf den OK Button.
android_sqlite_data_object_create_dialog

Den Namen für die neue Java Klasse festlegen

Android Studio legt nun automatisch die neue Java Klasse an. Dabei wird auch der minimale Quellcode für das Klassengerüst erzeugt. Diesen benötigen wir aber nicht und werden ihn daher vollständig durch unseren eigenen Code ersetzen.

Im Editorfenster ersetzen wir nun den gesamten Quelltext der ShoppingMemo.java mit folgendem Code:

ShoppingMemo.java

package de.codeyourapp.shoppinglist;

public class ShoppingMemo {

    private String product;
    private int quantity;
    private long id;


    public ShoppingMemo(String product, int quantity, long id) {
        this.product = product;
        this.quantity = quantity;
        this.id = id;
    }


    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }


    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }


    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }


    @Override
    public String toString() {
        String output = quantity + " x " + product;

        return output;
    }
}

Die ShoppingMemo-Klasse besitzt die drei Membervariablen product, quantity und id, auf die mit Hilfe der get– und set-Methoden zugegriffen werden kann.

Mit dem Konstruktor können wir die ShoppingMemo-Objekte erzeugen lassen. Die drei Instanzvariablen product, quantity und id werden beim Erzeugen der Objekte direkt mit den übergebenen Werten gefüllt.

Später werden wir die ShoppingMemo-Klasse nutzen, um die Daten der Datensätze unserer SQLite-Datenbank in Java-Objekten zu speichern. Diese Objekte entsprechen dann exakt einem Datensatz. Wir können dann mit den Objekten in unserem Code weiterarbeiten und ihren Inhalt bequem in einer Liste, bspw. mit Hilfe eines ListViews, ausgeben.

Ihren Inhalt können wir auch verändern und später die Änderungen in dem korrespondierenden Datensatz mit Hilfe der Objekte vornehmen. Die Klasse ShoppingMemo hilft uns somit Ordnung in das Datenchaos zu bringen und ermöglicht einen sichereren Umgang mit der SQLite-Datenbank.

In Android Studio sollte die eben erstellte Klasse ShoppingMemo.java jetzt folgendermaßen aussehen:

android_sqlite_data_object_class_code

Die Datenmodell Klassendatei ShoppingMemo.java mit dem eingefügten Quellcode

In der oberen Abbildung ist die Klasse ShoppingMemo im Editor von Android Studio bereits geöffnet. Der weiter oben aufgeführte Quellcode wurde schon eingefügt. Außerdem ist auch der Speicherort ihrer Klassendatei im Project Tool Window zu sehen.

4. Die Klasse ShoppingMemoDbHelper – Unsere Hilfsklasse für das Erzeugen der SQLite Datenbank

In diesem Arbeitsschritt werden wir eine weitere neue Java-Klasse in Android Studio anlegen. Die neue Klasse ShoppingMemoDbHelper wird uns bei dem Erzeugen und Updaten der SQLite Datenbank unterstützen.

Wie ihr Name schon andeutet, ist sie eine Hilfsklasse, die wir nicht zwingend benötigen. Sie vereinfacht aber die Arbeit mit der SQLite Datenbank sehr stark.

Die Hilfsklasse leiten wir von der Klasse SQLiteOpenHelper aus dem Package android.database.sqlite ab. Diese Elternklasse wird das eigentliche Erzeugen der SQLite Datenbank für uns übernehmen. Wir delegieren dies nur mit unserer Hilfsklasse ShoppingMemoDbHelper an sie weiter.

Die Klassendatei ShoppingMemoDbHelper.java legen wir nun, wie schon im vorherigen Abschnitt beschrieben, an:

  1. Mit der rechten Maustaste auf den Package-Ordner de.codeyourapp.shoppinglist klicken.
  2. Anschließend den Eintrag New des Kontext-Menüs anklicken.
  3. Danach auf den Eintrag Java Class klicken.
android_sqlite_dbhelper_create

Die neue Klasse ShoppingMemoDbHelper in Android Studio anlegen

Es öffnet sich wieder der Create New Class-Dialog, der uns bei der Erstellung der neuen Java Klasse unterstützt. Wir müssen nur einige Felder des Dialogs ausfüllen.

In dem Create New Class-Dialog nehmen wir nun die folgenden Einstellungen vor:

  1. Als Klassennamen tragen wir in das Feld Name ShoppingMemoDbHelper ein.
  2. Den Wert für Kind lassen wir auf Class stehen.
  3. Die Felder Superclass und Interface(s) lassen wir leer.
  4. Als Package sollte bereits automatisch unser Package-Ordner de.codeyourapp.shoppinglist eingetragen sein.
  5. Alle anderen Einstellungen übernehmen wir unverändert.
  6. Den Dialog bestätigen wir mit einem Klick auf den OK Button.
android_sqlite_dbhelper_create_dialog

Den Namen für die neue Java Klasse festlegen

Android Studio legt nun automatisch die neue Java Klasse ShoppingMemoDbHelper an. Sie wird im Package-Ordner unseres Android Projekts abgelegt, worin sich auch die MainActivity und ShoppingMemo Klassen befinden.

Im Editorfenster ersetzen wir nun den gesamten Quelltext der ShoppingMemoDbHelper.java mit folgendem Code:

ShoppingMemoDbHelper.java

package de.codeyourapp.shoppinglist;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class ShoppingMemoDbHelper extends SQLiteOpenHelper{

    private static final String LOG_TAG = ShoppingMemoDbHelper.class.getSimpleName();


    public ShoppingMemoDbHelper(Context context) {
        super(context, "PLATZHALTER_DATENBANKNAME", null, 1);
        Log.d(LOG_TAG, "DbHelper hat die Datenbank: " + getDatabaseName() + " erzeugt.");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

In dem oberen Quelltext passiert noch nicht viel. Wir sehen das minimale Grundgerüst unserer Hilfsklasse und die notwendigen Import-Anweisungen.

Da sich unsere Klasse von der SQLiteOpenHelper-Klasse ableitet, müssen wir deren beiden abstrakten Methoden onCreate() und onUpgrade() implementieren.

Mit dem Aufruf des Konstruktors der Elternklasse in Zeile 14 geben wir die wichtigen Daten für das Erzeugen der SQLite Datenbank an die SQLiteOpenHelper-Klasse weiter. Dabei enthält der context die Informationen über die Umgebung, in der die Datenbank ausgeführt wird, wie bspw. der Pfad zur Datenbank.

Den Datenbanknamen werden wir später in einer String-Konstante angeben, daher arbeiten wir hier mit einem Platzhalter. Das letzte Argument gibt die Version unserer Datenbank an. Bei jedem Datenbank-Upgrade wird dieser Wert um eins erhöht.

In Android Studio sollte die eben erstellte Klasse ShoppingMemoDbHelper jetzt folgendermaßen aussehen:

android_sqlite_dbhelper_class_code

Die neue Klasse ShoppingMemoDbHelper in Android Studio mit eingefügtem Quelltext

Wie das Erzeugen der SQLite Datenbank erfolgt, werden wir im nächsten Teil des Tutorials ausführlich beschreiben. Dann wird die Klasse ShoppingMemoDbHelper vervollständigt werden.

Für den Moment ist das minimale Grundgerüst aber ausreichend, so dass wir nun zur dritten und letzten neuen Java-Klasse unserer Android SQLite-App kommen.

5. Die Klasse ShoppingMemoDataSource – Unsere Arbeiterklasse, sie regelt die SQLite Datenbankzugriffe

Kommen wir nun zu unserer Arbeiterklasse ShoppingMemoDataSource. Sie ist für alle Datenbankzugriffe verantwortlich. Mit ihrer Hilfe schreiben wir Datensätze in die Tabelle unserer SQLite Datenbank und lesen diese auch wieder aus.

Die ShoppingMemoDataSource-Klasse besitzt eine Membervariable vom Datentyp SQLiteDatabase, in der wir unsere Datenbank-Objekte abspeichern werden. Dadurch hält die ShoppingMemoDataSource-Klasse die Verbindung zu unserer Datenbank aufrecht.

Weiterhin besitzt sie eine Membervariable vom Typ ShoppingMemoDbHelper, mit deren Hilfe wir die SQLite Datenbank erstellen lassen bzw. die Verbindung zur Datenbank herstellen können, wenn bereits eine Datenbank angelegt wurde.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Außerdem wird die Arbeiterklasse weitere Funktionen zur Verfügung stellen, die das Arbeiten mit den Datensätzen erleichtern. Dazu werden wir in späteren Teilen dieses SQLite Tutorials ausführlich eingehen.

Nun wollen wir die Klasse ShoppingMemoDataSource.java anlegen. Wie schon in den vorherigen Abschnitten beschrieben, legen wir die neue Java-Klasse folgendermaßen an:

  1. Mit der rechten Maustaste auf den Package-Ordner de.codeyourapp.shoppinglist klicken.
  2. Anschließend den Eintrag New des Kontext-Menüs anklicken.
  3. Danach auf den Eintrag Java Class klicken.
android_sqlite_data_source_create

Die neue Klasse ShoppingMemoDataSource in Android Studio anlegen

Es öffnet sich wieder der Create New Class-Dialog, der uns bei der Erstellung der neuen Java Klasse unterstützt. Wir müssen nur einige Felder des Dialogs ausfüllen.

In dem Create New Class-Dialog nehmen wir nun die folgenden Einstellungen vor:

  1. Als Klassennamen tragen wir in das Feld Name ShoppingMemoDataSource ein.
  2. Den Wert für Kind lassen wir auf Class stehen.
  3. Die Felder Superclass und Interface(s) lassen wir leer.
  4. Als Package sollte bereits automatisch unser Package-Ordner de.codeyourapp.shoppinglist eingetragen sein.
  5. Alle anderen Einstellungen übernehmen wir unverändert.
  6. Den Dialog bestätigen wir mit einem Klick auf den OK Button.
android_sqlite_data_source_create_dialog

Den Namen für die neue Java Klasse festlegen

Android Studio legt nun automatisch die neue Java Klasse ShoppingMemoDataSource an. Sie wird im Package-Ordner unseres Android Projekts abgelegt, worin sich alle von uns erstellten Klassen befinden.

Im Editorfenster ersetzen wir nun den gesamten Quelltext der ShoppingMemoDataSource.java mit folgendem Code:

ShoppingMemoDataSource.java

package de.codeyourapp.shoppinglist;


import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;


public class ShoppingMemoDataSource {

    private static final String LOG_TAG = ShoppingMemoDataSource.class.getSimpleName();

    private SQLiteDatabase database;
    private ShoppingMemoDbHelper dbHelper;


    public ShoppingMemoDataSource(Context context) {
        Log.d(LOG_TAG, "Unsere DataSource erzeugt jetzt den dbHelper.");
        dbHelper = new ShoppingMemoDbHelper(context);
    }
}

Die Klasse ShoppingMemoDataSource besteht momentan nur aus den beiden Membervariablen database und dbHelper, sowie aus dem Konstruktor ShoppingMemoDataSource(Context context).

In dem Konstruktor erzeugen wir eine ShoppingMemoDbHelper-Instanz und übergeben ihr den Context, also die Umgebung in der unsere App ausgeführt wird. Mit Hilfe der erzeugten Instanz dbHelper werden wir später die Verbindung zu unserer SQLite Datenbank herstellen.

Hinweis: Es gibt zwei Arten von Context-Objekten: den Applictaion Context (getApplicationContext()) und den Activity Context. Wir übergeben als Context den Activity Context in Form einer Referenz auf unsere MainActivity-Instanz, von welcher das ShoppingMemoDataSource-Objekt erzeugt wird.

Mehr gibt es im Moment zu dem Quellcode der Klasse ShoppingMemoDataSource nicht zu sagen. Auch diese Klasse wird mit dem SQLite Tutorial mitwachsen und Lektion für Lektion weiter vervollständigt werden.

In Android Studio sollte die eben erstellte Klasse ShoppingMemoDataSource nun folgendermaßen aussehen:

android_sqlite_data_source_class_code

Die neue Klasse ShoppingMemoDataSource in Android Studio mit eingefügtem Quelltext

Jetzt haben wir die drei benötigten Klassen angelegt und mit Quellcode befüllt. Als Nächstes sollten wir unsere Android App ausführen und testen, ob alle Arbeitsschritte korrekt durchgeführt wurden.

Wir werden dazu etwas Testcode in der MainActivity-Klasse ergänzen und anschließend unsere App auf einem Android Gerät ausführen.

6. Einfügen des Testcodes in die MainActivity der SQLite App

Jetzt sind wir fast am Ende vom zweiten Teil des Android SQLite Tutorials angekommen. Wir haben in dieser Lektion drei neue Java-Klassen erstellt, mit deren Hilfe wir in den späteren Teilen des Tutorials auf die SQLite Datenbank zugreifen werden.

Doch bevor wir mit der Datenbank arbeiten können, müssen wir sicherstellen, dass die drei neuen Klassen korrekt funktionieren.

Um dies zu testen, öffnen wir die Klassendatei MainActivity.java im Editor von Android Studio, indem wir doppelt auf ihren Dateinamen im Project Tool Window klicken. Die Klassendatei befindet sich im Package-Ordner de.codeyourapp.shoppinglist unseres Projekts.

Ihren bisherigen Quellcode lassen wir zu großen Teilen bestehen und fügen nur einige neue Zeilen darin ein. Der bereits überarbeitet Quellcode der MainActivity.java ist unten aufgeführt:

MainActivity.java

package de.codeyourapp.shoppinglist;
 
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
 
 
public class MainActivity extends AppCompatActivity {
 
    public static final String LOG_TAG = MainActivity.class.getSimpleName();
 
    private ShoppingMemoDataSource dataSource;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        ShoppingMemo testMemo = new ShoppingMemo("Birnen", 5, 102);
        Log.d(LOG_TAG, "Inhalt der Testmemo: " + testMemo.toString());
 
        dataSource = new ShoppingMemoDataSource(this);
    }
 
}

In Zeile 5 importieren wir die Log-Klasse und machen sie dadurch innerhalb unserer eigenen Klasse sichtbar. Anschließend legen wir in Zeile 10 die Konstante LOG_TAG an und speichern in ihr den Namen unserer Klasse. So können wir später im Logcat Tool Window von Android Studio direkt erkennen, wenn eine Log-Meldung von der MainActivity-Klasse ausgegeben wird.

In Zeile 12 legen wir die Membervariable dataSource an. In ihr werden wir eine Referenz auf das ShoppingMemoDataSource-Objekt speichern, wodurch unsere MainActivity-Klasse immer eine Verbindung zum Data Access Object der Datenbank aufrecht hält.

Anschließend überprüfen wir die Funktion unserer drei erstellten Klassen:

  • Testen der ShoppingMemo-Klasse – In Zeile 19 erzeugen wir die ShoppingMemo-Instanz testMemo und geben ihren Inhalt mit der Log-Anweisung in Zeile 20 an die Konsole aus.

  • Testen der beiden anderen Klassen – In Zeile 22 erzeugen wir ein ShoppingMemoDataSource-Objekt. Dadurch werden die beiden Konstruktoren der Klassen ShoppingMemoDataSource und ShoppingMemoDbHelper der Reihe nach aufgerufen und die darin angegebenen Log-Meldungen ausgegeben.

Auf diese Weise können wir prüfen, ob die drei Klassen richtig angelegt wurden. Diese Tests sind keine Funktionstests und garantieren auch nicht die Korrektheit unseres Quellcodes. Wir können aber mit diesen Tests schnell herausfinden, ob etwas beim Befolgen der Arbeitsschritte fehlgeschlagen ist. Mehr dazu im nächsten Abschnitt.

Die MainActivity.java Datei sollte in Android Studio nun wie folgt aussehen:

android_sqlite_activity_testcode

Die Klassendatei MainActivity.java mit den vorgenommenen Änderungen

Nachdem wir nun den Testcode in die MainActivity eingefügt haben, können wir die Funktion unserer Anwendung überprüfen. Dazu werden wir in den beiden nächsten Unterabschnitten unsere Android SQLite App auf einem virtuellen Android Gerät ausführen und die Log-Meldungen im Logcat Tool Window von Android Studio überprüfen.

Wenn ihr die gleichen Log-Meldungen erhaltet, sollte das Anlegen der drei Klassen auch bei euch erfolgreich verlaufen sein.

7. Ausführen und Überprüfen unserer Android SQLite App

Wir werden nun unserer Android App auf einem Android Virtual Device im Emulator ausführen lassen und die Log-Meldungen unserer Anwendung im Logcat Tool Window überprüfen. Auf diese Weise können wir das Verhalten der eben erstellten Klassen direkt in Android Studio analysieren.

Hinweis: Wenn ihr Probleme beim Ausführen der App im Android Emulator oder auf einem Android Gerät haben solltet, könnt ihr unseren großen Android Apps Programmieren Kurs als Hilfe nutzen. Darin zeigen wir, wie eine Android App im Emulator oder auf einem physikalischen Android Gerät ausgeführt wird.

Unsere App starten wir dazu wie gewohnt über den Run > Run 'app' Menüeintrag, den wir über die obere Menüleiste erreichen.

Unsere SQLite App sollte jetzt auf dem Android Gerät gestartet worden sein. Die grafische Benutzeroberfläche der Anwendung hat sich nicht geändert, daher sieht auf dem Gerät alles genau so aus wie in der vorherigen Lektion.

Hinweis: Das Emulator-Fenster mit dem darin laufenden Android Virtual Device muss für die nächsten Arbeitsschritte geöffnet bleiben. Zudem muss in dem AVD unsere eigene App ausgeführt werden. Sollte dies nicht der Fall sein, muss die App erneut im Emulator gestartet werden.

Um die Log-Meldungen zu überprüfen, öffnen wir in Android Studio das Logcat Tool Window während unsere App auf dem AVD im Emulator ausgeführt wird.

Dazu führen wir die folgenden Schritte aus:

  1. Wir öffnen das Logcat Tool Window mit einem Klick auf den Logcat-Tab am unteren Bildschirmrand.
  2. Anschließend wählen wir Emulator Nexus_9 als AVD in der Drop-Down Liste aus.
  3. Nun wählen wir unsere App de.codeyourapp.shoppinglist in der Liste rechts daneben aus.
  4. Danach stellen wir die Prioritätsstufe auf Verbose ein.
  5. Und geben in das anschließende Suchfeld MainActivity|ShoppingMemo als Suchbegriff ein.
  6. Zuletzt wählen wir den Eintrag Show only selected application in Liste ganz rechts aus.
android_sqlite_logcat_einstellungen

Überprüfen der Log-Meldungen unserer App im Logcat Tool Window von Android Studio

Mit den getätigten Einstellungen werden nun alle von unserer Anwendung ausgehenden Log-Meldungen im Logcat Tool Window ausgegeben. Wie in der oberen Abbildung zu erkennen ist, sind dies genau drei Log-Meldungen.

Zuerst teilt die MainActivity-Klasse den Inhalt der erzeugten Testmemo mit. Anschließend informiert die ShoppingMemoDataSource-Klasse darüber, dass sie nun das dbHelper-Objekt erzeugt. Woraufhin die ShoppingMemoDbHelper-Klasse uns über das Erzeugen einer Test-Datenbank informiert.

Wenn auch bei euch diese drei Log-Meldungen ausgegeben werden, hat das Erstellen der neuen Java-Klassen ordnungsgemäß funktioniert. Somit haben wir den Grundstein für unsere SQLite Datenbank Anwendung gelegt.

In den nächsten Lektionen werden wir mit den erstellten Klassen weiterarbeiten und über sie auf die SQLite Datenbank zugreifen. Dabei werdet ihr auch besser nachvollziehen können, warum wir diese Vorgehensweise gewählt haben und welche Vorteile beim Arbeiten mit dem Datenbanksystem dadurch entstehen.

Zusammenfassung

In dieser, doch etwas längeren, Lektion des Android SQLite Tutorials haben wir das Fundament für unsere Datenbank Anwendung gelegt. Die Android App macht momentan noch nichts, ist aber jetzt schon in der Lage eine SQLite Datenbank zu erzeugen.

Dies haben wir erreicht, indem wir drei neue Klassen mit Hilfe von Android Studio angelegt und diese mit Quellcode befüllt haben. Jede der drei Java-Klassen übernimmt dabei eine bestimmte Aufgabe.

Die ShoppingMemo-Klasse repräsentiert die Datensätze unserer SQLite Datenbank. Die ShoppingMemoDbHelper-Klasse hilft uns beim Erstellen und Aktualisieren der Datenbank. Die eigentliche Arbeit wird von der ShoppingMemoDataSource-Klasse übernommen, sie regelt alle Datenbankzugriffe, ob lesend oder schreibend, für unsere App.

Vor dem Anlegen der neuen Klassen haben wir das SQLite Datenbanksystem näher kennengelernt und erfahren, wie SQLite in der Android Plattform integriert ist. Danach haben wir den Ansatz vorgestellt, der beschreibt, wie wir die SQLite Datenbank in unserer Android App einsetzen wollen.

Am Ende der Lektion haben wir die MainActivity-Klasse mit Testcode erweitert und dadurch überprüft, ob alle drei Klassen korrekt angelegt wurden.

Nun sind wir bereit für den nächsten Schritt auf dem Weg hin zu einer funktionsfähigen Android SQLite Anwendung. In der nächsten Lektion werden wir eine Tabelle in unserer SQLite Datenbank anlegen und dabei SQL-Queries näher kennenlernen.



Comments 18

  1. Hallo Chris,
    erstmal auch von mir ein dickes Lob für das Tutorial. Mir gefällt vor allem, dass du auch auf die Hintergründe eingehst.

    Mein Problem:
    Ich kann im LogCat-Fenster unter Punkt 3 nichts einstellen. Bei mir steht „No debuggable processes“ in rot in der Zeile. Das Dropdown-Menu ist leer.

    Ich benutze keinen Emulator, sondern mein Samsung Galaxy S8 als physikalisches Gerät. Die App wird auch geöffnet. Ich finde nur leider in der LogCat kein „de.codeyourapp.shoppinglist“-package.

    Grüße
    Florian

    1. Post
      Author

      Hallo Florian,

      danke für dein Lob!

      Ich habe selbst ein Galaxy S8 und damit alle meine Lektionen getestet. Es hat problemlos funktioniert. Daher sollte es mit deinem Handy klappen.

      Ich denke zwar, dass du die folgenden Schritte alle befolgt hast, aber ich führe sie zur Übersicht einmal auf:

      1. Die Entwickleroptionen und das USB-Debugging auf dem Galaxy S8 müssen aktiviert sein.
      2. Das Handy muss mit dem Rechner über USB verbunden werden, nachdem in Android Studio das Projekt bereits geöffnet wurde.
      3. Auf dem Handy muss der Zugriff vom Rechner aus zugelassen werden. So wie hier beschrieben.
      4. Jetzt in Android Studio die App ausführen und auf das Handy übertragen lassen mit Run App.
      5. Das Handy angeschlossen lassen und das Logcat Tool Window öffnen. Jetzt sollte das Handy unter Punkt 2 aufgeführt sein und viele Log-Meldungen in Logcat ausgegeben werden.

      Das ist alles. Mit diesen Schritten sollten auch bei Dir die Logcat-Meldungen vom Handy in Android Studio ausgegeben werden. Mehr ist nicht zu tun. Hast du einen Viren-Scanner? Manchmal machen Anti-Viren Programme Probleme mit Android Studio.

      Sobald es Dir möglich ist die App auf das Handy mittels Run App zu übertragen, besteht ja eine funktionierende USB-Verbindung über die Android Debug Bridge. Somit sollten dann auch die Log-Meldungen darüber übertragen werden können.

      Ich hoffe, meine Aufführungen helfen Dir etwas weiter.

      Viele Grüße, Chris

  2. Hallo Chris,

    super Tutorial!

    Ich nutze das als Referenz für mein eigenes Projekt. Dabei habe ich eine Datenbank mit 3 Tabellen.
    Dadurch, dass hier in der Klasse die toString() Methode überschrieben ist, werden in den Ausgaben natürlich immer nur die Strings richtig angezeigt, die auch über toString() angefragt werden. Für alle anderen kommt ein Text wie bei Tobias:

    com.example.plabsprojects.mtgcommanderlifecounter.DB_Memo@eb38ae1
    

    Hast du eine Idee / einen Vorschlag, wie man das fixen kann?

    Viele Grüße!

    1. Post
      Author

      Hallo Pascal,

      wenn jede deiner Tabelle ein eigenes Datenmodell, hier im Tutorial die ShoppingMemo-Klasse, verwendet, muss für die entsprechenden Datenmodell-Klassen die toString() Methode implementiert werden.

      Viele Grüße, Chris

  3. Hi,

    echt ein super Tutorial! Hilfreich ist es, dass auch viele Schritte immer wiederholt werden.

    Allerdings stoße ich am Ende auf ein Problem wenn ich die App testen will. Ich bekomme folgende Fehlermeldung:

    Error:(33, 20) error: method onCreate(Bundle) is already defined in class MainActivity
    Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
    > Compilation failed; see the compiler error output for details.
    

    Sorry bin blutiger Anfänger und kann nicht erkennen, dass ich etwas falsch gemacht habe.

    Wäre super wenn mir jemand weiterhelfen kann!

    Gruß
    Peter

    1. Post
      Author

      Hallo Peter,

      danke für dein Lob! Anhand der Fehlermeldung ist in deinem Quellcode die onCreate() Methode zweimal vorhanden. Die Methode darf aber nur einmal existieren.

      Viele Grüße, Chris

  4. Hallo,
    mir gefällt das Tutorial echt gut, es ist sehr angenehm geschrieben, Danke!
    Leider möchte bei mir in der Helper Klasse einiges nicht.
    1. die super Funktion nicht und gibt mir auch keine Gründe warum.
    2. Er nutzt den Import der SQLiteOpenHelper nicht.
    3. Die Overrides sagen mir, dass sie nicht Overriden
    Wäre schön, wenn jemand Ideen hat woran es liegt

    1. Post
      Author

      Hallo Avo,

      danke für dein Lob!

      Schwer zu sagen, woran es liegt. Wenn du möchtest, kannst Du mir deine Projektdateien (den ganzen Android Studio Projektordner) als ZIP per E-Mail zusenden. Die E-Mail Adresse kannst Du im Impressum finden. Ich schaue dann mal, ob ich etwas herausfinden kann. Sollte die Zip-Datei zu groß sein, dann schicke nur die Java Quellcode-Dateien.

      Viele Grüße, Chris

  5. Hallo,

    wirkliche ein gelungenes Tutorial , das hat mir sehr geholfen!

    Ich habe jedoch ein Problem, dass ich die Datenabnkeinträge nicht angezeigt bekomme. Bei mir zeigts in der Log nur eine Art Adresse an:

    D/MainActivity: Inhalt der Testmemo:
    com.example.tuttiadmin.knobel_statistik.KnobelMemo@1780e24

    Also sind Einträge drin, aber ich kann die Daten so nicht sehen …

    1. Post
      Author

      Hallo Tobias,

      danke für’s Lob!

      Ist in deiner Klasse KnobelMemo die Methode toString() implementiert? Falls nicht, könnte das die Lösung sein.

      Viele Grüße, Chris

    2. Hallo Chris,

      ja das wars 😀

      Ich habe die Methoden automatisch angelegt und die String Methode total übersehen haha,

      vielen Dank !

  6. Hi, also ich habe da ein „kurioses“ Problem mit den Log Ausgaben. Ich lasse das Projekt auf einem Huawei Mate S laufen. Die App läuft dort Problemlos und ohne Fehlermeldung, jedoch übergibt sie keinerlei Daten an den logcat. Auf dem Device läuft Android 5.1.1, API 22.

    Wenn ich das Projekt jetzt aber über den Emulator laufen lasse, dann wird die Log Ausgabe aber ausgegeben. Kann das an einer falschen ADB Anbindung zwischen dem Huawei liegen?!

    1. Post
      Author

      Hallo Rene,

      ja, es kann schon an dem Zusammenspiel zwischen dem Huawei und Android Studio (bzw. der ADB) liegen. Es gab schon einmal eine Leserin, die über ein Problem mit ihrem Huawei berichtet hatte. Vielleicht ist auf Huawei-Geräten auch das Android Logging System etwas anders implementiert worden?

      Viele Grüße, Chris

    1. Post
      Author

      Hallo Uli,

      danke für das Lob! Es freut mich wenn das Tutorial nützlich ist und den Lesern hilft.

      Viele Grüße, Chris

  7. Ich habe den Code aus eurem Artikel mehrere Male kopiert und bekomme jedesmal nur 2 Meldungen im Log, die 1. („Inhalt der Testmemo: 5x Birnen“) wird mir nicht angezeigt.
    Kann es sein, das dies an der Android Version, auf welche die App kompiliert wird (nicht die minimal Anforderung!) liegt?

    1. Post
      Author

      Hallo Jojo,

      die erste Meldung (“Inhalt der Testmemo: 5x Birnen”) sollte auch bei dir auf jeden Fall angezeigt werden. Gerade da die anderen beiden Meldungen bei dir auch angezeigt werden. Eventuell liegt es an dem Log-Filter, da die erste Meldung von der MainActivity aus versendet wird. Versuche mal ohne Log-Filter die Meldungen zu betrachten oder nur Meldungen der MainActivity anzeigen zu lassen.

      Ich hoffe das hilft dir weiter 🙂

      Viele Grüße, Chris

  8. Pingback: Android SQLite Tutorial - Teil 1: SQLite Projekt anlegen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.