Issue
I have been working on getting my database backing up to work and I have reached a point where I am not sure what to do.
Basically at first the application opens a Login activity, the user logs in and their database file (if it exists) is downloaded from the Firebase Storage, and then the application navigates to the MainActivity.
In the MainActivity I call a method that sends the user's database file to Firebase Storage. I tried to manage the process by closing the database but since i couldn't fix an error of "E/ROOM: Invalidation tracker is initialized twice :/.", then I found an answer to use a checkpoint (Backup Room database). Now I implemented the forced checkpoint method.
(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());
}
});
}
}
}
If the user logs out, then the files in the "/data/data/"+ getPackageName() + "/databases/" are deleted, which I have manually confirmed by looking at the databases folder of the application.
My issue is that after the databases are deleted and a new user logs in, then the previous database data remains but when I manually check the app's data folder, then the /databases/ folder shows that the files were deleted and a new file is created but it doesn't show any WAL or SHM files and also I get the data of another database which is created when the application first runs, but that file is also not shown in the databases/ folder.
Can anyone explain why the folder doesn't show the files that should be present, where is the application getting the data that was deleted and how to fix it.
Edit: My application has multiple Room databases and I just realized that all the data is still readable after the files were deleted.
The method to delete the database files
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;
}
Solution
If you are using the same exact RoomDatabase
object simply building another one over the same object will prevent any hold over cached data from showing up. I've tested this using multiple database swaps large and small and there is no bleed over.
If you are using a new Instance of the RoomDatabase
object for every login try closing the old one after the user logs out. Room will typically close when not needed but if you need it to happen immediately, manually closing it is your best bet.
roomDb.getOpenHelper().close();
Answered By - avalerio