【问题标题】:Room best ways to create backups for offline application?房间为离线应用程序创建备份的最佳方法?
【发布时间】:2018-06-18 19:36:05
【问题描述】:

所以我说相当复杂的数据库,它使用many to many 数据库设计和foreign keys 并连接表,它是Room 数据库。我想为它创建备份系统,因为它是离线应用程序,我需要导出数据库并将其存储到谷歌驱动器的应用程序文件夹中。最近几天我读了很多关于它的文章,但仍然有点困惑我看到有办法将数据库导出为 CSVJSONexcel 文件或就像.db 文件一样,但是这样做的最佳做法是什么以及专业人员如何处理它?

【问题讨论】:

  • 您的数据库本质上只是一个简单的文件。使用例如WorkManager 应该让预定的上传变得轻而易举。

标签: android performance sqlite android-sqlite android-room


【解决方案1】:

几乎不需要做任何复杂的事情,只需保存 SQLiteDatabase 文件即可。

基本上关闭 Room db 然后保存文件。

例如以下是一个非常基本的示例,它保存在名为 DBsaves 的子目录中的下载目录中:-

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    resetSequenceAction();
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        verifyStoragePermissions(this);
    }
}

@Override
protected void onStart() {
    super.onStart();
    mTestDB = Room.databaseBuilder(this,TestDatabase.class,TestDatabase.DBNAME).build();
    addSomeData();
    addSomeData();
    addSomeData();
    addSomeData();
    mTestDB.close();
    File dbfile = this.getDatabasePath(TestDatabase.DBNAME);
    File sdir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"DBsaves");
    String sfpath = sdir.getPath() + File.separator + "DBsave" + String.valueOf(System.currentTimeMillis());
    if (!sdir.exists()) {
        sdir.mkdirs();
    }
    File savefile = new File(sfpath);
    try {
        savefile.createNewFile();
        int buffersize = 8 * 1024;
        byte[] buffer = new byte[buffersize];
        int bytes_read = buffersize;
        OutputStream savedb = new FileOutputStream(sfpath);
        InputStream indb = new FileInputStream(dbfile);
        while ((bytes_read = indb.read(buffer,0,buffersize)) > 0) {
            savedb.write(buffer,0,bytes_read);
        }
        savedb.flush();
        indb.close();
        savedb.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}


public void verifyStoragePermissions(Activity activity) {

    final int REQUEST_EXTERNAL_STORAGE = 1;
    String[] PERMISSIONS_STORAGE = {

            //Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };

    int permission = ActivityCompat.checkSelfPermission(
            activity,
            Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if(permission != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}
  • 注意 onCreate 和 verifyStoragePermissions 方法仅用于获取写入外部存储的权限(注意用户权限也在清单中设置)。

    • 导入是在 Room 之外执行此操作(如果您要从备份中恢复)。

运行后:-

然后将文件复制到 PC 并使用 SQLite 管理器打开:-

这完全符合预期并且高度便携,即您可以将其放入任何 SQLite 工具中(此类工具使用的 SQLite 版本可能是一个限制因素)

【讨论】:

  • 是的,基本上只是反转过程,即复制 db 以恢复到 dbfile,您可能会发现有必要重新启动应用程序。我用Intent i = getBaseContext().getPackageManager() .getLaunchIntentForPackage( getBaseContext().getPackageName() ); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); finish(); startActivity(i); System.exit(0);
  • 但是,您可能需要先获取数据库的副本。我所做的是复制数据库,删除原始文件,然后复制文件以恢复到数据库文件。如果一切正常,请删除所拍摄的副本。如果不正确,则删除数据库文件并重命名已获取的副本(复制到与 db 相同的路径)。
  • 问题是,如果恢复是在开始以外的任何地方,那么您基本上需要刷新所有活动的所有数据。所以理论上是的,但它可能很难/复杂。
  • 还有一件事,启用预写日志记录的过程是否相同?我的意思是用它创建另一个文件 .db-wal
  • 理论上收盘应该收拾好。我相信 Room 会开启 WAL。
猜你喜欢
  • 2014-06-04
  • 2016-01-14
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 2011-06-06
  • 1970-01-01
  • 2017-07-17
相关资源
最近更新 更多