Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using pre-populated database in Room by copy database file from assert

I want to use pre-populated database in Android Room. I found a way to make it through using the callback, and filled up the database files. But something is wrong, I'm sure that the database is copied normally, but it remains empty in the device monitor and android emulator. Can you please help me

public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
private static final String DB_NAME = "base.db";
static Context ctx;

public abstract Dao dao();

public static AppDatabase getDatabase(Context context) {
    if (INSTANCE == null) {
        ctx = context;
        synchronized (AppDatabase.class) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context,
                        AppDatabase.class, DB_NAME)
                        .allowMainThreadQueries()
                        .addCallback(rdc)
                        .build();
            }
        }
    }
    return INSTANCE;
}

private static RoomDatabase.Callback rdc = new RoomDatabase.Callback() {
    public void onCreate(SupportSQLiteDatabase db) {

        new PopulateDbAsync(INSTANCE, ctx).execute();
        Log.d("db create ", "table created when db created first time in  onCreate");
    }

    public void onOpen(@NonNull SupportSQLiteDatabase db) {
        ContentValues contentValues = new ContentValues();
    }
};

private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {

    private Dao dao;
    AssetManager assetManager = ctx.getAssets();

    PopulateDbAsync(AppDatabase db, Context context) {
        Dao = db.Dao();
        ctx = context;
    }

    @Override
    protected Void doInBackground(final Void... params) {
        String DB_PATH = "/data/data/mypackage/databases/";
        String DB_NAME = "base.db";
        try {
            Log.d("AppDatabase","Trying copy database file");
            OutputStream myOutput = new FileOutputStream(DB_PATH + DB_NAME);
            byte[] buffer = new byte[1024];
            int length;
            InputStream myInput = ctx.getAssets().open("base.db");
            while ((length = myInput.read(buffer)) > 0) {
                myOutput.write(buffer, 0, length);
            }
            myInput.close();
            myOutput.flush();
            myOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
}
like image 681
AlexS Avatar asked Oct 29 '25 03:10

AlexS


2 Answers

I solved after spending 6 hours on researching and R & D .

Context is that : - I want to put already existing finaldb.db(which is present inside assests folder) into room database .

Step 1 : copy this framework files from here link

Step 2 : You need to migrate , chill i have code :)

@Database(entities = {Status.class}, version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
    public abstract DataDao StatusDao();

    private static AppDatabase INSTANCE;


    public static AppDatabase getDatabase(Context context) {
        if (INSTANCE == null) {
            INSTANCE = createDatabase(context);
        }
        return (INSTANCE);
    }

    private static final Migration MIGRATION_2_3 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            Log.d("kkkk","bc");

            String SQL_CREATE_TABLE = "CREATE TABLE IF NOT EXISTS 'Status' " +
                    "( 'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
                    "  'category' TEXT NOT NULL," +
                    "  'sub_category' TEXT NOT NULL," +
                    "  'content' TEXT NOT NULL," +
                    "  'favourite' INTEGER DEFAULT(0))";

            database.execSQL(SQL_CREATE_TABLE);

        }
    };

    private static AppDatabase createDatabase(Context context) {
        RoomDatabase.Builder<AppDatabase> builder =
                Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class,
                        context.getString(R.string.dbase_name));


        return (builder.openHelperFactory(new AssetSQLiteOpenHelperFactory())
                .allowMainThreadQueries()
                .addMigrations(MIGRATION_2_3)
                .build());
    }

}

In MIGRATION_2_3 you have to create table exactly same as current database(which is present in assests folder)

want to learn about migration

Step 3 : Now table is created successfully in room database !

In case of crash see your logcat , in which its written in understandable form .

like image 181
iamkdblue Avatar answered Nov 01 '25 12:11

iamkdblue


You cannot, properly, do the copy of the database in the onCreate method.

When the onCreate method is called the database has been created (the created database is passed to the method). You have to do the copy before the onCreate method and before the database is opened.

You could override's the RoomDatabase init method and do the copy from that method or do the copy before invoking the databaseBuilder.

like image 43
MikeT Avatar answered Nov 01 '25 13:11

MikeT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!