Probleme beim Kopieren einer SQLite Datenbank

J

Jooker86

Neues Mitglied
0
Hallo zusammen,

bin noch relativ neu in der Android-Programmierung und komme gerade an einem Punkt nicht weiter. Ich habe eine Datenbank mit "SqliteBrowser" erstellt und diese in den Assets-Ordner kopiert. Danach habe ich in Android Studio die Klassen nach den folgenden zwei Tutorials erstellt:

blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

Die Methode createDataBase() wird bei mir nicht in der MainActivity sondern in der als nächstes geöffneten Activity aufgerufen (ich weiß nicht, ob das von Bedeutung ist). Dabei wird die Datenbank jedoch nicht erstellt bzw. kopiert. Ich erhalte stattdessen folgenden Error-Log:

Code:
03-30 21:46:29.323 28881-28881/? W/System.err: java.io.FileNotFoundException: database.db
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.content.res.AssetManager.openAsset(Native Method)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.content.res.AssetManager.open(AssetManager.java:324)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.content.res.AssetManager.open(AssetManager.java:298)
03-30 21:46:29.323 28881-28881/? W/System.err:  at MYPACKAGENAME.database.DBHelper.copyDataBase(DBHelper.java:47)
03-30 21:46:29.323 28881-28881/? W/System.err:  at MYPACKAGENAME.database.DBHelper.onCreate(DBHelper.java:78)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
03-30 21:46:29.323 28881-28881/? W/System.err:  at MYPACKAGENAME.database.DBHelper.createDataBase(DBHelper.java:31)
03-30 21:46:29.323 28881-28881/? W/System.err:  at MYPACKAGENAME.activities.MasterMainmenue.onCreate(MasterMainmenue.java:98)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.Activity.performCreate(Activity.java:6289)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.ActivityThread.access$900(ActivityThread.java:177)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.os.Handler.dispatchMessage(Handler.java:102)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.os.Looper.loop(Looper.java:145)
03-30 21:46:29.323 28881-28881/? W/System.err:  at android.app.ActivityThread.main(ActivityThread.java:5951)
03-30 21:46:29.333 28881-28881/? W/System.err:  at java.lang.reflect.Method.invoke(Native Method)
03-30 21:46:29.333 28881-28881/? W/System.err:  at java.lang.reflect.Method.invoke(Method.java:372)
03-30 21:46:29.333 28881-28881/? W/System.err:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
03-30 21:46:29.333 28881-28881/? W/System.err:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)

Ich habe schon so ziemlich alle Foren nach diesem Fehler durchsucht und besonders auf "stackoverflow" viel dazu gefunden, aber alle dort vorgeschlagenen Lösungen halfen bei mir nichts.

Ich habe auch öfter mal etwas von SD-Karten gelesen, deshalb bin ich mir nicht ganz sicher, ob der Pfad /data/data/PACKAGE-NAME/databases/ nun auf dem Gerät oder auf der SD-Karte liegt? Eine SD-Karte ist bei mir jedenfalls nicht im Gerät und ich möchte auch nicht, dass die Datenbank dorthin kopiert wird.

Hier noch der Code von meinem DBHelper:

Code:
public class DBHelper extends SQLiteOpenHelper{

    private static String DB_PATH = "/data/data/MYPACKAGENAME/databases/";
    private static String DB_NAME = "database.db";
    private SQLiteDatabase myDataBase;
    private final Context myContext;

