E. A. Bagby
E. A. Bagby

Reputation: 930

Cannot open SQLite database from SQLIte Helper Oncreate, when OnCreate is triggered by opening database for the first time

When the mainactivity tries to open the database for the first time after the app is installed, the SQLiteHelper Oncreate method is triggered (as one would expect). I want to then populate the database after the datatables are created in OnCreate, but doing so requires me to open the database again in my content creator class (which is called from OnCreate). The app crashes when it tries to open the database in the content creator class

Basically I'm trying to populate the database once it is created, but apparently not going about it the right way.

From the SQLiteHelper Class:

...

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(SQL_CREATE_TABLE); //sql string to create the table

    dbContents.baseContents(sqcontext);

}

From the content creator class:

public class dbContents {


public static void baseContents(Context context) {

    dbDataSource ds = new dbDataSource(context);
    ds.open();

...

From dbDataSource Class:

public dbDataSource(Context context) {
    dbHelper = new MySQLiteHelper(context);
    DatabaseVersion = dbHelper.DatabaseVersion;  //used when MainActivity onResume to know if it needs to repopulate reminders
}

public void open() throws SQLException {
    database = dbHelper.getWritableDatabase(); //crashes here
}

...

It appears to crash at the line database = dbHelper.getWritableDatabase(); in the open() method. To reiterate, SQLiteHelper OnCreate is called when the database is opened in the main activity. When the database is opened in the mainactivity, it is calling the same open() method posted above where it is crashing when called from the dbcontents class. Is this a threading issue?

Upvotes: 0

Views: 173

Answers (2)

Pankaj Nimgade
Pankaj Nimgade

Reputation: 4549

I have written some snippet of code that would help you populate SQLite Database, code is available on Github that you may check the working example.

Make a class name CreateDatabase.java, it's whole purpose is to create database and add a table to it.

public class CreateDatabase extends SQLiteOpenHelper implements BaseColumns {

    private static final String DATABASE_NAME = "database_name.sqlite";
    private static final int DATABASE_VERSION = 1;
    public static final String TEXT_TYPE = " TEXT";
    public static final String COMMA_SEP = ",";

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("CreateDatabase: ","onCreate: called for the first time");
        db.execSQL(SQL_CREATE_TEST_ONE_TABLE);
    }

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

    public static final String SQL_CREATE_TEST_ONE_TABLE = "CREATE TABLE IF NOT  EXISTS " + "TestOne_Table" +
            " (" + BaseColumns._ID + " INTEGER PRIMARY KEY," +
            "first_column_name" + TEXT_TYPE + COMMA_SEP +
            "second_column_name" + TEXT_TYPE + ")";
}

now that you have this class you need to find a way to use it to make your database as soon as the app starts, as you know onCreate() will be called only once, so below code matters only for the first time the database is made, put it somewhere it can be called as apps opens up.

    CreateDatabase createAllTables = new CreateDatabase(getApplicationContext());
    SQLiteDatabase database = createAllTables.getWritableDatabase();

these lines will help you create the database.

after these lines have been run, you can see the database in the DDMS like this, which you can pull and read it in SQLite Browser or Mozilla Sqlit Manager

enter image description here

after the database has been successfully created you can use following code to populate it with some data, i have put some values as en example to show.

public class SqliteTestOneActivity extends AppCompatActivity {

    private Button save_Button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite_test_one);

        initializeUI();
    }

    private void initializeUI() {
        save_Button = (Button) findViewById(R.id.SqliteTestOneActivity_button);
        save_Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyReader myReader = new MyReader(getApplicationContext());
                myReader.open();
                myReader.insert("Jack", "Sam");
                myReader.close();
            }
        });
    }

    private static class MyReader {
        private static final String Table_Name = "TestOne_Table";
        private final Context mCtx;
        private SQLiteDatabase mDb;
        private InternalHelper mDbHelper;

        public MyReader(Context mCtx) {
            this.mCtx = mCtx;
        }

        public MyReader open() {
            this.mDbHelper = new InternalHelper(this.mCtx);
            this.mDb = mDbHelper.getWritableDatabase();
            return this;
        }

        public void insert(String first, String second) {
            ContentValues values = new ContentValues();
            values.put("first_column_name", first);
            values.put("second_column_name", second);
            mDb.insert(Table_Name, null, values);
        }


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

        private static class InternalHelper extends SQLiteOpenHelper {

            private static final String DATABASE_NAME = "database_name.sqlite";
            private static final int DATABASE_VERSION = 1;

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

            public void onCreate(SQLiteDatabase paramSQLiteDatabase) {
            }

            public void onUpgrade(SQLiteDatabase paramSQLiteDatabase, int paramInt1, int paramInt2) {
            }
        }
    }

}

once you run this activity click on save button and your data will be saved in the database, you can pull the database from the DDMS and check the records

Output enter image description here

Upvotes: 1

laalto
laalto

Reputation: 152827

You should not attempt to call getWritableDatabase() or getReadableDatabase() from SQLiteOpenHelper lifecycle methods such as onCreate() or methods called from there. That will fail with a "called recursively" exception.

Instead, use the SQLiteDatabase that is given as a parameter to onCreate() or other lifecycle methods.

Upvotes: 3

Related Questions