资产文件夹中的 DB 文件.会更新吗? [英] DB File in Assets Folder. Will it be Updated?
问题描述
我是 Android SQLite 的新手.这就是我所拥有的:
I'm new to the Android SQLite whole thing. This is what I have:
- 我的
assets
文件夹中有db.sqlite
. - 数据库的目的是只读.用户不会写信给它.
- 当应用更新时,
db.sqlite
将被替换为一个新的 db(我将从项目中删除旧文件并添加新文件).
- I have
db.sqlite
in myassets
folder. - The intent of the db is to READ ONLY. The user will not write to it.
- When the app gets updated, the
db.sqlite
will be replaced be a new db (I'll delete the old file from the project and add the new one).
我担心的是:
- 旧的 db 文件会被删除吗?(这就是我想要的;用新的替换旧的)
- 为什么要问?因为当我调试我的应用程序时,每次更新db文件时,我都需要从设备上卸载应用程序才能强制更新.当用户从 Play 商店更新我的应用程序时,他们是否需要做同样的事情?我很害怕.
- 如果是,实施它们以满足我的要求的正确方法是什么?
这就是我扩展 SQLiteOpenHelper 类的方式.我遵循了在互联网上找到的教程:
This is how I extends the SQLiteOpenHelper class. I followed a tutorial I found in the internet:
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class DataBaseHelper extends SQLiteOpenHelper{ //The Android's default system path of your application database. private static String DB_PATH = "/data/data/com.mydomain.myapp/databases/"; private static String DB_NAME = "db.sqlite"; private SQLiteDatabase myDataBase; private final Context myContext; /* * Constructor * Takes and keeps a reference of the passed context in order to access to the application assets and resources. * @param context **/ public DataBaseHelper(Context context) { super(context, DB_NAME, null, 1); this.myContext = context; } /** * Creates a empty database on the system and rewrites it with your own database. * */ public void createDataBase() throws IOException{ boolean dbExist = checkDataBase(); if(dbExist){ //do nothing - database already exist Log.i("myapp", "database already exist"); }else{ Log.i("myapp", "database NOT exist"); //By calling this method and empty database will be created into the default system path //of your application so we are gonna be able to overwrite that database with our database. this.getReadableDatabase(); try { copyDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } } } /** * Check if the database already exist to avoid re-copying the file each time you open the application. * @return true if it exists, false if it doesn't */ private boolean checkDataBase(){ SQLiteDatabase checkDB = null; try{ String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); }catch(SQLiteException e){ //database does't exist yet. } if(checkDB != null){ checkDB.close(); } return checkDB != null ? true : false; } /** * Copies your database from your local assets-folder to the just created empty database in the * system folder, from where it can be accessed and handled. * This is done by transfering bytestream. * */ private void copyDataBase() throws IOException{ //Open your local db as the input stream InputStream myInput = myContext.getAssets().open(DB_NAME); // Path to the just created empty db String outFileName = DB_PATH + DB_NAME; //Open the empty db as the output stream OutputStream myOutput = new FileOutputStream(outFileName); //transfer bytes from the inputfile to the outputfile 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(); } public void openDataBase() throws SQLException{ //Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); } @Override public synchronized void close() { if(myDataBase != null) myDataBase.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } // My public helper methods to access and get content from the database go here
推荐答案
您不能在
onUpgrade()
中替换数据库,因为在此方法中数据库已在使用中.您必须在打开数据库之前执行此操作,就像在DatabaseHelper
的构造函数中一样.由于您不能使用onUpgrade()
,您必须自己管理数据库版本控制.使用SharedPreferences
是一个很好的方法.您检查您的数据库是否存在(如果它已经从assets
目录复制)并检查版本是否存在数据库.现在您可以删除旧数据库并从assets
复制新数据库.请参阅下面的实现.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 yourDatabaseHelper
. As you can't useonUpgrade()
, you have to manage database versioning by yourself. UsingSharedPreferences
is a good way for it. You check if your database exists (if it is already copied fromassets
directory) and check the version if database exists. Now you can delete old database and copy new one fromassets
. See implementation below.为了标记您更新的应用程序是在
assets
中使用新数据库发布的,只需增加DATABASE_VERSION
常量.To mark your updated application is published with new database in
assets
just incermentDATABASE_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) { } }
这篇关于资产文件夹中的 DB 文件.会更新吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!