4

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;
    }
}
}
AlexS
  • 918
  • 1
  • 12
  • 28

4 Answers4

5

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 .

Oxobo
  • 513
  • 1
  • 5
  • 13
iamkdblue
  • 3,448
  • 2
  • 25
  • 43
2

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.

MikeT
  • 51,415
  • 16
  • 49
  • 68
1

I'm solved it. Database class:

@Database(entities = {Entity1.class, Entity2.class, Entity3.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;

public abstract Entity1Dao 1Dao();
public abstract Entity2Dao 2Dao();
public abstract Entity3Dao 3Dao();

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

  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()
            .build());
  }
}

Also you should get SQL Helpers, link

AlexS
  • 918
  • 1
  • 12
  • 28
0

My issue is a little bit different than the OP.

I was copying the database file from internal storage which I downloaded from the internet, not from assets. And java.lang.RuntimeException: Unable to copy database file is raised because I didn't grant READ_EXTERNAL_STORAGE before this, or in general granting WRITE_EXTERNAL_STORAGE as READ_EXTERNAL_STORAGE is included in WRITE_EXTERNAL_STORAGE and already need the write permission for downloading the file.

Zain
  • 37,492
  • 7
  • 60
  • 84