Noctilux
Noctilux

Reputation: 259

close() was never explicitly called on database

I've done app that is not crashing, but i get these errors in my logcat. They appear when i go back to first activity and choose items from listview. I tried to close cursors and database. What's going wrong?

09-25 09:13:07.609: I/dalvikvm(1013): threadid=3: reacting to signal 3
09-25 09:13:07.759: I/dalvikvm(1013): Wrote stack traces to '/data/anr/traces.txt'
09-25 09:13:08.089: I/dalvikvm(1013): threadid=3: reacting to signal 3
09-25 09:13:08.160: I/dalvikvm(1013): Wrote stack traces to '/data/anr/traces.txt'
09-25 09:13:08.579: I/dalvikvm(1013): threadid=3: reacting to signal 3
09-25 09:13:08.629: I/dalvikvm(1013): Wrote stack traces to '/data/anr/traces.txt'
09-25 09:13:23.170: D/dalvikvm(1013): GC_CONCURRENT freed 516K, 6% free 10848K/11463K, paused 27ms+14ms
09-25 09:13:23.209: E/SQLiteDatabase(1013): close() was never explicitly called on database '/data/data/hr.punctum.LociranjePonudaProizvoda/databases/proizvodidb' 
09-25 09:13:23.209: E/SQLiteDatabase(1013): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1943)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1007)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:770)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at hr.punctum.LociranjePonudaProizvoda.ListaProizvoda.onCreate(ListaProizvoda.java:27)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.Activity.performCreate(Activity.java:4465)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.os.Handler.dispatchMessage(Handler.java:99)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.os.Looper.loop(Looper.java:137)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at android.app.ActivityThread.main(ActivityThread.java:4424)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at java.lang.reflect.Method.invokeNative(Native Method)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at java.lang.reflect.Method.invoke(Method.java:511)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
09-25 09:13:23.209: E/SQLiteDatabase(1013):     at dalvik.system.NativeStart.main(Native Method)
09-25 09:13:23.230: E/System(1013): Uncaught exception thrown by finalizer
09-25 09:13:23.261: E/System(1013): java.lang.IllegalStateException: Don't have database lock!
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase.verifyLockOwner(SQLiteDatabase.java:2090)
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2182)
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase$1.entryRemoved(SQLiteDatabase.java:2178)
09-25 09:13:23.261: E/System(1013):     at android.util.LruCache.trimToSize(LruCache.java:197)
09-25 09:13:23.261: E/System(1013):     at android.util.LruCache.evictAll(LruCache.java:285)
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase.deallocCachedSqlStatements(SQLiteDatabase.java:2143)
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase.closeClosable(SQLiteDatabase.java:1126)
09-25 09:13:23.261: E/System(1013):     at android.database.sqlite.SQLiteDatabase.finalize(SQLiteDatabase.java:1914)
09-25 09:13:23.261: E/System(1013):     at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
09-25 09:13:23.261: E/System(1013):     at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
09-25 09:13:23.261: E/System(1013):     at java.lang.Thread.run(Thread.java:856)
09-25 09:13:23.390: I/dalvikvm(1013): threadid=3: reacting to signal 3
09-25 09:13:23.409: I/dalvikvm(1013): Wrote stack traces to '/data/anr/traces.txt'

DatabaseHelper.java

package hr.punctum.LociranjePonudaProizvoda;


public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "proizvodidb";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        String sql = "CREATE TABLE IF NOT EXISTS proizvodi (" +
                        "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + 
                        "naziv TEXT, " +
                        "tvrtka TEXT, " +
                        "cijena TEXT, " +
                        "kategorija TEXT, " +
                        "telefonTvrtke TEXT, " +
                        "adresaTvrtke TEXT, " +
                        "latitude INTEGER, " +
                        "longitude INTEGER)";

        db.execSQL(sql);

        ContentValues values = new ContentValues();

        values.put("naziv", "Canon 5D mark III");
        values.put("tvrtka", "M-Computers");
        values.put("cijena", "27257kn");
        values.put("kategorija", "fotoaparati");
        values.put("telefonTvrtke", "01/3707800");
        values.put("adresaTvrtke", "Cankareva 3, Zagreb");
        values.put("latitude", 45813029);
        values.put("longitude", 15977894);
        db.insert("proizvodi", "tvrtka", values);

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

        db.close();
    }

ListaProizvoda.java

package hr.punctum.LociranjePonudaProizvoda;


public class ListaProizvoda extends ListActivity {

