【问题标题】:Application gives data from deleted database file in Android应用程序从 Android 中已删除的数据库文件中提供数据
【发布时间】:2022-01-10 07:19:18
【问题描述】:

我一直在努力让我的数据库备份工作,但我已经到了不知道该怎么做的地步。

基本上,首先应用程序打开一个登录活动,用户登录并从 Firebase 存储下载他们的数据库文件(如果存在),然后应用程序导航到 MainActivity。

在 MainActivity 中,我调用了一个将用户的数据库文件发送到 Firebase 存储的方法。我试图通过关闭数据库来管理该过程,但由于我无法修复“E/ROOM:无效跟踪器被初始化两次:/。”的错误,所以我找到了使用检查点的答案(Backup Room database)。现在我实现了强制检查点方法。

(MarkerDao)
    @RawQuery
    int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
(MarkerRepository)
 public void checkPoint(){
        Thread thread= new Thread(() ->  markerDao.checkpoint(new SimpleSQLiteQuery("pragma wal_checkpoint(full)")));
        thread.start();
    }
(ViewModel)
    public void setCheckpoint(){
        repository.checkPoint();
    }

(Database back-up method in the MainActivity)
    private void copyDbToFirebase(){
        String currentDBPath = "/data/data/"+ getPackageName() + "/databases/locations_table";
        File dbBackupFile = new File(currentDBPath);
        if (dbBackupFile.exists()){
            markerViewModel.setCheckpoint();
            // create file from the database path and convert it to a URI
            Uri backupDB = Uri.fromFile(new File(currentDBPath));
            // Create a StorageReference
            StorageReference dbReference = storageRef.child("users").child(userId).child("user database").child("locations_table");
            // Use the StorageReference to upload the file
            if (userId != null){
                dbReference.putFile(backupDB).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Log.d(TAG, "onSuccess: "+4 + taskSnapshot);
                        Toast.makeText(getApplicationContext(), "Database copied to Firebase 4", Toast.LENGTH_LONG).show();
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.d(TAG, "onFailure: "+ e.getMessage());
                    }
                });
            }
        }
    }

如果用户注销,则“/data/data/”+ getPackageName() + “/databases/”中的文件将被删除,我已通过查看应用程序的数据库文件夹手动确认。

我的问题是,在删除数据库并有新用户登录后,以前的数据库数据仍然存在,但是当我手动检查应用程序的数据文件夹时,/databases/ 文件夹显示文件已被删除并且新的文件已创建,但它没有显示任何 WAL 或 SHM 文件,而且我还获得了在应用程序首次运行时创建的另一个数据库的数据,但该文件也未显示在 databases/ 文件夹中。

谁能解释为什么该文件夹不显示应该存在的文件,应用程序在哪里获取已删除的数据以及如何修复它。

编辑:我的应用程序有多个 Room 数据库,我刚刚意识到删除文件后所有数据仍然可读。

删除数据库文件的方法

  private boolean deleteDatabaseFiles(File path) {
        if(path.exists() ) {
            File[] files = path.listFiles();
            for(int i=0; i<files.length; i++) {
                if(files[i].isDirectory()) {
                    deleteDatabaseFiles(files[i]);
                }
                else {
                    files[i].delete();
                }
            }
        }
        return true;
    }

【问题讨论】:

    标签: java android database sqlite android-room


    【解决方案1】:

    如果您使用的是完全相同的 RoomDatabase 对象,只需在同一对象上构建另一个对象即可防止任何保留的缓存数据出现。我已经使用大大小小的多个数据库交换对此进行了测试,并且没有溢出。

    如果您每次登录都使用RoomDatabase 对象的新实例,请尝试在用户注销后关闭旧实例。房间通常会在不需要时关闭,但如果您需要立即关闭,最好手动关闭。

    roomDb.getOpenHelper().close();
    

    【讨论】:

    • 数据库是同步的,所以一次只存在一个实例,我之前试过关闭数据库的解决方法,登录后返回错误E/SQLiteLog: (1) no such table: room_table_modification_log in "SELECT * FROM room_table_modification_log WHERE invalidated = 1;" E/ROOM: Cannot run invalidation tracker. Is the db closed?
    • 我花了一段时间才明白自己做错了什么,而且一旦关闭,应用程序中没有逻辑来重建数据库。代表我犯了一个愚蠢的错误,但谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    相关资源
    最近更新 更多