6

I want my SQLite database instance to be wiped away when the program starts.

What I tried was make a method on my class MyDBAdapter.java like this:

public class MyDbAdapter {
    private static final String TAG = "NotesDbAdapter";
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;
    private static final String DATABASE_NAME = "gpslocdb";
    private static final String PERMISSION_TABLE_CREATE = "CREATE TABLE permission ( fk_email1 varchar, fk_email2 varchar, validated tinyint, hour1 time default '08:00:00', hour2 time default '20:00:00', date1 date, date2 date, weekend tinyint default '0', fk_type varchar, PRIMARY KEY  (fk_email1,fk_email2))";
    private static final String USER_TABLE_CREATE = "CREATE TABLE user ( email varchar, password varchar, fullName varchar, mobilePhone varchar, mobileOperatingSystem varchar, PRIMARY KEY  (email))";

    private static final int DATABASE_VERSION = 2;
    private final Context mCtx;
    private static class DatabaseHelper extends SQLiteOpenHelper {

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

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(PERMISSION_TABLE_CREATE);
            db.execSQL(USER_TABLE_CREATE);
        }

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

    /**
     * Constructor - takes the context to allow the database to be
     * opened/created
     * 
     * @param ctx the Context within which to work
     */
    public MyDbAdapter(Context ctx) {
        this.mCtx = ctx;
    }

    /**
     * Open the database. If it cannot be opened, try to create a new
     * instance of the database. If it cannot be created, throw an exception to
     * signal the failure
     * 
     * @return this (self reference, allowing this to be chained in an
     *         initialization call)
     * @throws SQLException if the database could be neither opened or created
     */
    public MyDbAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        mDbHelper.close();
    }

    public long createUser(String email, String password, String fullName, String mobilePhone, String mobileOperatingSystem) 
    {
        ContentValues initialValues = new ContentValues();
        initialValues.put("email",email);
        initialValues.put("password",password);
        initialValues.put("fullName",fullName);
        initialValues.put("mobilePhone",mobilePhone);
        initialValues.put("mobileOperatingSystem",mobileOperatingSystem);
        return mDb.insert("user", null, initialValues);
    }


    public Cursor fetchAllUsers() {

        return mDb.query("user", new String[] {"email", "password", "fullName", "mobilePhone", "mobileOperatingSystem"}, null, null, null, null, null);
    }

    public Cursor fetchUser(String email) throws SQLException {

        Cursor mCursor = mDb.query(true, "user", new String[] {"email", "password", "fullName", "mobilePhone", "mobileOperatingSystem"}
            , "email" + "=" + email, null, null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;
    }
    public List<Friend> retrieveAllUsers() 
    {
        List <Friend> friends=new ArrayList<Friend>();

        Cursor result=fetchAllUsers();

        if( result.moveToFirst() ){
            do{
                //note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
                friends.add(new Friend(result.getString(result.getColumnIndexOrThrow("email")), "","","",""));
            }while( result.moveToNext() );
        }


        return friends;
    }

}

What is the best way to do this?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
NullPointerException
  • 36,107
  • 79
  • 222
  • 382
  • 1
    Be *very* careful about how you go about this. The activity that serves as the front door for your application may be torn down and re-created multiple times during what the user considers its "lifetime," and deleting the database prematurely will lead to all sorts of confusion. Can I ask what drove your decision to wipe all of the data when the application starts? – Blrfl Dec 21 '10 at 13:10
  • dont worry, i have to clear the database each time i open the app because i have to fill it from scratch with remote database data – NullPointerException Dec 21 '10 at 13:22
  • 2
    How are you identifying when the app "opens" versus when it is simply brought back from the background? As others have stated, simply navigating away from an activity doesn't close an app and this doesn't guarantee that when you launch an app from its icon that you're actually launching a new instance of it. The behavior you require doesn't fit with the lifecycle of an Android app. You need to abstract the fetching and clearing of your data in a way not so strictly tied to the app lifecycle. – Mike Yockey Dec 21 '10 at 17:06

4 Answers4

13

Beside onCreate() and onUpgrade() you can override onOpen(). Drop all tables there and call onCreate().

public class MyApplication extends Application {
    protected static final String           LOG_TAG = "MyApplication";

    private static DatabaseAdapter          mDb;

    private static MyApplication    mInstance;

    /**
     * @return The instance of the database adapter.
     */
    public static DatabaseAdapter getDatabaseAdapter() {
        return mDb;
    }

    /**
     * @return The instance of the application.
     */
    public static Context getInstance() {
        return mInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.w(LOG_TAG, "Application::onCreate");
        mInstance = this;
        mDb = new DatabaseAdapter();
    }

    @Override
    public void onTerminate() {
        // Close the internal db
        getDatabaseAdapter().close(DatabaseAdapter.INTERNAL);

        Log.e(LOG_TAG, "::onTerminate::");
        super.onTerminate();
    }
}

The advantage of subclassing Application is that this will be called always when your application is started or terminated. Independent of the activity that is started. Global operations like open/close a database should be placed here.

Documentation:

Base class for those who need to maintain global application state. You can provide your own implementation by specifying its name in your AndroidManifest.xml's tag, which will cause that class to be instantiated for you when the process for your application/package is created.

WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
  • but this onOpen will be called each time i open the database in all the activitys on my app..... isn't it? and i dont want that, i want to be cleared only when my app starts – NullPointerException Dec 21 '10 at 13:25
  • I wonder if it may be faster to use DELETE FROM and clear out all of the records rather than dropping the tables and then recreating them. Unfortunately I can't test that right now, but it's another option. – McStretch Dec 21 '10 at 13:26
  • 1
    @AndroidUser99: You don't open/close the database in each activity, do you? You should open/close this in the Application class you extended! @McStretch: It might be a bit faster, but a delete from doesn't reset the autoincrement of your primary keys... – WarrenFaith Dec 21 '10 at 13:37
  • sorry but i dont understand what you mean with application class i extend – NullPointerException Dec 21 '10 at 13:54
  • and if i do that on all my acitivites classes, it only be opened one time? when i start my app? i dont understand you... – NullPointerException Dec 21 '10 at 15:33
  • also why you extend application? i have activities on my project, not applications :S – NullPointerException Dec 21 '10 at 15:34
  • @WarrenFaith: Good call I didn't think about that. – McStretch Dec 21 '10 at 15:38
  • then what i should do in my activities to get access to the database using that application class? i can't imagine it, this is new and too munch hard for me – NullPointerException Dec 21 '10 at 16:14
  • there is not another easy way to clear my database without using that application... ? – NullPointerException Dec 21 '10 at 16:18
  • Subclassing Application is a task of 2 minutes (I do this always right after creating a project and barely touch it more than twice a month) --- ok short said: `MyApplication.onCreate()` is called as soon as your app starts. So you can call from everywhere `MyApplication.getInstance()` to get the application object (its a singleton pattern). Or you could call `MyApplication.getDatabaseAdapter()` to get the database connection. As you see in `onCreate()` the database will be opened and in `onTerminate()` it will be closed. – WarrenFaith Dec 21 '10 at 16:20
  • there are other ways, like using flags or shared preferences, but they don't fix the problem, that you open/close your database for every activity, which is, simply said, ineffective and just senseless – WarrenFaith Dec 21 '10 at 16:23
  • in the oncreate of application, i have to pass a contexto to the MyDbAdapter.... code is wrong, can you add the context to the code? i dont know where i have to get/find that context. I mean this: public void onCreate() { super.onCreate(); //Log.w(LOG_TAG, "Application::onCreate"); mInstance = this; mDb = new MyDbAdapter(); } – NullPointerException Dec 21 '10 at 16:39
  • i tryed using mInstance as a context, and removing INTERNAL, and ok, i didn't got errors. The problem is that i put a breakpoint on the oncreate of MyApplication and when i start my app the onCreate is not called.... because debug mode doesn't stop on the breakpoint... i have to do something to get myApplication created? – NullPointerException Dec 21 '10 at 16:45
  • i added my manifest on the first post, please, edit your answer with the code i have to modify/add on the manifest, i dont know how to add that application to the manifest and i can't find a example – NullPointerException Dec 21 '10 at 16:50
  • done, you can simply add `android:name=".MyApplication"` to the `` tag like to the `` tag (I think I should write a short tutorial for this...) – WarrenFaith Dec 21 '10 at 16:56
  • oh it works!!! only one more thing (i hope), where i should put the call to the method open() from the MyDBAdapter class? – NullPointerException Dec 21 '10 at 17:05
  • You dont need to call it by yourself. It will be called like onCreate. Just override the methode like onCreate and it should work. – WarrenFaith Dec 21 '10 at 17:17
  • then i have to put mDb.open(); on the oncreate of the application, is ok? – NullPointerException Dec 21 '10 at 17:24
  • Yeah you should do that. In my adapter class the open() call is inside the constructor, so I just need to create an instance. – WarrenFaith Dec 22 '10 at 09:09
  • wooow im back, i have problems with this solution... if i override onOpen with the droptables, my tables are erased every time a activity call MyApplication.getDatabaseAdapter() and tryes to get some data, for example: MyApplication.getDatabaseAdapter().retrieveAllFriends(); I dont ask for this, i need that the database get's erased every time the app starts, not every time a activity tryes to access the bd – NullPointerException Jan 19 '11 at 17:49
  • So you still close the database every time? Don't do that, the only open/close calls you should have should be in the Application class. Nowhere else... also it would be nice if you could accept my answer... – WarrenFaith Jan 19 '11 at 18:36
  • 11
    Just to be honest: it is a unkindly behavior to remove the "accepted" from the answer just because you have something more you want... the topic is 1 month old... – WarrenFaith Jan 19 '11 at 18:47
  • (I'm with @Warren on this one: not too nice to want more after a month, and above all: to remove the accepted mark to get attention?) – Arjan Jan 19 '11 at 19:52
  • @WarrenFaith As per docs http://developer.android.com/reference/android/app/Application.html#onTerminate%28%29 onTerminate is never called its for emulator only so how the database is supposed to be closed – ingsaurabh Sep 15 '11 at 05:33
  • @ingsaurabh: Yeah I was pointed to that a while ago. I am not sure, but even if this will not be called, if your app will be terminated, it should also close the db connection. – WarrenFaith Sep 15 '11 at 09:02
7

The quick and easy solution that I used was to delete the database file in the OnCreate() method by calling another method named doDBCheck(). The doDBCheck() looks for the file on the emulator/phone's file system and if it exists, remove it.

 private static final String DB_PATH = "data/data/<package name here>/databases/<db name>";

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mainView = (TextView) findViewById(R.id.mainView);
    doDBCheck();

}

private void doDBCheck()
{
    try{
            File file = new File(DB_PATH);
            file.delete();
    }catch(Exception ex)
    {}
}
kwoodson
  • 959
  • 9
  • 11
4

Use the in-memory flag, so there is no need to clear it.

Erdal
  • 1,472
  • 3
  • 16
  • 33
2

There is a method you can use to tell SQLiteDatabase to delete one of the databases programatically like this:

context.deleteDatabase(DATABASE_NAME);

You need the Context and the name of your database to delete.

You could stick this in your constructor that makes the connection to the SQLite Database.

More info: how to drop database in sqlite?

Community
  • 1
  • 1
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335