    protected EditText searchText;
    protected SQLiteDatabase db;
    protected Cursor cursor;
    protected ListAdapter adapter;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        db = (new DatabaseHelper(this)).getWritableDatabase();
        searchText = (EditText) findViewById (R.id.searchText);

    }    

    @SuppressWarnings("deprecation")

    public void search(View view) {

        cursor = db.rawQuery("SELECT _id, naziv, tvrtka, cijena FROM proizvodi WHERE naziv LIKE ?", 
                        new String[]{searchText.getText().toString() + "%"}); 
        adapter = new SimpleCursorAdapter(this,R.layout.proizvodi_list_artikl,cursor,new String[] {"naziv", "tvrtka", "cijena"},new int[] {R.id.naziv, R.id.tvrtka, R.id.cijena});

        startManagingCursor(cursor);
        setListAdapter(adapter);

    }

    public void onListItemClick(ListView parent, View view, int position, long id) {

        Intent intent = new Intent(getApplicationContext(), DetaljiProizvoda.class);
        Cursor cursor = (Cursor) adapter.getItem(position);
        intent.putExtra("PROIZVODI_ID", cursor.getInt(cursor.getColumnIndex("_id")));
        startActivity(intent);

    }      

}   

DetaljiProizvoda.java

package hr.punctum.LociranjePonudaProizvoda;



public class DetaljiProizvoda extends Activity {

    protected TextView naziv;
    protected TextView kategorija;
    protected TextView tvrtka;
    protected TextView telefonTvrtke;
    protected TextView adresaTvrtke;
    protected int proizvodId;
    protected Cursor cursor; 
    protected ListAdapter adapter; 
    protected SQLiteDatabase db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.detalji_proizvoda);

        proizvodId = getIntent().getIntExtra("PROIZVODI_ID", 0);
        db = (new DatabaseHelper(this)).getWritableDatabase();
        cursor = db.rawQuery("SELECT proizv._id, proizv.naziv, proizv.tvrtka, proizv.cijena, proizv.kategorija, proizv.telefonTvrtke, proizv.adresaTvrtke, proizv.latitude, proizv.longitude FROM proizvodi proizv LEFT OUTER JOIN proizvodi mgr ON proizv._id = mgr._id WHERE proizv._id = ?", 
                new String[]{""+proizvodId});

        if (cursor.getCount() == 1)
        {
            cursor.moveToFirst();

            naziv = (TextView) findViewById(R.id.naziv);
            naziv.setText(cursor.getString(cursor.getColumnIndex("naziv"))); 

            kategorija = (TextView) findViewById(R.id.kategorija);
            kategorija.setText(cursor.getString(cursor.getColumnIndex("kategorija")));

            tvrtka = (TextView) findViewById(R.id.tvrtka);
            tvrtka.setText(cursor.getString(cursor.getColumnIndex("tvrtka")));

            telefonTvrtke = (TextView) findViewById(R.id.telefonTvrtke);
            telefonTvrtke.setText(cursor.getString(cursor.getColumnIndex("telefonTvrtke")));

            adresaTvrtke = (TextView) findViewById(R.id.adresaTvrtke);
            adresaTvrtke.setText(cursor.getString(cursor.getColumnIndex("adresaTvrtke")));

        }             
    }

      public void changeActivity(View view) { 

            Intent intent = new Intent(getApplicationContext(), GMapsActivity.class);
            intent.putExtra("PROIZVODI_ID", cursor.getColumnIndex("_id"));
            intent.putExtra("PROIZVODI_LATITUDE", cursor.getInt(cursor.getColumnIndex("latitude")));
            intent.putExtra("PROIZVODI_LONGITUDE", cursor.getInt(cursor.getColumnIndex("longitude")));
            startActivity(intent);      

            cursor.close();
            db.close(); 

        }                  

    }   

Upvotes: 0

Views: 4921

Answers (4)

Hardik Joshi
Hardik Joshi

Reputation: 9507

You should forgot database.close(). Please varify all database.open() in your cases and close database after you successfully operate it..

Upvotes: 1

Ian Warwick
Ian Warwick

Reputation: 4784

You would be better off making your DatabaseHelper into a singleton and keeping it open for the lifetime of the app:-

DatabaseHelper helper = DatabaseHelper.getInstance();

This is a common approach since you never have to close your database explicitly and since Android is a single user environment, its uncessessary to open and close the database frequently.

ContentProvider implementations are persisted as singletons and its common to create an field instance of your SqliteOpenHelper in the providers onCreate(...), you can see an example of it here http://developer.android.com/guide/topics/providers/content-provider-creating.html

So however you decide to manage your databases lifecycle, consider holding a single instance somewhere to save you some trouble, especially when you start using it across threads.

Upvotes: 1

Ashwani
Ashwani

Reputation: 1584

close your database on onStop() or onDestroy() method of your activity.

Upvotes: 3

Ram kiran Pachigolla
Ram kiran Pachigolla

Reputation: 21191

close the database when in onDestroy of your activity

protected void onDestroy() 
{
    super.onDestroy();
    if (db != null) 
    {
        db.close();
    }
}

and also add close method in datahelper class as

public void close() {
        // NOTE: openHelper must now be a member of CallDataHelper;
        // you currently have it as a local in your constructor
        if (openHelper != null) {
            openHelper.close();
        }
    }

Upvotes: 0

Related Questions