DB File in Assets Folder. Will it be Updated?

旧巷老猫 提交于 2019-11-27 07:17:50

You can't replace database in onUpgrade() because in this method the database is already in use. You have to do it before the database is open, like in a constructor of your DatabaseHelper. As you can't use onUpgrade(), you have to manage database versioning by yourself. Using SharedPreferences is a good way for it. You check if your database exists (if it is already copied from assets directory) and check the version if database exists. Now you can delete old database and copy new one from assets. See implementation below.

To mark your updated application is published with new database in assets just incerment DATABASE_VERSION constant.

private static class DatabaseHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "database.db";
    private static final int DATABASE_VERSION = 1;
    private static final String SP_KEY_DB_VER = "db_ver";
    private final Context mContext;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mContext = context;
        initialize();
    }

    /**
     * Initializes database. Creates database if doesn't exist.
     */
    private void initialize() {
        if (databaseExists()) {
            SharedPreferences prefs = PreferenceManager
                    .getDefaultSharedPreferences(mContext);
            int dbVersion = prefs.getInt(SP_KEY_DB_VER, 1);
            if (DATABASE_VERSION != dbVersion) {
                File dbFile = mContext.getDatabasePath(DATABASE_NAME);
                if (!dbFile.delete()) {
                    Log.w(TAG, "Unable to update database");
                }
            }
        }
        if (!databaseExists()) {
            createDatabase();
        }
    }

    /**
     * Returns true if database file exists, false otherwise.
     * @return
     */
    private boolean databaseExists() {
        File dbFile = mContext.getDatabasePath(DATABASE_NAME);
        return dbFile.exists();
    }

    /**
     * Creates database by copying it from assets directory.
     */
    private void createDatabase() {
        String parentPath = mContext.getDatabasePath(DATABASE_NAME).getParent();
        String path = mContext.getDatabasePath(DATABASE_NAME).getPath();

        File file = new File(parentPath);
        if (!file.exists()) {
            if (!file.mkdir()) {
                Log.w(TAG, "Unable to create database directory");
                return;
            }
        }

        InputStream is = null;
        OutputStream os = null;
        try {
            is = mContext.getAssets().open(DATABASE_NAME);
            os = new FileOutputStream(path);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
            os.flush();
            SharedPreferences prefs = PreferenceManager
                    .getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

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

After alot search. I found this- asset folder database is read only. you can't update the database in asset folder. suppose your next app version publish on google play store with new updated database in assert folder. if the name of the both database in assert are same (in previous app and new app) the android system will read old database file only.because file system can't contains two files with same name. What you need to do is just change the name of new database file name in dataOpenhelper.class. like database_1.db .

public class DatabaseOpenHelper extends SQLiteAssetHelper {
    private static final String DATABASE_NAME = "dbbasic_5.db";
    private static final int DATABASE_VERSION = 3;
    private Context contaxtDB;

    // ********* reminder **********
   //  only change database_name = like dbbasic_5.6.7.8  .
    // *******   do not change database_version
    //

    public DatabaseOpenHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        contaxtDB = context;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);

    }


}

this one is working fine, try it

public class DatabaseHelper extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 3;
private static final String SP_KEY_DB_VER = "db_ver";
private static final String DATABASE_NAME = "db.db";
private static String DB_PATH = "/data/data/APP_PACKAGE/databases/";
    static SQLiteDatabase db;
    public Context context;

SessionManager session;

    public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            this.context = context;
            session = SessionManager.getInstance(context);;
            //initialize();
        }

    public void createDataBase() throws IOException {
            if (!checkDataBase()) {
                getWritableDatabase();
                copyDataBase();
            }
        }

    public boolean checkDataBase() {
            /**/
            boolean found = new File(DB_PATH + DATABASE_NAME).exists();
            if(found)
            {
                int dbVersion = Integer.valueOf(session.getData(SP_KEY_DB_VER, "1"));
                if (DATABASE_VERSION != dbVersion) {
                    File dbFile = context.getDatabasePath(DATABASE_NAME);
                    if (!dbFile.delete()) {
                        Log.w("Warning: ", "Unable to update database");
                    }
                    found = false;
                }
            }
            return found;
        }

        public void copyDataBase() throws IOException {
            InputStream myInput = this.context.getAssets().open(DATABASE_NAME);
            OutputStream myOutput = new FileOutputStream(DB_PATH + DATABASE_NAME);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer))>0){
                myOutput.write(buffer, 0, length);
            }
            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();
            session.saveData(SP_KEY_DB_VER, String.valueOf(DATABASE_VERSION));
            //int dbVersion = prefs.in(SP_KEY_DB_VER, 3);
        }

        public void openDataBase() throws SQLException {
            db = SQLiteDatabase.openDatabase(DB_PATH + DATABASE_NAME, null, 0);
        }
    }

MainActivity -> OnCreate

db = new DatabaseHelper(context);
try {
   db.createDataBase();
} catch (IOException ioe) {
   throw new Error("Unable to create database");
}

db.openDataBase();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!