user3328547 user3328547 - 1 month ago 16
Android Question

Android sqlite getdatabase called recursively

I have got a problem with my database.
When the app start it should create the database with the tables if they not exist, but the app chrashes instantly after start. When i close the db after opening logcat tells me that "i want to open an already closed object" and when I do not close the database I have got the error "

getReadableDatabase called recursively
". I do not know what I should do. Sometimes it works but when I unistall the app and install them again the errors apear.

The error without the close:

02-20 11:50:06.980: E/AndroidRuntime(15375): FATAL EXCEPTION: main
02-20 11:50:06.980: E/AndroidRuntime(15375): java.lang.RuntimeException: Unable to start activity ComponentInfo{de.vertretungsplan2/de.vertretungsplan2.Main}: java.lang.IllegalStateException: getDatabase called recursively
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread.access$600(ActivityThread.java:153)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.os.Handler.dispatchMessage(Handler.java:99)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.os.Looper.loop(Looper.java:137)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread.main(ActivityThread.java:5289)
02-20 11:50:06.980: E/AndroidRuntime(15375): at java.lang.reflect.Method.invokeNative(Native Method)
02-20 11:50:06.980: E/AndroidRuntime(15375): at java.lang.reflect.Method.invoke(Method.java:525)
02-20 11:50:06.980: E/AndroidRuntime(15375): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
02-20 11:50:06.980: E/AndroidRuntime(15375): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
02-20 11:50:06.980: E/AndroidRuntime(15375): at dalvik.system.NativeStart.main(Native Method)
02-20 11:50:06.980: E/AndroidRuntime(15375): Caused by: java.lang.IllegalStateException: getDatabase called recursively
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:204)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-20 11:50:06.980: E/AndroidRuntime(15375): at de.vertretungsplan2.helper.DBHandler.insertPW(DBHandler.java:89)
02-20 11:50:06.980: E/AndroidRuntime(15375): at de.vertretungsplan2.helper.DBHandler.onCreate(DBHandler.java:46)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-20 11:50:06.980: E/AndroidRuntime(15375): at de.vertretungsplan2.Main.onCreate(Main.java:42)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.Activity.performCreate(Activity.java:5133)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
02-20 11:50:06.980: E/AndroidRuntime(15375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293)
02-20 11:50:06.980: E/AndroidRuntime(15375): ... 11 more


The error with close:

02-20 11:57:47.880: E/AndroidRuntime(15853): FATAL EXCEPTION: main
02-20 11:57:47.880: E/AndroidRuntime(15853): java.lang.RuntimeException: Unable to start activity ComponentInfo{de.vertretungsplan2/de.vertretungsplan2.Main}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/de.vertretungsplan2/databases/settings
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread.access$600(ActivityThread.java:153)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.os.Handler.dispatchMessage(Handler.java:99)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.os.Looper.loop(Looper.java:137)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread.main(ActivityThread.java:5289)
02-20 11:57:47.880: E/AndroidRuntime(15853): at java.lang.reflect.Method.invokeNative(Native Method)
02-20 11:57:47.880: E/AndroidRuntime(15853): at java.lang.reflect.Method.invoke(Method.java:525)
02-20 11:57:47.880: E/AndroidRuntime(15853): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
02-20 11:57:47.880: E/AndroidRuntime(15853): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
02-20 11:57:47.880: E/AndroidRuntime(15853): at dalvik.system.NativeStart.main(Native Method)
02-20 11:57:47.880: E/AndroidRuntime(15853): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/de.vertretungsplan2/databases/settings
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:263)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-20 11:57:47.880: E/AndroidRuntime(15853): at de.vertretungsplan2.Main.onCreate(Main.java:42)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.Activity.performCreate(Activity.java:5133)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
02-20 11:57:47.880: E/AndroidRuntime(15853): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2293)
02-20 11:57:47.880: E/AndroidRuntime(15853): ... 11 more


This is my DBHandler:

package de.vertretungsplan2.helper;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DBHandler extends SQLiteOpenHelper {

private static final String TAG = "DBHandler";
//Attributes of Database
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "settings";

//Attributes of table "PASSWORD"
private static final String TABLE_NAME_PW = "password";
private static final String PASSWORD_ID ="id";
private static final String PASSWORD_NAME = "password";

//Attributes of table "KURS"
private static final String TABLE_NAME_KURS = "kurs";
private static final String KURS_ID = "id";
private static final String KURS_NAME ="kurs";

//Operations
private static final String DROP_PW_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME_PW;
private static final String DROP_KURS_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME_KURS;

//Attributes of DBHandler

public DBHandler(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG,"db aktion start, DBHandler-onCreate");
/*
if(db == null || !db.isOpen()) {
db = getWritableDatabase();
}*/
createTables(db);
insertPW("-1");
insertKurs("-1");
db.close();
Log.i(TAG,"db aktion stop, DBHandler-onCreate");
}

