DB файл в папке Assets. Будет ли он обновляться?
Я новичок в Android SQLite все это. Вот что у меня есть:--5-->
- Я
db.sqlite
в своем . - целью БД является только чтение. Пользователь не будет писать ему.
- когда приложение обновляется, то
db.sqlite
будет заменен новый db (я удалю старый файл из проекта и добавлю новый).
что меня беспокоит:
- будет ли старый файл db удален? (это то, что я хочу; замена старого на новый)
- зачем спрашивать? Потому что, когда я отлаживаю свое приложение, каждый раз, когда я обновляю файл db, мне нужно удалить приложение с устройства, чтобы заставить обновление. Должны ли пользователи делать то же самое при обновлении моего приложения из play store? Я боюсь этого.
- будет ли это зависеть от того, как я реализую onCreate (SQLiteDatabase) и onUpgrade(SQLiteDatabase, int, int)?
- если да, то каков правильный способ их реализации для удовлетворения моего требования?
вот как я расширяю SQLiteOpenHelper класса. Я следил за учебником, который я нашел в интернете:
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
3 ответов
вы не можете заменить базу в onUpgrade()
потому что в этом методе база данных уже используется. Вы должны сделать это до открытия базы данных, как в конструкторе вашего DatabaseHelper
. Как вы не можете использовать onUpgrade()
, вы должны управлять версиями базы данных самостоятельно. Используя SharedPreferences
- это хороший способ для этого. Вы проверяете, существует ли ваша база данных (если она уже скопирована из assets
directory) и проверьте версию, если база данных существует. Теперь вы можете удалить старую базу данных и скопировать новый assets
.
Увидеть ниже.
чтобы отметить ваше обновленное приложение публикуется с новой базой данных в assets
просто incerment DATABASE_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.класс. как database_1.децибел.
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();