Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

close() was never explicitly called in Android and SQlite

Tags:

android

sqlite

I've looked at many posts on stackoverflow about this error, and it looks like the fix is in overriding the onDestroy() method and closing the database. But that doesn't seem to work in my case. I'm actually not getting any error when Eclipse initially runs the app on my phone, but when I close the app and relaunch it on my phone - that's when the close() was never explicitly called on databaseshows up in LogCat. I'm calling an external database that's in my assets folder, not sure if that has anything to do with it or not.

DBAdapter:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

public class DBAdapter extends SQLiteOpenHelper {

public static final String KEY_ROWID = "_id";
public static final String KEY_HDATE = "date";
public static final String KEY_MONTHDAY = "monthday";
public static final String KEY_YEAR = "year";
public static final String KEY_HD = "happened";

// The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.vdm.whtt/databases/";
private static String DB_NAME = "wht.db";
private static final String DB_TABLE = "historydaytable";

private SQLiteDatabase db;

private final Context ourContext;

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

public void createDataBase() throws IOException {

    boolean dbExist = checkDataBase();

    if (dbExist) {
        // do nothing - database already exist
    } else {

        // By calling this method and empty database will be created into
        // the default system path
        // of your application so we are gonna be able to overwrite that
        // database with our database.
        this.getReadableDatabase();

        try {

            copyDataBase();

        } catch (IOException e) {

            throw new Error("Error copying database");

        }
    }

}

private boolean checkDataBase() {
    SQLiteDatabase checkDB = null;

    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null,
                SQLiteDatabase.OPEN_READONLY);
    } catch (SQLiteException e) {
        // database does't exist yet.
    }

    if (checkDB != null) {
        checkDB.close();
    }

    return checkDB != null ? true : false;
}

private void copyDataBase() throws IOException {
    InputStream myInput = ourContext.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();
}

public void open() throws SQLException {
    String myPath = DB_PATH + DB_NAME;
    db = SQLiteDatabase.openDatabase(myPath, null,
            SQLiteDatabase.OPEN_READONLY);
}

@Override
public synchronized void close() {
    if (db != null)
        db.close();
    super.close();
}

@Override
public void onCreate(SQLiteDatabase db) {
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
    onCreate(db);
}

public String[] getTH(long aLong) { 
    String[] columns = new String[] { KEY_YEAR, KEY_MONTHDAY, KEY_HD };
    Cursor cursor = db.query(DB_TABLE, columns, KEY_HDATE + "=" + aLong,
            null, null, null, null);

    if (cursor != null) {
        cursor.moveToFirst();
        String hpToday[] = new String[3];
        hapToday[0] = cursor.getString(0);
        hapToday[1] = cursor.getString(1);
        hapToday[2] = cursor.getString(2);
        cursor.close();
        this.db.close();
        return hpToday;
    }
    return null;
}

public String[] getFirstRandomAnswer(int randomNum1) {
    String[] columns = new String[] { KEY_YEAR, KEY_MONTHDAY, KEY_HD };
    Cursor cursor = db.query(DB_TABLE, columns, null,
            null, null, null, null);
    if (cursor != null) {
        cursor.moveToPosition(randomNum1);
        String r1Str[] = new String[3];
        r1Str[0] = cursor.getString(0);
        r1Str[1] = cursor.getString(1);
        r1Str[2] = cursor.getString(2);
        cursor.close();
        this.db.close();
        return r1Str;
    }
    return null;
}

public String[] getSecondRandomAnswer(int randomNum2) {
    String[] columns = new String[] { KEY_YEAR, KEY_MONTHDAY, KEY_HD };
    Cursor cursor = db.query(DB_TABLE, columns, null,
            null, null, null, null);
    if (cursor != null) {
        cursor.moveToPosition(randomNum2);
        String r2Str[] = new String[3];
        r2Str[0] = cursor.getString(0);
        r2Str[1] = cursor.getString(1);
        r2Str[2] = cursor.getString(2);
        cursor.close();
        this.db.close();
        return r2Str;
    }
    return null;
}
}

MainActivity:

    import java.io.IOException;
import java.util.Locale;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import android.os.Bundle;
import android.text.Html;
import android.widget.TextView;
import android.app.Activity;
import android.database.SQLException;

public class MainActivity extends Activity {
private DBAdapter dba;
TextView hiddenDBdatetv, todayIstv, optionAtv;
String MMdStr;
String[] todayArray;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    hiddenDBdatetv = (TextView) findViewById(R.id.hiddenDBdate_TV);
    todayIstv = (TextView) findViewById(R.id.todayIs_TV);
    optionAtv = (TextView) findViewById(R.id.optionA_TV);

    dba = new DBAdapter(this);

    try {
        dba.createDataBase();
    } catch (IOException ioe) {
        throw new Error("Unable to create database");
    }
    try {
        dba.open();
    } catch (SQLException sqle) {
        throw sqle;
    }

    getMMdDate();
    getTH();
}

private void getMMdDate() {
    Date anotherCurDate = new Date();
    SimpleDateFormat formatter = new SimpleDateFormat("MMd", Locale.US);
    MMdStr = formatter.format(anotherCurDate);
    SimpleDateFormat dateFormat = new SimpleDateFormat("MMd");
    Date myDate = null;
    try {
        myDate = dateFormat.parse(MMdStr);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    SimpleDateFormat timeFormat = new SimpleDateFormat("MMMMMMMMMM d");
    String finalDate = timeFormat.format(myDate);
}

private void getTH() {
    long aLong = Long.parseLong(MMdStr);
    dba.open();
    todayArray = dba.getTH(aLong);
    dba.close();
    optionAtv.setText(todayArray[2]);
}

@Override
protected void onDestroy() {
    dba.close();
    super.onDestroy();
}

}
like image 442
kirktoon1882 Avatar asked Oct 05 '22 20:10

kirktoon1882


1 Answers

You are leaving an open database in createDatabase() (when dbExist == false), and you are opening your database (again) in onCreate(), then again in getTH()...

The trick to avoiding this error is tracking when your database is already open and making sure to close it when you are done using it. Consider checking isOpen() before trying to open your database if you find yourself opening it numerous times.

like image 60
Sam Avatar answered Oct 10 '22 19:10

Sam