    public DBHelper(Context context){
        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    public void createDataBase(){
        if(checkDataBase()){

        }else{
            this.getReadableDatabase();
            copyDataBase();
        }
    }

    private boolean checkDataBase(){
        File f = new File(DB_PATH + DB_NAME);
        if(f.exists()){
            return true;
        }else{
            return false;
        }
    }

    private void copyDataBase(){
        try{
            InputStream myInput = myContext.getAssets().open(DB_NAME);
            String outFileName = DB_PATH + DB_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();
        }catch (IOException e){
            e.printStackTrace();
        }

    }

    public void openDataBase(){
        myDataBase = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
    }

    public void closeDataBase(){
        if(myDataBase != null){
            myDataBase.close();
        }
    }



    @override
    public void onCreate(SQLiteDatabase db) {
     

    }

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

    }


Wäre super, wenn mir jemand helfen könnte!

Vielen Dank!
Gruß
Tom
 
Zuletzt bearbeitet von einem Moderator:
Bearbeitet von: u.k-f - Grund: Code in Code-Tags gepackt
Ich hab das Szenario mit deinem Quellcode mal nachgestellt und es hat alles problemlos geklappt.
Jooker86 schrieb:
private static String DB_PATH = "/data/data/MYPACKAGENAME/databases/";
Hast du vielleicht in der Zeile vergessen dein Paket Namen anstelle von "MYPACKAGENAME" einzutragen?
 
Nee, da steht da schon mein richtiger Paket Name. Hab das nur für diesen Beitrag im Quellcode und dem Error-Log verändert.

Dann kann es ja nur am Handy liegen. Ich wollte mir mal den Installations-Ordner der App anschauen und hab das Gerät mal an den PC angeschlossen. Konnte aber nichts von meiner App auf dem ganzen Gerät finden. /data/data/ ist komplett leer und andere Apps aus dem App Store finde ich unter /Android/data/...
Da weiß ich allerdings nicht, ob das der Installationspfad ist oder ob das nur sonstige Dateien der Apps sind, weil in den Ordnern da auch nur Werbe-Videos und -Bilder drinnen sind. Hab gelesen, dass man Root-Rechte braucht, um die Dateien sehen zu können. Gilt das auch für den PC-Browser?
Kann es vielleicht an den fehlenden Root-Rechten liegen, dass die Datenbank nicht kopiert werden kann?
 
Das du nur mit dem Datei Explorer auf die Dateien Zugreifen kannst, wenn du Root hast ist richtig. Das nur deine App Zugriff auf den Ordner hat ist gewollt, deshalb dürfte es auch keine Probleme geben wen deine App ohne Root versucht auf den Ordner zuzugreifen.

Versuch mal den Ort deiner Datenbank per "getDatabasePath(DB_NAME)" zu bekommen und dann die Datenbank zu kopieren:
Code:
public void createDataBase() {
        File dbPath = myContext.getDatabasePath(DB_NAME);
        if (checkDataBase(dbPath)) {

        } else {
            this.getReadableDatabase();
            copyDataBase(dbPath);
        }
    }

    private boolean checkDataBase(File dbPath) {
        if (dbPath.exists()) {
            return true;
        } else {
            return false;
        }
    }

    private void copyDataBase(File dbPath) {
        try {
            InputStream myInput = myContext.getAssets().open(DB_NAME);
            //String outFileName = DB_PATH + DB_NAME;           
            OutputStream myOutput = new FileOutputStream(dbPath);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myOutput.flush();
            myOutput.close();
            myInput.close();
        } catch (IOException e) {          
            e.printStackTrace();
        }

    }
 
Bitte korrigiert mich, wenn ich falsch liege aber ich dachte der Fehler entsteht, weil die Assets nicht gelesen werden können und nicht, weil etwas mit dem Verzeichnis nicht stimmt.
Ich glaube dein Dateiname ist einfach nur falsch. Vielleicht ein Tippfehler? Schau bitte mal nach, ob die Datei im Assets Ordner "database.db" heißt
 
Also der Dateiname ist richtig. Ich habe es jetzt jeweils einmal mit und ohne Dateiendung einmal mit und ohne dem .getDatabasePath-Befehl probiert. Es kommt leider immer der selbe Fehler. Ich werde jetzt einfach mal probieren, das Handy zurückzusetzen, weil es ja offensichtlich daran liegt.
 
Zurücksetzen bringt auf jeden fall nichts
[doublepost=1459440172,1459440077][/doublepost]Kannst du das Projekt eventuell irgendwo als Zip hochladen, damit ich es mir anschauen kann?
 
Ich hab's mal hochgeladen:

GELÖSCHT
 
Zuletzt bearbeitet:
Ich hab mir das gerade kurz angeschaut und du hast die Datenbank in einem Unterverzeichnis im assets Ordner. Wenn du die Datei öffnen willst musst du den Ordner natürlich noch mit angeben.
Code:
InputStream myInput = myContext.getAssets().open("database/" + DB_NAME);

Damit ist bei mir kein Fehler aufgetaucht aber das ist nicht gerade die eleganteste Lösung

p.s. Die App sieht bisher ganz gut aus aber man kann noch nicht überall scrollen, nur als kleiner Hinweis :smile:
 
Das war es leider auch nicht. Wenn ich das mache kommt das als Fehler:

java.io.FileNotFoundException: database/database

Ich hatte aber auch schon probiert die Datenbank ohne Unterordner direkt in Assets zu speichern, ging auch nicht.

PS: Auf jeden Fall jetzt schon mal VIELEN DANK für deine/eure Mühe! Die App ist ja noch lange nicht fertig. Das ist mein erstes Projekt und alles, was da drinnen ist hab ich mir aus Foren und Videos angeeignet. Erstmal mach ich alles funktionsfähig und dann versuch ich es zu verstehen :) Ob das der richtige Weg ist, sei dahingestellt....bis zu diesem Problem hat's jedenfalls geklappt.
 
