4

I want to create an offline dictionary app, that need sometimes to get update and old database will be replaced by new one. It's what I want to do, and I did something like this with SQLiteAssetHelper Library:

Note: SQLiteAssetHelper will copy database from assets folder into app data folder

public class MyDb extends SQLiteAssetHelper {
  private static final String DATABASE_NAME    = "db.sqlite";
  private static final int    DATABASE_VERSION = 1;
  public MyDb(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }
}

now i want to update database, after puting new db.sqlite file into assets folder, I have manipulate my codes like this:

public class MyDb extends SQLiteAssetHelper {
  private static final String DATABASE_NAME    = "db.sqlite";
  private static final int    DATABASE_VERSION = 2;
  public MyDb(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }
}

but when i compiled and run, it says: Can't upgrade read-only database from version 1 to 2

what is the solution?

by clearing app data, it will works fine...

SORRY FOR MY BAD ENGLISH...

Pejman
  • 2,442
  • 4
  • 34
  • 62

4 Answers4

7

Quoting the documentation:

If you have a read-only database or do not care about user data loss, you can force users onto the latest version of the SQLite database each time the version number is incremented (overwriting the local database with the one in the assets) by calling the setForcedUpgrade() method in your SQLiteAsstHelper subclass constructor.

You can additionally pass an argument that is the version number below which the upgrade will be forced.

Note that this will overwrite an existing local database and all data within it.

You are not calling setForcedUpgrade() from your constructor.

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • @Omid: Start over with a fresh install of your database version 1 app and try again, in case your past attempts corrupted your files. Beyond that, consider posting the entire stack trace in your question. – CommonsWare Nov 02 '14 at 19:46
  • 1
    Not sure why Omid is having issues, this worked fine for me. Overwrote the old database, imported the new one, just like I wanted. – JustSomeQuickGuy Dec 21 '14 at 20:59
6

You should call setForcedUpgrade(); after your Constructor :

public class MyDb extends SQLiteAssetHelper {

  private static final int    DATABASE_VERSION = 2;//+1
  public MyDb(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    setForcedUpgrade(); 
  }
}
S.M_Emamian
  • 17,005
  • 37
  • 135
  • 254
2

It's solved by this:

  @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion != newVersion) {
      context.deleteDatabase(DATABASE_NAME);
      new MyDb(context);
    }else
      super.onUpgrade(db, oldVersion, newVersion);
  }

It's very useful for some database that we don't need old data when getting update.

Pejman
  • 2,442
  • 4
  • 34
  • 62
  • This is the correct answer, as setForcedUpgrade(); is simply not working, i would suggest to put context.deleteDatabase(DATABASE_NAME); in the constructor of the SQLiteAssetHelper class instead of setForcedUpgrade(); – ueen May 24 '19 at 21:01
2

Please note that deleting the old db and creating new one in onUpgrade is not the right solution. Older data has to be migrated. Incase you are not interested in maintaining older data ov version 1, it is alright.

Right way is to use onUpgrade to modify the schema. Most of the time altering the schema required recreating table. In such cases follow below approach

  1. rename existing table (say table_xyz) to be altered to some temp name (say temp_table_xyz)
  2. create the table (table_xyz) with new schema
  3. copy the contents from temp table temp_table_xyz to the new table_xyz
Aun
  • 1,883
  • 1
  • 17
  • 26
  • my data are not important to stay, this is a dictionary, sometimes we change misspells in db. so old db must delete i think – Pejman Nov 03 '14 at 15:06