I am trying to update my database in my Android application. When I update the version number, onUpgrade gets called, but the version number doesn't increase, so every time I access the database, onUpgrade gets called. Here is my code:
private final static int DB_VERSION = 8;
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.myContext = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "in onCreate");
try {
copyDataBase();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "in onUpgrade. Old is: " + oldVersion + " New is: " + newVersion);
myContext.deleteDatabase(DB_NAME);
Log.d(TAG, "the version is " + db.getVersion());
db.setVersion(newVersion);
Log.d(TAG, "the version is " + db.getVersion());
onCreate(db);
}
Anyone know why this is happening?
Don't try to manually set the version. (This is all taken care of.)
Don't try to delete the database. You're in the middle of upgrading it, and it shouldn't really surprise you that manually setting the version of a database you've just deleted doesn't work very well.
All you should do in onUpgrade is make the changes needed to the structure of the tables. If you want to do this by deleting the current tables (NOT the database) and then re-creating them, then that's fine.
If you need to preserve the data in your tables, have a look at this question for suggestions on how to do it:
Upgrade SQLite database from one version to another?
I ended up adding another database to the assets folder. I know its not the best solution, but it works. When the app is upgraded this time, it just writes the new database - it has a new name - instead of the old one. I check if the old one exists and if it does, I delete it.
Related
I'm using GreenDao 3.2.2 for my DB,
On my first run on creating Entities via #tags everything worked ok.
Now I am editing the gradle schema to higher versions because I added some props to a table:
greendao {
schemaVersion 4
}
However the OpenHelper onUpgrade method is never called, thus my project is always crashing because some columns are not found.
Application class
//Init DB
UpgradeHelper helper = new UpgradeHelper(this, ENCRYPTED ? "db-encrypted" : "db", null);
Database db = ENCRYPTED ? helper.getEncryptedWritableDb("app-cipher") : helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
OpenHelper class
public class UpgradeHelper extends DaoMaster.OpenHelper {
public UpgradeHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//never gets called
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion);
//do migrations
}
}
am I missing something?
Got it!!! After hours of searching and reading GreenDAO code I understood the problem.
The problem is that getEncryptedWritableDb creates another kind of DB that does not extends SQLiteDatabase. So even when the EncryptedHelper gets the onUpgrade method, my helper class didn't catch it because it fell into another signature.
The solution was simply using the other signature that receives a DAO Database interface:
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by migrating all tables data");
//do migration
}
of course I needed to update all my Migration methods to receive a Database object instead of a StandardDatabase
I have the following problem:
I have a App in the Store, version code 1 now I'm working on a update for this app.
The problem is, that if the user already saved data, I must update the data when the user run the app the first time after updating to version code 2.
my question is, how to implement this in android? Is this possible?
the pseudo code should look like this:
protected void onCreate(Bundle savedInstanceState) {
if (old_version == 1 && version_now == 2)
{
// my update code which will only performed once in a lifetime of the app
}
// ...
}
Read the app version, run your code and store in the SharedPreferences, that you already run your code. Very nice described in these questions:
App version/name: How to get the build/version number of your Android application?
Run only once: Run code only once after an application is installed on Android device
If you are using SQLiteOpenHelper to manage your queries, there is a method called OnUpgrade that will get called when a user has upgraded his app, and the new version of the app has a version code larger than the previous.
An example use:
public static void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
Log.w(TodoTable.class.getName(), "Upgrading database from version "
+ oldVersion + " to " + newVersion
+ ", which will destroy all old data");
database.execSQL("DROP TABLE IF EXISTS " + TABLE_TODO);
onCreate(database);
}
Here you can use oldVersion and newVersion to do incremental updates of your database if you don't want to just drop your tables. You have to make sure that you increment the database version number. The database version number is passed as a constructor argument to SQLiteOpenHelper.
An example of incremental upgrades:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
db.beginTransaction();
boolean success = true;
for (int i = oldVersion ; i < newVersion ; ++i) {
int nextVersion = i + 1;
switch (nextVersion) {
case 2:
success = upgradeToVersion2(db);
break;
// etc. for later versions.
case 3:
success = upgradeToVersion3(db);
break;
}
if (!success) {
break;
}
}
if (success) {
db.setTransactionSuccessful();
}
db.endTransaction();
}
}
I am getting following error while Version Creating My Database.
01-18 12:08:01.157: ERROR/AndroidRuntime(3079): Caused by: java.lang.IllegalArgumentException: Version must be >= 1, was 0
Please Help me regarding this.
Each database you create has a version number. That way you can keep track of them if you upgrade the application (perform necessary database changes for the upgrade on existing data). The version number must start from 1.
If you look at the following code:
private static class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + "
(id INTEGER PRIMARY KEY, name TEXT)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w("Example", "Upgrading database, this will drop tables and recreate.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
onUpgrade will handle all necessary database upgrades. Sometimes you'll opt to just destroy (drop) the current database and create a new one.
it seems you have set previous version as 0, remove your app from phone, reinstall it, make sure new version is greater then previous one.
Each time i run the project same values are also being inserted in the android database. Even i have given the drop if exists query.What i need is that the data in the database gets updated only if there are some changes in the response from the server side instead of cresting database every time but what is happening with me is that same values got insertes again in the tables. How do I solve this? Following is my code:
public void onCreate(SQLiteDatabase database) {
try{
// onUpgrade(database, oldVersion, newVersion)
database.execSQL(DATABASE_CREATE);
}
catch (Exception e) {
System.out.println("in on create db"+e);
}}
public void onUpgrade(SQLiteDatabase database, int oldVersion,
int newVersion) {
database.execSQL("DROP TABLE IF EXISTS" +DATABASE_CREATE);
onCreate(database);
}
private static final String INSERT = "insert into "
+ DATABASE_TABLE + "(KEY_TYPE,KEY_ENCODING,KEY_WIDTH,KEY_HEIGHT,KEY_DATA,KeyIId)"+" values (?,?,?,?,?,?)";
public WineDatabaseAdapter(Context context) {
try{
this.context = context;
openHelper = new WineDatabaseHelper(context);
this.db=openHelper.getWritableDatabase();
this.insertStmt=this.db.compileStatement(INSERT);
}
catch(Exception e)
{
System.out.println(e);
}
}
Can anyone help me how to solve this problem.
Thanks
DROP TABLE seems a pretty extreme way of trying to stop duplicate values. It's a bit hard to follow the code you've posted, but the normal way of stopping duplicates is to add a unique index on the appropriate column(s). Have you tried that yet ? E.g. something like
CREATE UNIQUE INDEX idx_keytype ON tableName (key_type)
What does your schema look like? If you don't want duplicate rows and you know a certain column will be unique use the "UNIQUE" specifier on it. If what you really want is for the row to be replaced you have to use the databaseHelper command "replace" ie. dbHelper.replace(...);
I need to update my android application in the market to next version.next version i need to update the sqlite DB without losing the exsiting data.
In version one i did not create the tables in runtime instead get the database file from the "assets" folder and copies into the system database path of my application.
Refer to this link
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
next version of my app i have modify the exsting table columns and add extra records and there are few new tables as well.I have updated the data base and copied to asset folder.
This will work for users who buy the app for first time,but not for existing users,my question is how can i update the version one users data base without losing existing data
Sam.
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion
+ " to "
+ newVersion + ", which will destroy all old data");
if(oldVersion == 2 && newVersion == 3)
{
db.execSQL("ALTER TABLE xyz ADD bobby int default 0");
}
else
{
db.execSQL("DROP TABLE IF EXISTS xyz");
onCreate(db);
}
}
}
Prepare sql query to upgrade database.
If database exists then perform updating else copy database from assets.
In tutorial that you provided is such code:
if(dbExist){
//do nothing - database already exist
}else{
In place where is //do nothing - database already exist put your upgrading code.
You could try a patch-like solution I describe in this blog post. It will aid with incremental upgrading and will continue to scale as you build more and more versions.
http://www.greenmoonsoftware.com/2012/02/sqlite-schema-migration-in-android/
In your SQLiteHelper class the DATABASE_VERSION variable should be the latest version. Suppose earlier DATABASE_VERSION was 1 and as you are upgrading so it must be 2.
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
Now Upgrade the old database version to new Version. If you don't set the latest version number in the database then onUpgrade(..., ...) will get called repeatedly.
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
logger.info("DBManager - :::: Upgrading database from version " + oldVersion+ " to "+ newVersion + ", which will modify some old table");
String sqlFileName = "update_version_1.sql";
int totalSQLQueries = executeSQLScript(db, sqlFileName);
logger.info("DBManager - :::: Upgrading database from version - " +"Total " + totalSQLQueries +" queries executed succesfully from " +sqlFileName);
if(db.getVersion() == oldVersion) {
db.setVersion(newVersion);
logger.info("DBManager - :::: DB Version upgraded from " +oldVersion +" to " +newVersion);
}
}
Your database modification code must be written within a transaction. See the code bellow as an example of using transaction for database upgrade :-
private int executeSQLScript(SQLiteDatabase db, String sqlFileName)
{
int count = 0;
InputStream inputStream = null;
BufferedReader bufferReader = null;
try
{
db.beginTransaction();
inputStream = localContext.getApplicationContext().getAssets().open(sqlFileName);
bufferReader = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while((inputLine = bufferReader.readLine()) != null)
{
if(inputLine.trim().equalsIgnoreCase("BEGIN;") || inputLine.trim().equalsIgnoreCase("END;"))
{
continue;
}
else
{
db.execSQL(inputLine);
count = count + 1;
}
}
db.setTransactionSuccessful();
}
catch(Exception ex) {
ex.printStackTrace();
}
finally
{
if(bufferReader != null)
{
try {
bufferReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream != null)
{
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
db.endTransaction();
}
return count;
}