【问题标题】:How to change the default database file location of Room DataBase?如何更改 Room Database 的默认数据库文件位置?
【发布时间】:2018-07-31 21:59:50
【问题描述】:

我在我的应用程序中使用 RoomDB。能够执行crud操作。 其实我想看db文件。

getDatabasePath("user.db").getAbsolutePath();

上面的代码给了我 db 文件保存的目录 目录是这样的

 /data/data/com.example.manvish.roomdb/databases/user.db

但即使在命令提示符下使用 sudo,我仍然无法访问数据目录。 现在我想将 DB 文件位置更改为内部存储器或 SD 卡中的其他一些文件夹。我该怎么做?

【问题讨论】:

  • 没有理由复制到外部文件夹。 Room 只能从内部应用程序内存中读取。如果您的应用程序需要外部 SQLite 文件,则需要使用 SQLiteOpenHelper、AFAIK。如果你只想看内容,我已经给你链接了这个stackoverflow.com/questions/44429372/…
  • @cricket_007 我想修改db直接使用sqlite浏览器将一些虚拟数据添加到表中..不仅仅是查看
  • 好的,我没有发现任何外部 SQLite 文件无法读取或导入 Room 的引用,所以如果您找到方法,请随时告诉我。
  • 你做到了吗
  • @M.Yogeshwaran No ..no

标签: android android-sqlite android-room


【解决方案1】:

Java 解决方案:

  1. 在清单中授予权限
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  1. 创建db(这里的SofDatabase是一个单例类)
private static final String DB_NAME = "stack_overflow_db";
private static final String DB_PATH = String.format("%s/%s",
 Environment.getExternalStorageDirectory().getAbsolutePath(), DB_NAME);
    public static synchronized SofDatabase getInstance(Context aContext) {
        if (sInstance == null) {
            sInstance = Room.databaseBuilder(aContext, SofDatabase.class, DB_PATH)
                    .fallbackToDestructiveMigration()
                    .addCallback(roomCallback).build(); //adding callback from Room
        }
        return sInstance;
    }

回调

     /**
     * Get Notified once db is created
     */
    private static final RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            Log.i("SOF", db.getPath()); //which prints out -->  I/SOF: /storage/emulated/0/stack_overflow_db
            // add some jobs once db is created
        }
    };

【讨论】:

    【解决方案2】:

    要更改 db 位置,只需将构建 Room 数据库时的路径(例如文件夹中的 db 示例)放在内部存储中:

    fun getDatabase(context: Context, scope: CoroutineScope):   TestDatabase {
                return INSTANCE ?: synchronized(this) {
                    val instance =
                        Room.databaseBuilder(
                            context.applicationContext,
                            TestDatabase::class.java,
                            Environment.getExternalStorageDirectory().absolutePath + "/yourFolder/yourdb"
                        ).build()
                    INSTANCE = instance
                    return instance
                }
            }

    这是一个 Kotlin 示例,如果您在 Java 中需要它,请告诉我。 问候。

    【讨论】:

    • 它对我不起作用 --> java.lang.IllegalArgumentException: File storage/sdcard0/Download/database/example contains a path separator.使用 Room 版本 1.1.1。在华为 P8 Lite 上。
    【解决方案3】:

    不确定这是否是您要查找的内容,但就我而言,就像 @M.Yogeshwaran 一样,我需要能够设置数据库的初始状态并从那里开始工作,所以我最终这样做了:

    /**
     * @param context
     */
    public DatabaseService(Context context) {
    
            File dst = context.getDatabasePath(DB_NAME);
            dst.delete();
            File src = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath()+"/database.db");
            try {
                copy(src,dst);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            // Init the database singleton
            db = Room.databaseBuilder(context, CrediforceDatabase.class, Constants.DB_NAME).build();
    }
    
    public static void copy(File src, File dst) throws IOException {
        try (InputStream in = new FileInputStream(src)) {
            try (OutputStream out = new FileOutputStream(dst)) {
                // Transfer bytes from in to out
                byte[] buf = new byte[1024];
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
            }
        }
    }
    

    为了更清楚一点:

    1. DB_NAME = "database.db"
    2. 出于测试目的,我的下载文件夹中有我想要“导入”的“database.db”,稍后我将转换此代码,以便设备从服务器中提取初始数据库。
    3. dst.delete();只是在我测试时删除现有的数据库文件(不确定是否需要)
    4. 这基本上翻译为:启动应用程序 > 替换数据库文件 > 构建数据库。
    5. 必须小心 room_master_table 中的 identity_hash,如果这与预期的不同,它将无法正常工作。

    另外,我从这个答案中提取了这个想法: https://stackoverflow.com/a/50383879/2150472

    希望对大家有所帮助!

    P.S,如果您只需要能够查看数据并执行 CRUD 操作,您可以随时使用此插件:https://github.com/amitshekhariitbhu/Android-Debug-Database

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多