76

我想将 Room 与预先填充的数据库一起使用,但我不明白如何告诉 Room 在哪里可以找到我的数据库。

我现在把它放进去src/main/assets/databases,当我为 Room 数据库创建实例时,我是这样创建的:

Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase.class,
    "justintrain.db"
)
.allowMainThreadQueries()
.build();

这样,我认为它每次都在创建一个新数据库,或者无论如何,它没有使用预先填充的数据库。

我怎样才能找到我的数据库?

4

8 回答 8

41

这就是我解决它的方法,以及如何使用预先填充的数据库(最高到 Room v. alpha5)发布应用程序

  • 将您的 SQLite DBdatabase_name.db放入assets/databases文件夹

  • 从这个 repo中获取文件并将它们放在一个名为 ie 的包中sqlAsset

  • 在您的AppDatabase班级中,相应地修改您房间的数据库创建代码:

    Room.databaseBuilder(context.getApplicationContext(), 
                         AppDatabase.class, 
                         "database_name.db")
    .openHelperFactory(new AssetSQLiteOpenHelperFactory())
    .allowMainThreadQueries()
    .build();
    

请注意,您必须使用"database_name.db"而不是getDatabasePath()或其他方法:它只需要文件名。

于 2017-08-09T21:09:11.723 回答
31

更新(2019 年 11 月 7 日)

从 2.2.0 版开始,Room 现在支持使用开箱即用的预打包数据库

https://developer.android.com/jetpack/androidx/releases/room#2.2.0

2.2.0 版本之前的解决方案:没有任何其他外部库的简单解决方案。

Room 依赖于现有的 Android 框架代码来创建或打开数据库。如果您查看FrameworkSQLiteOpenHelper(Room 的版本SQLiteOpenHelper)的源代码,它会在需要时在内部调用SQLiteOpenHelper.getReadableDatabase()和其他方法。

mContext.getDatabasePath("my-database.sqlite")因此,最简单的解决方案是在使用 Room 创建数据库之前将数据库文件从 assets 目录复制到。

在您的情况下,代码看起来像这样 -

private final String DB_NAME = "my-database.sqlite";

private MyDatabase buildDatabase(Context context) {
    final File dbFile = context.getDatabasePath(DB_NAME);

    if(!dbFile.exists()) {
        copyDatabaseFile(dbFile.getAbsolutePath());
    }

    return Room.databaseBuilder(context.getApplicationContext(),
        MyDatabase.class, DB_NAME)
        .build();
}

private void copyDatabaseFile(String destinationPath) {
    // code to copy the file from assets/database directory to destinationPath
}

此链接具有复制数据库所需的代码 -带有代码的链接

于 2018-05-17T05:25:51.820 回答
16

我遇到了同样的问题,所以我创建了一个完全可以做到这一点的库。接受的答案有效,但我认为使用库更容易。

AppDatabase db = RoomAsset
    .databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db")
    .build(); 

将其添加到存储库末尾的根 build.gradle 中:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

添加依赖

dependencies {
    // ... other dependencies
    implementation 'com.github.humazed:RoomAsset:v1.0'
}

你可以在这里找到图书馆:https ://github.com/humazed/RoomAsset

于 2017-11-19T01:34:25.233 回答
15

工作 2019 解决方案,没有黑客或依赖(Kotlin)

  1. 将您的.db文件放入assets/databases(或其中的任何文件夹,只要它位于 下assets)。

  2. 使用 Room 2.2 的现有createFromAsset()函数,传入数据库的路径。例如,如果您的数据库文件已命名my_data.db并且位于databases该文件夹的目录下assets,那么您将执行createFromAsset("databases/my_data.db").

假设您的数据库名称(例如my_data)存储在名为 的常量变量中DATABASE_NAME,您可以使用以下示例代码:

Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    DATABASE_NAME
                )
                    .createFromAsset("databases/$DATABASE_NAME.db")
                    .build()

重要提示:确保您的数据类/实体的架构与.db文件的架构精确匹配。例如,如果一个列未NOT NULL.db文件中显式标记为,则这意味着该列中可以包含空值。在 Kotlin 中,您必须将其与val colName: dataType? = null数据类中的内容相匹配。如果你只是这样做val colName: dataType,Kotlin 会将它编译成一个NOT NULL列,当你尝试运行你的应用程序时会抛出一个异常。

注意:如果您想从下载到 Android 设备本身的数据库文件创建 Room 数据库,您也可以使用该createFromFile()功能。查看有关如何执行此操作的官方文档。

于 2019-09-13T11:20:04.350 回答
9

Room 现在支持预填充数据库。只需使用SQLite Browser之类的程序或您选择的任何其他程序来准备您的数据库。然后把它放在Assets Folder一个名为databasethen call 的子文件夹中:

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromAsset("database/myapp.db")
.build()

如果您没有将数据库作为资产提供但您下载了它或者它在文件系统中,那么方法是:

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromFile(File("mypath"))
.build()

有关此功能的更多描述或数据库迁移,您可以查看文档培训

于 2020-01-01T18:23:14.317 回答
1

与房间类似的解决方案,不使用外部库:1.将您的数据库复制到资产文件夹中 2.从资产文件夹中复制您的数据库

public class MainActivity extends AppCompatActivity {

public static AppDatabase db;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    copyDatabase(getApplicationContext(), "yourdatabase.db");

    db = Room.databaseBuilder(getApplicationContext(), .class, "yourdatabase.db").allowMainThreadQueries().build();
}

private void copyDatabase(Context context, String databaseName) {
    final File dbPath = context.getDatabasePath(databaseName);

    // If the database already exists, return
    if (dbPath.exists()) {
        Log.d("Activity", "db Path Exists");
        return;
    }

    // Make sure we have a path to the file
    dbPath.getParentFile().mkdirs();

    // Try to copy database file
    try {
        final InputStream inputStream = context.getAssets().open(databaseName);
        final OutputStream output = new FileOutputStream(dbPath);

        byte[] buffer = new byte[8192];
        int length;

        while ((length = inputStream.read(buffer, 0, 8192)) > 0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        inputStream.close();
    }
    catch (IOException e) {
        Log.d("Activity", "Failed to open file", e);
        e.printStackTrace();
    }
}

}

于 2019-02-21T22:07:45.127 回答
1

从 Room 2.2 开始,您可以使用以下命令预填充数据库:

Room.databaseBuilder(appContext, TestDatabase.class, “Sample.db”)
    .createFromAsset(“database/myapp.db”)
    .build()
于 2019-11-22T14:54:13.960 回答
0

您只需复制assets/databasesapp/databases
然后添加 它会保留您的addMigrations()数据databaseBuilder

于 2017-08-20T09:29:53.643 回答