如何在android app中的资产文件夹中添加新列到现有数据库?

时间:2014-08-31 10:36:42

标签: android android-sqlite

我编写了一个使用资产文件夹中现有数据库中数据的应用程序。复制和使用数据我在ExternalOpenDbHelper后写了:

public class ExternalDbOpenHelper extends SQLiteOpenHelper {

    public static String DB_PATH;

    private static String TABALE_NAME = "font";
    private static String FONT_ID = "_id";
    private static String FONT_TYPE = "font_type";
    private static String FONT_SIZE = "font_size";

    private static String POEM_TABLE = "poem";
    private static String POEM_ID = "_id";
    private static String READ_POINT = "read_point";
    private static String BOOKMARK = "bookmark";

    public static String DB_NAME;
    public SQLiteDatabase database;
    public final Context context;
    private static final int DATABASE_VERSION = 2;

    public SQLiteDatabase getDb() {
        return database;
    }

    public ExternalDbOpenHelper(Context context, String databaseName) {
        super(context, databaseName, null, DATABASE_VERSION);
        this.context = context;

        String packageName = context.getPackageName();

        DB_PATH = String.format("//data//data//%s//databases//", packageName);
        DB_NAME = databaseName;
        openDataBase();
    }

    public void createDataBase() {
        boolean dbExist = checkDataBase();
        if (!dbExist) {
            this.getReadableDatabase();
            try {
                copyDataBase();
            } catch (IOException e) {
                Log.e(this.getClass().toString(), "Copying error");
                throw new Error("Error copying database!");
            }
        } else {
            Log.i(this.getClass().toString(), "Database already exists");
        }
    }

    private boolean checkDataBase() {
        SQLiteDatabase checkDb = null;
        try {
            String path = DB_PATH + DB_NAME;
            checkDb = SQLiteDatabase.openDatabase(path, null,
                    SQLiteDatabase.OPEN_READONLY);
        } catch (SQLException e) {
            Log.e(this.getClass().toString(), "Error while checking db");
        }
        if (checkDb != null) {
            checkDb.close();
        }
        return checkDb != null;
    }