Wirklich? Bei mir hat es funktioniert :confused2:
Ich schau mir das ganze morgen nochmal an, wenn ich zeit hab

Haha, ich hab erhlich gesagt auch so angefangen und mittlerweile würde ich sagen versteh ich auh alles ziemlich gut aber es braucht seine zeit, bis man wirklich alles drauf hat. Auf jeden fall nicht aufgeben! :flapper:
 
Ahh, jetzt hab ich`s. Ich habe bei mir im Dateinamen (DB_NAME) die Endung .db noch ergänzt und jetzt kommt wirklich kein Fehler mehr :D
 
Das hatte ich auch schon probiert. Dann unterscheidet sich allerdings nur die Fehlermeldung:

java.io.FileNotFoundException: database
oder
java.io.FileNotFoundException: database.db

Wenigstens ist es gut zu hören, dass es bei anderen funktioniert :) Kann man denn anhand des Fehler-Codes, den ich ganz oben gepostet hab, rauslesen, bei welchem Vorgang der Fehler auftaucht? Oder kann es an Einstellungen des Handys liegen? Z.b. dass der Installationspfad bei mir aus irgendwelchen Gründen ein anderer ist?
 
Nein, wenn du den ordner mit angibst funktioniert es :D
Also

Code:
InputStream myInput = myContext.getAssets().open("database/" + DB_NAME);

Und natürlich kann man das rauslesen
Die Fehlermeldung ist so aufgebaut, dass zuerst die Funktion steht, in der der Fehler aufgetreten ist. Wenn man weiterschaut sieht man in den nächsten zeilen dann die Funktion, die die vorherige aufgerufen haben und immer so weiter
Sagen wir mal es gibt 3 Funktionen

A() -> B() -> C()

Wenn jetzt in der Funktion C() ein Fehler auftritt steht im Log zuerst die Funktion C() und die Zeile, mit dem Fehler, dann kommt Funktion B() mit der Zeile, in der C() aufgerufen wurde und dann A() mit der Zeile in der B() aufgerufen wurde.
Du musst also die erste Funktion finden, die in einer Klasse in deinem Package ist. Das ist in diesem Fall diese Zeile:

03-30 21:46:29.323 28881-28881/? W/System.err: at MYPACKAGENAME.database.DBHelper.copyDataBase(DBHelper.java:47)

Die Zahl, die in der Klammer steht ist die Zeile mit dem Fehler. Durch die anderen Informationen in dem Log kann man sehen, dass der AssetManager die Datei nicht finden also muss es eigentlich am Dateinamen liegen :)
 
  • Danke
Reaktionen: Jooker86
Jetzt hat es funktioniert! Das mit dem Aufbau der Fehlermeldung hab ich noch nicht gewusst. Dass da die Zeile angegeben wird ist natürlich sehr hilfreich, denn dann kann ich in Zukunft gezielter nach dem Fehler googlen.

Vielen vielen Dank für die Hilfe!!!
 

Ähnliche Themen

M
  • MikelKatzengreis
Antworten
10
Aufrufe
212
swa00
swa00
R
Antworten
6
Aufrufe
997
swa00
swa00
S
Antworten
33
Aufrufe
2.659
Sempervivum
S
Zurück
Oben Unten