Warum funktioniert SQLite DB kopieren nicht

  • 8 Antworten
  • Neuester Beitrag
Diskutiere Warum funktioniert SQLite DB kopieren nicht im Android App Entwicklung im Bereich Android OS.
S

stikker

Neues Mitglied
Hallo, ich habe folgendes Problem. Ich erstelle eine Datenbank und zur Kontrolle möchte ich die in anderes Verzeichnis verschieben, da man ja nicht ohne weiteres an die Datenbanken ran kommt.
Wenn ich meinen Code starte kommt folgendes:
D/INFO: Helper hat die Datenbank: testdb.db erzeugt.
D/KEINE DB !!!: KEINE DB !!!
D/DURCH !!!: DURCH !!!!
Sprich, der ist der Meinung, dass die Datenbank erstellt wurde, aber zum kopieren ist sie doch nicht da.
Wo liegt der Fehler ?

package com.example.dbtest;

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

import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class MainActivity extends AppCompatActivity {
SQLiteServer_user sqLiteServerUser;

@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

sqLiteServerUser = new SQLiteServer_user(MainActivity.this);

try {
File backupDB = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "my_data_backup.db");
File currentDB = getDatabasePath("testdb.db");
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Log.d("DONE !!!", "DONE !!!");
} else {
Log.d("KEINE DB !!!", "KEINE DB !!!");
}
} catch (IOException e) {
Log.d("FEHLER !!!", "FEHLER !!!!");
}

Log.d("DURCH !!!", "DURCH !!!!");
}
}

class SQLiteServer_user extends SQLiteOpenHelper {
private static final String DatabaseName = "testdb.db";

SQLiteServer_user(Context context) {
super(context, DatabaseName, null, 1);
Log.d("INFO", "Helper hat die Datenbank: " + getDatabaseName() + " erzeugt.");
}

@override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String createTable = "CREATE TABLE user (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"datum TEXT);";
sqLiteDatabase.execSQL(createTable);

}

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

}
}
 
swa00

swa00

Moderator
Teammitglied
Hallo ,

deine angewandte Filehandling - Technik ist leider falsch.
du benötigst keine Filestreams


Siehe hier :
SQLiteOpenHelper | Android Developers

In deinem Beispiel - ändere den Constructor
SQLiteDatabase database = new SQLiteServer_user (Context,[FILENAME]).getWritableDatabase();
 
Zuletzt bearbeitet:
S

stikker

Neues Mitglied
Danke erstmal.
Ich rufe das jetzt so auf:
sqLiteServerUser = new SQLiteServer_user(MainActivity.this).getWritableDatabase();

dann kommt:
java.io.FileNotFoundException: /storage/emulated/0/Download/my_data_backup.db: open failed: EACCES (Permission denied)

setze ich in der manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

selber Fehler.

Wenn ich aber in dem Anwendungsmanager gehe und dann die app wähle und Berechtigung Speicher erlaube geht es.
Aber wie schalte ich das per Programm ein ?
 
J

jogimuc

Stammgast
Hallo
Erstmal eines um eine Datei auf System Ebne zu kopieren darf die nicht geöffnet sein.
Das heißt du musst deine DB schließen bevor du die Datei kopieren kannst.
Ist ja bei Windows auch nicht anders.

Zweitens bin ich mir bei drinem path der Datei nicht sicher ob der stimmt.

Ist normalerweise /data/data/deinPaketName/...

Auch noch eine Frage unter welcher Android Version arbeitest du?
Denn ab sdk 29 ist der Zugriff auf denn externen Datenträger nicht mehr so einfach.

Das wirst du da mit SAF machen müssen.
Beitrag automatisch zusammengefügt:

Du siehst ja schon an der Aussage
D/KEINE DB !!!: KEINE DB !!!
Das die Abfrage der DB mit dem von dir gewählten paht ein false zurück gibt.
 
Zuletzt bearbeitet:
swa00

swa00

Moderator
Teammitglied
@jogimuc