private void createTables(SQLiteDatabase db){
Log.i(TAG,"db aktion start, DBHandler-createTables");
String CREATE_PW_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME_PW +" (" + PASSWORD_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + PASSWORD_NAME + " TEXT);";
String CREATE_KURS_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME_KURS +" (" + KURS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KURS_NAME + " TEXT);";
if(db == null || !db.isOpen()) {
db = getWritableDatabase();
}
db.execSQL(CREATE_PW_TABLE);
Log.i(TAG,"db aktion start, nach PW Table erzeugen");
db.execSQL(CREATE_KURS_TABLE);
Log.i(TAG,"db aktion start, nach Kurs Table erzeugen");
db.close();
Log.i(TAG,"db aktion stop, DBHandler-createTables");
}


@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(TAG,"db aktion start, DBHandler-onUpgrade");
Log.w(TAG,"Upgrade der Datenbank von Version " + oldVersion
+ " zu " + newVersion + "; alle Daten werden gelöscht");
db.execSQL(DROP_PW_TABLE);
Log.i(TAG,"db aktion start, OnUpgrade nach Drop PW Table");
db.execSQL(DROP_KURS_TABLE);
Log.i(TAG,"db aktion start, OnUpgrade nach Drop kurs Table");
db.close();
Log.i(TAG,"db aktion start, OnUpgrade nach close db");
onCreate(db);
Log.i(TAG,"db aktion stop, DBHandler-onUpgrade");
}

public void insertPW(String PW){
Log.i(TAG,"db aktion start, DBHandler-insertPW");
long rowId = -1;
try{
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getWritableDatabase();
}
ContentValues values = new ContentValues();
values.put(PASSWORD_NAME, PW);
rowId = db.insert(TABLE_NAME_PW, null, values);
db.close();
}catch (SQLiteException e){
Log.e(TAG,"insert()",e);
}finally{
Log.d(TAG, "insert(): rowId=" + rowId);
Log.i(TAG,"db aktion stop, DBHandler-insertPW");
}
}

public void insertKurs(String Kurs){
Log.i(TAG,"db aktion start, DBHandler-insertKurs");
long rowId = -1;
try{
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getWritableDatabase();
}
ContentValues values = new ContentValues();
values.put(KURS_NAME, Kurs);
rowId = db.insert(TABLE_NAME_KURS, null, values);
db.close();
}catch (SQLiteException e){
Log.e(TAG,"insert()",e);
}finally{
Log.d(TAG, "insert(): rowId=" + rowId);
Log.i(TAG,"db aktion stop, DBHandler-insertKurs");
}
}

public String getPW(){
Log.i(TAG,"db aktion start, DBHandler-getPW");
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getReadableDatabase();
}
Cursor cursor = db.query(TABLE_NAME_PW, new String[] {PASSWORD_ID, PASSWORD_NAME},null,null,null,null,null);
for(int i=0; i<cursor.getCount();i++){
cursor.moveToNext();
}
Log.i(TAG,"db aktion stop, DBHandler-getPW");
db.close();
return cursor.getString(1);
}

public String getKurs(){
Log.i(TAG,"db aktion start, DBHandler-getKurs");
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getReadableDatabase();
}
Cursor cursor = db.query(TABLE_NAME_KURS, new String[] {KURS_ID, KURS_NAME},null,null,null,null, null);
for(int i=0; i<cursor.getCount();i++){
cursor.moveToNext();
}
db.close();
Log.i(TAG,"db aktion stop, DBHandler-getKurs");
return cursor.getString(1);
}

public int getPWCount(){
Log.i(TAG,"db aktion start, DBHandler-getPWCount");
String query = "SELECT * FROM " + TABLE_NAME_PW;
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getReadableDatabase();
}
Cursor cursor = db.rawQuery(query,null);
Log.i(TAG,"db aktion stop, DBHandler-getPWCount");
db.close();
return cursor.getCount();
}

public int getKursCount(){
Log.i(TAG,"db aktion start, DBHandler-getKursCount");
String query = "SELECT * FROM " + TABLE_NAME_KURS;
SQLiteDatabase db = null;
if(db == null || !db.isOpen()) {
db = getReadableDatabase();
}
Cursor cursor = db.rawQuery(query,null);
Log.i(TAG,"db aktion stop, DBHandler-getKursCount");
db.close();
return cursor.getCount();
}
}


I used this Logs to find out where the error apears but it does not help me.

Thank you for help.

Answer

Calling getWritableDatabase() when the database file doesn't exist causes the open helper onCreate() to be invoked.

The db passed to as an argument to onCreate() is the database being opened. You should use it for your initialization instead of calling getWritableDatabase() again as you do in your insertPW() and other methods. The db == null || !db.isOpen() condition doesn't help since you've just initialized the local db variable to null.