This is the fist time I've used SQLiteOpenHelper (or databases on android). When I get a writeable database I was wondering why onCreate isnt being called on each new instance of the class. Am I doing something wrong?
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "MyDatabase.db";
private static final int DATABASE_VERSION = 1;
private String PrSQLcmd = "";
public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL("CREATE TABLE IF NOT EXISTS Contact(Firstname TEXT, LastName TEXT");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
In SQLiteOpenHelper, the meaning of 'onCreate' is different from what it is in an Activity. Here,'onCreate' is called only once, which is the first time you create the database. The next time you run the app, the database is already there, so it won't call 'onCreate'. Your object level initialization should be done in the constructor and not in 'onCreate'
To see 'onCreate' being called, either manually delete the db file, or simply uninstall the app.
Related
Im a bit new to OOP so i want to know if im doing things correctly. For communication with database i have created a class SQLiteHelper witch does all the usual stuff (onCreate, onUpdate) and also opens and closes connection.
Here is the class, at the moment it has just on table but more will be added:
public class SQLiteHelper extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "notebook";
public static final int DATABASE_VERSION = 2;
public static final String TABLE_LIST = "list";
public static final String TABLE_LIST_ID = "_id";
public static final String TABLE_LIST_NAME = "name";
public SQLiteDatabase db;
public SQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("create table " + TABLE_LIST + "(" + TABLE_LIST_ID
+ " integer primary key autoincrement, " + TABLE_LIST_NAME
+ " text not null);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LIST);
onCreate(db);
}
public void open(){
db = getWritableDatabase();
}
public void close(){
db.close();
}
}
And next for each table i will create a new class witch extends previous class andd where i do all the operations relevant to that specific table.
For example ListSQL:
public class ListSQL extends SQLiteHelper {
public ListSQL(Context context) {
super(context);
}
public void delete(int id) {
open();
db.delete(TABLE_LIST, TABLE_LIST_ID + " = " + id, null);
close();
}
}
My question is that in OOP is this the correct way of doing things? Espesially the usage of open/close methods and db and TABLE variables in ListSQL seem kind of strange to me?
I always open the db connection in onResume() and close it in onPause(). In this way database is always open for each activity.
The reason I am not doing it in onCreate() and onDestroy() is once user go to other activity onCreate() of new activity will be called first then onDestroy() of old activity so if I perform any operation(ex:- search in my list or changing the status of user etc) on places other then onCreate() it will crash the app with reason database already closed.
Note: You have to open and close the connection, even if you are using SQLiteHelper class.
According to the Android manual, you do not need to close a database when using an SQLiteOpenHelper. The system will do it for you.
As #Dan mentioned above, you do no need to open and close the database every time you do a read/write operation if you are using SQLiteOpenHelper. The best way to use the database is :
1.
Declare and initialize an instance of SQLiteHelper in your Application base class like this :
public class App extends Application {
public static SQLiteHelper db;
#Override
public void onCreate() {
super.onCreate();
db = new SQLiteHelper(getApplicationContext());
db.open();
}
}
2.
In you activity, or any other place you want to use the DB, initialize the SQLiteHelper object like this :
SQLiteHelper db = App.db;
And then you can use the database anyway you want without having to worry about opening and closing it (:
I've seen a lot of ties between the onCreate and onOpen methods and SQLite database management in Android.
I am an iOS developer and I'm trying to "translate" (so to speak) my cocoa library so it could be used on Android. I need to create an SQLite database at runtime. I don't have an activity - since this is a library I'm creating. It seems I can't create a DB without an activity, is this correct ?
To create sqlite db, you don't basically need an activity in the library.it needs a context!!,
You can have a method in library/class which basically take a context in input/parameter and create database.
This context can be passed from application activity or service or receiver.
I don't see why you should not be able to open a database without an activity. You need to extend SQLiteOpenHelper.
public class MyDatabase {
private final DatabaseHelper databaseHelper;
private SQLiteDatabase db;
private static final String DATABASE_NAME = "com.my.db";
private static final int DATABASE_VERSION = 1;
public MyDatabase(Context context) {
databaseHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
//use db.execSQL to create the database
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// use db.execSQL to update (modify) the database
}
}
public SQLiteDatabase open() throws SQLException {
db = databaseHelper.getWritableDatabase();
return db;
}
}
Using ORMLite v 4.40, I try to get my app running, but it seems to ignore the onCreate function
My DatabaseHelper looks like this (snippet style)
public class ORMLiteHelper extends OrmLiteSqliteOpenHelper {
private Context databaseContext;
private static String DATABASE_NAME = "InVinoVeritas";
private static int DATABASE_VERSION = 1;
public ORMLiteHelper(Context context) {
super (context, DATABASE_NAME, null, DATABASE_VERSION);
Log.v("ORMLiteHelper", "Cosntructor");
...
#Override
public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) {
Log.v("DatabaseHelper", "onCreate");
...
#Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
Log.v("DatabaseHelper", "onUpgrade");
...
My MainActivity calls the DatabaseHelper as described:
public class MainActivity extends OrmLiteBaseActivity<ORMLiteHelper> {
I have tried re-installing the application, upgrading the database version, nothing works.
I do see the constructor call (including typo :-), the onCreate and onUpgrade however are not called.
Any help appreciated
Barry
Create instance of ORMLiteHelper and call getWritableDatabase(). When database is not created then onCreate will be invoked.
I have an existing database based on SQLiteOpenHelper that has several versions and code to upgrade it and that works fine. But in case a user installs an older version of the app (that expects a lower database version) it will currently crash - the ContentProvider using it can't access the database. I'd like to prevent it from crashing but I don't want to actually downgrade the database - adding the code to do that would be pain. Dropping all tables would certainly work but starting with a fresh file is imo cleaner and less error prone.
That's about what the database helper looks like - nothing special
public class MyDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 3;
private static final String DATABASE_NAME = "my.db";
public MyDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
onUpgrade(db, 0, DATABASE_VERSION);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion < 1) db.execSQL("CREATE TABLE A...");
if (newVersion < 2) db.execSQL("CREATE TABLE B...");
if (newVersion < 3) db.execSQL("CREATE TABLE C...");
}
#Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// I'd like to delete the database here
// the only problem is that I can't from here
// since this is called in the middle of getWritableDatabase()
// and SQLiteDatabase has no .recreate() method.
}
}
The possible ways I've come up to do that are:
Do it from the outside: catch exceptions in the ContentProvider, delete the file and request to open the database again. - I don't like that since it's not the responsibility of the provider.
Replacing SQLiteOpenHelper with my own copy of that class that deletes the file instead of calling onDowngrade - Problem is that it's using package private parts of SQLiteDatabase (e.g. .lock()) which I can't replace without duplicating SQLiteDatabase too (that would probably result in duplicating the whole sqlite stack).
Is there any good approach to do that or do I have to go the DROP TABLES way e.g. like described here?
I've figured out a way that works nicely by extending SQLiteOpenHelper and all I need to do in MyDbHelper is to extend this class.
public abstract class DeletingSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = DeletingSQLiteOpenHelper.class.getSimpleName();
private final File mDatabaseFile;
public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler) {
super(context, name, factory, version, errorHandler);
mDatabaseFile = context.getDatabasePath(name);
}
public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
mDatabaseFile = context.getDatabasePath(name);
}
#Override
public synchronized SQLiteDatabase getWritableDatabase() {
try {
return super.getWritableDatabase();
} catch (SQLiteDowngradeFailedException e) {
// that's our notification
}
// try to delete the file
mDatabaseFile.delete()
// now return a freshly created database
return super.getWritableDatabase();
}
#Override
public final void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// throwing a custom Exception to catch it in getWritableDatabase
throw new SQLiteDowngradeFailedException();
}
// that's the exception
static class SQLiteDowngradeFailedException extends SQLiteException {
public SQLiteDowngradeFailedException() {}
public SQLiteDowngradeFailedException(String error) {
super(error);
}
}
}
I would to erase and recreate the database for my app each time I send a new version of my app from Eclipse to my phone (I am developing and changing my database very often). What is the easiest way to do this?
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, dbName, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE USERS (username TEXT, password TEXT);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS USERS");
onCreate(db);
}
i use this one in my code :) change super(context, dbName, null, <database version number>); and it will execute onUpgrade method.
If this is something you do not wish to do once it is live, you can just clear data from your application manager each time. Also, you can make the database version number different and have the onUpgrade destroy and recreate the DB
private static final String DATABASE_NAME = "MyDbName";
private static final int DATABASE_VERSION = 6;
private static class DbOpenHelper extends SQLiteOpenHelper{
public DbOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
onUpgrade(this.getWritableDatabase(), 0, 0);
//
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TableHelper1.CREATE_TABLE_QUERY);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+ TableHelper1.TABLE_NAME);
onCreate(db);
}
}
In Eclipse, go into Debug Configurations, then Android Application on the left hand side. Select the debug configuration that you are using and then select the Target tab.
At the bottom, you'll see a checkbox labeled "Wipe User Data".
If you check that, everytime you launch the simulator, the data associated with your application (including the SQLite database) will be erased.
Your application will then call onCreate() for your SQLiteOpenHelper, and your database will be recreated.