    private void copyDataBase() throws IOException {

        InputStream externalDbStream = context.getAssets().open(DB_NAME);

        String outFileName = DB_PATH + DB_NAME;

        OutputStream localDbStream = new FileOutputStream(outFileName);

        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = externalDbStream.read(buffer)) > 0) {
            localDbStream.write(buffer, 0, bytesRead);
        }
        localDbStream.close();
        externalDbStream.close();

    }

    public SQLiteDatabase openDataBase() throws SQLException {
        String path = DB_PATH + DB_NAME;
        if (database == null) {
            createDataBase();
            database = SQLiteDatabase.openDatabase(path, null,
                    SQLiteDatabase.OPEN_READWRITE);
        }
        return database;
    }

    @Override
    public synchronized void close() {
        if (database != null) {
            database.close();
        }
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

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

        if (newVersion > oldVersion) {
            db.execSQL("ALTER TABLE cat ADD point BOOLEAN NOT NULL DEFAULT 0;");
            db.execSQL("ALTER TABLE poem ADD read_point BOOLEAN NOT NULL DEFAULT false;");
            db.execSQL("ALTER TABLE poem ADD bookmark INTEGER NOT NULL DEFAULT 0;");
        }
    }

    public int updateFont(int i, String fontName, int p) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues font = new ContentValues();
        font.put(FONT_TYPE, fontName);
        font.put(FONT_SIZE, p);

        String whereClause = FONT_ID + " LIKE ?";
        String[] whereArgs = new String[] { String.valueOf(i) };

        return db.update(TABALE_NAME, font, whereClause, whereArgs);
    }

    public void updateReadPoint(int poemId, int readPointTeransfer) {
        SQLiteDatabase db = this.getWritableDatabase();
        String whereClause;
        String[] whereArgs;

        if (poemId != readPointTeransfer) {
            ContentValues readPoint = new ContentValues();
            readPoint.put(READ_POINT, Boolean.toString(true));

            whereClause = POEM_ID + " LIKE ?";
            whereArgs = new String[] { String.valueOf(poemId) };

            db.update(POEM_TABLE, readPoint, whereClause, whereArgs);

            if (readPointTeransfer != -1) {
                readPoint.put(READ_POINT, Boolean.toString(false));
                whereArgs = new String[] { String.valueOf(readPointTeransfer) };
                db.update(POEM_TABLE, readPoint, whereClause, whereArgs);
            }
        }
    }

    public void updateBookmarkList(int i, String idOfThisPoem) {


        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues bookmarkValue = new ContentValues();
        String whereClause = POEM_ID + " LIKE ?";
        String[] whereArgs = new String[] { idOfThisPoem };
        if (i == 0) {

            bookmarkValue.put(BOOKMARK, Integer.toString(0));
            db.update(POEM_TABLE, bookmarkValue, whereClause, whereArgs);
        } else if (i == 1) {

            bookmarkValue.put(BOOKMARK, Integer.toString(1));
            db.update(POEM_TABLE, bookmarkValue, whereClause, whereArgs);
        }
    }

    public boolean bookmarkStatus(String idOfThisPoem){
        String idOfThisBookmarkedPoem = null;
        Boolean iconFull = null;

        String[] tableColumns = new String[] { POEM_ID, BOOKMARK };
        String whereClause = POEM_ID + " LIKE ?";
        String[] whereArgs = new String[] { idOfThisPoem };
        Cursor poetCursor = database.query(POEM_TABLE, tableColumns,
                whereClause, whereArgs, null, null, POEM_ID);

        poetCursor.moveToFirst();
        if (!poetCursor.isAfterLast()) {
            do {

                idOfThisBookmarkedPoem = poetCursor.getString(1);

            } while (poetCursor.moveToNext());
        }
        poetCursor.close();

        if (Integer.valueOf(idOfThisBookmarkedPoem) == 0) {
            iconFull = false;

        } else if (Integer.valueOf(idOfThisBookmarkedPoem) == 1) {
            iconFull = true;

        }
        return iconFull;
    }

}

在我的代码中,我检查了手机上是否复制了数据,请勿再次复制,但如果路径上没有,则从资产文件夹中复制并在手机上复制的数据库上读/写。每次app运行时我都无法从资产中复制数据库,因为我只是在数据库上写(// data // data //%s // databases //)。现在我需要在它的两个表上添加新列,因为我发布它之前不喜欢最终用户卸载并再次安装应用程序。我尝试搜索大量工作,但找不到解决方案。我想如果我可以删除数据(//数据//数据//%s //数据库//)路径可以正确执行。

2 个答案:

答案 0 :(得分:0)

  

如何在android app中的资产文件夹中将新列添加到现有数据库?

您无法修改资产。

欢迎您通过调用execSQL()对象上的SQLiteDatabase并执行ALTER TABLE语句来修改数据库的本地副本。

我赞同laalto的评论:请use SQLiteAssetHelper。除此之外,它还为您提供了多种向现有数据库添加新列的方法。

答案 1 :(得分:0)

您需要对数据库进行版本控制。换句话说,当您打开数据库时,您似乎无法对当前版本进行任何检查。

例如,您定义当前版本:

public static final int DATABASE_VERSION = 1;

但是,您必须添加首选项(SharedPreferences)或类似内容,以便在安装数据库时保存用户设备上安装的数据库版本。然后在以后的更新中,您可以更改版本并添加代码以将DB更新为新版本。由于您尚未完成此操作,因此您还需要检查未找到版本的情况。

要执行升级,请使用ExternalDbOpenHelper构造函数或类似openDataBase甚至checkDataBase的方法,通过使用当前数据库版本调用onUpgrade进行版本检查,已安装的数据库版本。

像这样:

    onUpgrade(database, settings.getInt(OLD_DB_VERSION, 0), DATABASE_VERSION);

您还必须记住在执行更新或新安装发生后保存新的数据库版本。