Android 资产文件夹中的数据库文件。它会被更新吗?

Android 资产文件夹中的数据库文件。它会被更新吗?,android,sqlite,android-assets,sqliteopenhelper,Android,Sqlite,Android Assets,Sqliteopenhelper,我对安卓SQLite这件事还不熟悉。这就是我所拥有的: 我的assets文件夹中有db.sqlite 数据库的目的是只读。用户将不会对其进行写入 当应用程序更新时,db.sqlite将被替换为一个新的db(我将从项目中删除旧文件并添加新文件) 我关心的是: 旧的数据库文件会被删除吗?(这就是我想要的;用新的替换旧的) 为什么要问?因为当我调试应用程序时,每次更新db文件时,我都需要从设备上卸载应用程序以强制更新。当用户从play store更新我的应用程序时,是否也需要这样做?我很担心

我对安卓SQLite这件事还不熟悉。这就是我所拥有的:

  • 我的
    assets
    文件夹中有
    db.sqlite
  • 数据库的目的是只读。用户将不会对其进行写入
  • 当应用程序更新时,
    db.sqlite
    将被替换为一个新的db(我将从项目中删除旧文件并添加新文件)
我关心的是:

  • 旧的数据库文件会被删除吗?(这就是我想要的;用新的替换旧的)
    • 为什么要问?因为当我调试应用程序时,每次更新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数据