Laurent
Laurent

Reputation: 1739

Use SQLite database from assets folder

I'm extending DaoMaster.OpenHelper to manage assets folder database. Since it's not user related data the changes can be huge the only one thing I want to achieve is delete and recreate the database when there is a new version. What I don't understand is that this code works when i'm debugging my app on the emulator or even if i generate the apk and install it on my device manually. But when I deploy my app on the market and I install it on my device from there it looks like the it can't find the database.

Exception java.lang.RuntimeException: Unable to resume activity {com.livos.companionplants/com.livos.companionplants.main.MainActivity}: android.database.sqlite.SQLiteException: no such column: T.definition (code 1): , while compiling: SELECT T."_id",T."plant_id",T."definition" FROM "plant_definition" T ################################################################# Error Code : 1 (SQLITE_ERROR) Caused By : SQL(query) error or missing database. (no such column: T.definition (code 1): , while compiling: SELECT T."_id",T."plant_id",T."definition" FROM "plant_definition" T) #################################################################

@ApplicationScope
public class DatabaseOpenHelper extends DaoMaster.OpenHelper {
    private String TAG = DatabaseOpenHelper.class.getSimpleName();
    private static final String SP_KEY_DB_VER = "db_ver";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SharedPreferences sharedPreferences;

    private SQLiteDatabase sqliteDatabase;

    private static String DB_PATH;

    private static String DB_NAME;

    public DatabaseOpenHelper(Context context, SharedPreferences sharedPreferences, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
        this.context = context;
        this.sharedPreferences = sharedPreferences;
        DB_NAME = name;


        DB_PATH = context.getFilesDir().getAbsolutePath().replace("files", "databases") + File.separator;


        try {
            createDataBase();
        } catch (Exception ioe) {
            throw new Error("Unable to create database");
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    }

    /** Open Database for Use */
    public void openDatabase() {
        String databasePath = DB_PATH + DB_NAME;
        sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
                (SQLiteDatabase.OPEN_READWRITE));
    }

    /** Close Database after use */
    @Override
    public synchronized void close() {
        if ((sqliteDatabase != null) && sqliteDatabase.isOpen()) {
            sqliteDatabase.close();
        }
        super.close();
    }

    /** Get database instance for use */
    public SQLiteDatabase getSqliteDatabase() {
        return sqliteDatabase;
    }

    /** Create new database if not present */
    public void createDataBase() {
        SQLiteDatabase sqliteDatabase;

        if (databaseExists()) {
            int dbVersion = sharedPreferences.getInt(SP_KEY_DB_VER, 1);
            // If different version then delete current database and copy the new one from assets
            if (DATABASE_VERSION != dbVersion) {
                File dbFile = context.getDatabasePath(DB_NAME);
                boolean dbFileDeleted = dbFile.delete();
                if (!dbFileDeleted) {
                    Log.w(TAG, "Unable to update database");
                } else {
                    createDataBase();
                }
            }
            /* Check for Upgrade */
        } else {
            /* Database does not exists create blank database */
            sqliteDatabase = this.getReadableDatabase();
            sqliteDatabase.close();
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
            editor.apply();

            copyDataBase();
        }
    }

    /** Check Database if it exists */
    private boolean databaseExists() {
        SQLiteDatabase sqliteDatabase = null;
        try {
            String databasePath = DB_PATH + DB_NAME;
            sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
                    SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            e.printStackTrace();
        }

        if (sqliteDatabase != null) {
            sqliteDatabase.close();
        }
        return sqliteDatabase != null;
    }

    /**
     * Copy existing database file in system
     */
    public void copyDataBase() {

        int length;
        byte[] buffer = new byte[1024];
        String databasePath = DB_PATH + DB_NAME;

        try {
            InputStream databaseInputFile = this.context.getAssets().open(DB_NAME);
            OutputStream databaseOutputFile = new FileOutputStream(databasePath);

            while ((length = databaseInputFile.read(buffer)) > 0) {
                databaseOutputFile.write(buffer, 0, length);
                databaseOutputFile.flush();
            }
            databaseInputFile.close();
            databaseOutputFile.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static boolean isRoboUnitTest() {
        return "robolectric".equals(Build.FINGERPRINT);
    }

Upvotes: 0

Views: 399

Answers (1)

Laurent
Laurent

Reputation: 1739

Solution using Kuffs proposition

@ApplicationScope
public class DatabaseOpenHelper extends DaoMaster.OpenHelper {
    private String TAG = DatabaseOpenHelper.class.getSimpleName();
    private static final String SP_KEY_DB_VER = "db_ver";
    private static final int DATABASE_VERSION = 2;

    private Context context;
    private SharedPreferences sharedPreferences;

    private SQLiteDatabase sqliteDatabase;

    private static String DB_PATH;

    private static String DB_NAME;

    public DatabaseOpenHelper(Context context, SharedPreferences sharedPreferences, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
        this.context = context;
        this.sharedPreferences = sharedPreferences;
        DB_NAME = name;

        try {
            createDataBase();
        } catch (Exception ioe) {
            throw new Error("Unable to create database");
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    }

    /** Open Database for Use */
    public void openDatabase() {
        String databasePath = context.getDatabasePath(DB_NAME).toString();
        sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
                (SQLiteDatabase.OPEN_READWRITE));
    }

    /** Close Database after use */
    @Override
    public synchronized void close() {
        if ((sqliteDatabase != null) && sqliteDatabase.isOpen()) {
            sqliteDatabase.close();
        }
        super.close();
    }

    /** Get database instance for use */
    public SQLiteDatabase getSqliteDatabase() {
        return sqliteDatabase;
    }

    /** Create new database if not present */
    public void createDataBase() {
        SQLiteDatabase sqliteDatabase;

        if (databaseExists()) {
            int dbVersion = sharedPreferences.getInt(SP_KEY_DB_VER, 1);
            /* If different version then delete current database and copy the new one from assets*/
            if (DATABASE_VERSION != dbVersion) {
                File dbFile = context.getDatabasePath(DB_NAME);
                boolean dbFileDeleted = dbFile.delete();
                if (!dbFileDeleted) {
                    Log.w(TAG, "Unable to update database");
                } else {
                    createDataBase();
                }
            }
        } else {
            /* Database does not exists create blank database */
            sqliteDatabase = this.getReadableDatabase();
            sqliteDatabase.close();
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putInt(SP_KEY_DB_VER, DATABASE_VERSION);
            editor.apply();

            copyDataBase();
        }
    }

    /** Check Database if it exists */
    private boolean databaseExists() {
        SQLiteDatabase sqliteDatabase = null;
        try {
            String databasePath = context.getDatabasePath(DB_NAME).toString();
            sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
                    SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            e.printStackTrace();
        }

        if (sqliteDatabase != null) {
            sqliteDatabase.close();
        }
        return sqliteDatabase != null;
    }

    /**
     * Copy existing database file in system
     */
    public void copyDataBase() {

        int length;
        byte[] buffer = new byte[1024];
        String databasePath = context.getDatabasePath(DB_NAME).toString();

        try {
            InputStream databaseInputFile = this.context.getAssets().open(DB_NAME);
            OutputStream databaseOutputFile = new FileOutputStream(databasePath);

            while ((length = databaseInputFile.read(buffer)) > 0) {
                databaseOutputFile.write(buffer, 0, length);
                databaseOutputFile.flush();
            }
            databaseInputFile.close();
            databaseOutputFile.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Upvotes: 0

Related Questions