Android 资产文件夹中的数据库文件。它会被更新吗?
我对安卓SQLite这件事还不熟悉。这就是我所拥有的:Android 资产文件夹中的数据库文件。它会被更新吗?,android,sqlite,android-assets,sqliteopenhelper,Android,Sqlite,Android Assets,Sqliteopenhelper,我对安卓SQLite这件事还不熟悉。这就是我所拥有的: 我的assets文件夹中有db.sqlite 数据库的目的是只读。用户将不会对其进行写入 当应用程序更新时,db.sqlite将被替换为一个新的db(我将从项目中删除旧文件并添加新文件) 我关心的是: 旧的数据库文件会被删除吗?(这就是我想要的;用新的替换旧的) 为什么要问?因为当我调试应用程序时,每次更新db文件时,我都需要从设备上卸载应用程序以强制更新。当用户从play store更新我的应用程序时,是否也需要这样做?我很担心
- 我的
文件夹中有assets
db.sqlite
- 数据库的目的是只读。用户将不会对其进行写入
- 当应用程序更新时,
将被替换为一个新的db(我将从项目中删除旧文件并添加新文件)db.sqlite
- 旧的数据库文件会被删除吗?(这就是我想要的;用新的替换旧的)
- 为什么要问?因为当我调试应用程序时,每次更新db文件时,我都需要从设备上卸载应用程序以强制更新。当用户从play store更新我的应用程序时,是否也需要这样做?我很担心
- 这是否会受到我如何实施和实施的影响?
- 如果是,如何正确实施这些措施以满足我的要求
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()
,因此必须自己管理数据库版本控制。使用SharedReferences
是一种很好的方法。您可以检查数据库是否存在(如果它已经从资产
目录复制),如果数据库存在,则检查版本。现在,您可以从资产中删除旧数据库并复制新数据库。
见下面的实现
要标记更新后的应用程序与新数据库一起发布在assets
中,只需输入database\u VERSION
常量即可
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) {
}
}
经过多次搜索。我发现这个-资产文件夹数据库是只读的。无法更新资产文件夹中的数据库。假设您的下一个应用程序版本在google play store上发布,新的更新数据库位于assert文件夹中。如果assert中的两个数据库的名称相同(在以前的应用程序和新的应用程序中),android系统将只读取旧的数据库文件。因为文件系统不能包含两个同名的文件。
您需要做的只是在dataOpenhelper.class中更改新数据库文件名的名称。比如数据库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);
}
}
这个不错,试试看
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();
你的代码比我的简单得多。我希望它能起作用。尽管在测试之前我有一个问题:在initialize()
中,如果旧数据库存在并且版本不同,您只需删除它。你不想创建一个新的吗?后面有“if(!databaseExists()){createDatabase();}”。如果数据库被删除,它将创建该数据库。当然可以重写来保存这张支票,我没注意到。我还以为这是一个的部分呢!我想你的实现会成功的。谢谢:)我是android的新手,有人能告诉我如何使用这段代码吗?我也在使用资产文件夹数据库,希望升级database@biegleux我也是android新手,使用asset folder在设备上安装db。如果我为某个专栏升级db,这是如何实现的?但请注意,它会删除旧的db数据