Jörg, ich denke du meintest wahrscheinlich eher ab API 23 :)

@stikker
Wenn du ab API 23 (Marshmellow) in dem von Dir gewählten Pfad arbeiten möchtest,
benötigst du eine gesonderte User-Permission.
Request App Permissions | Android Developers
 
Zuletzt bearbeitet:
J

jogimuc

Stammgast
@swa00
Nein das meine ich nicht mir ist klar das sich ab 23 die Permission geändert haben.
Ab 29 oder sogar ab Android 8 ist es nicht mehr mit den klassischen Java File Methoden möglich auf die externe sd karte zu zugreifen.
Auch sein Path zu seiner DB Datei wird nicht richtig sein.

Er will ja die DB Datei auf System Ebene kopieren.

Zugriff auf den Download Ordner sollte gehen, da der eigentlich als interner Speicher vom System angesehen wird.
String rootPath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/xxxx.txt
File file=new File(rootPath);

Request App Permissions | Android Developers
natürlich vorausgesetzt.
Ohne die User Permissions API 23 geht es auch mit dem Download Ordner nicht mehr.

um auf einen XY Ordner der SD Karte zuzgreifen brauchst du ab API 29 SAF.
What is Scoped Storage in Android 11?
 
Zuletzt bearbeitet:
S

stikker

Neues Mitglied
Habe mal ein bisschen gebastelt.

Wenn ich folgendes ausführe:
sqLiteServerUser = new SQLiteServer_user(MainActivity.this).getWritableDatabase();
...
private static final String DATABASE_FILE_PATH = "" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
private static final String DatabaseName = "testdb.db";

SQLiteServer_user(Context context) {
super(context, DATABASE_FILE_PATH + File.separator + DatabaseName, null, 1);
Log.d("INFO", "Helper hat die Datenbank: " + getDatabaseName() + " erzeugt.");
}

@override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String createTable = "CREATE TABLE user (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"datum TEXT);";
sqLiteDatabase.execSQL(createTable);

String insert="INSERT INTO user (datum) VALUES ('2020-03-16');";
sqLiteDatabase.execSQL(insert);
}
...
wird die Datenbank gleich im Downloadverzeichnis erstellt ohne kopieren. Damit kann ich mir das kopieren sparen.
Aber warum schreibt der nichts in die Datenbank rein ?

Achja ich erstelle meine App unter API
minSdkVersion 16
targetSdkVersion 29
 
J

jogimuc

Stammgast
Hallo hast du denn auch die permission vom User zu Laufzeit bekommen? Wie schon gesagt reicht es nicht mehr nur sie im Manifest zu setzen.

Wird den in der DB auch deine Tabelle erstellt oder nur die Datei?

Das Schreiben in die DB würde ich nicht mit execsql machen. Sondern mit der insert Methode der DB.

Mit der execsql methote werden nicht alle SQL Befehle unterstützt.
Dazu gibst es die Methoden der DB Klasse.

Könnte auch sein das android nicht den klassischen SQL Befehl unterstützt.
Sondern in einer anderen Form haben will.

Zb mit Set

INSERT INTO tabelle SET spalte1='Wert1', spalte2='Wert2'

Deshalb benutze die DB Methode dafür.
 
Zuletzt bearbeitet:
S

stikker

Neues Mitglied
Danke für die Weiterhilfe. Scheint so als wenn in dem Fall wirklich nur die Android Funktionen gehen.
Ich mache das jetzt so:
sqLiteServerUser=new SQLiteServer_user(this);
sqLiteServerUser.insertData("2020-04-12");
....

public boolean insertData(String datum) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("datum", datum);
long result = db.insert("user", null, contentValues);
if (result == -1)
return false;
else
return true;
}
...

Damit speichert er jetzt wirklich die Daten in einer Datenbank, die im Ordner Dowload liegt.
 
Ähnliche Themen - Warum funktioniert SQLite DB kopieren nicht Antworten Datum
1
28
1