javaandroidbackupandroid-roomandroid-external-storage

Restore from Room Sqlite database from sd card not working


I looked at others answers like Backup and restore SQLite database to sdcard and Restoring SQLite DB file etc. but i still dont see the restoring of database when i uninstall and reinstall app and restore backup. Here is the code I have currently.

        public class BackupAndRestore {
        
            public static void importDB(Context context) {
                try {
                    File sd = Environment.getExternalStorageDirectory();
        
                    if (sd.canRead()) {
                        File currentDB = context.getDatabasePath(AppDatabase.DATABASE_NAME);
                        File backupDB = new File(sd, AppDatabase.DATABASE_NAME);
        
                        if (currentDB.exists()) {
                            FileChannel src = new FileInputStream(backupDB).getChannel();
                            FileChannel dst = new FileOutputStream(currentDB).getChannel();
                            dst.transferFrom(src, 0, src.size());
                            src.close();
                            dst.close();
                            Toast.makeText(context, "Database Restored successfully", Toast.LENGTH_SHORT).show();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        
            public static void exportDB(Context context) {
                try {
                    File sd = Environment.getExternalStorageDirectory();
                    File data = Environment.getDataDirectory();
        
        
                    if (sd.canWrite()) {
        
                        File currentDB = context.getDatabasePath(AppDatabase.DATABASE_NAME);
                        File backupDB = new File(sd, AppDatabase.DATABASE_NAME);
        
                        if (currentDB.exists()) {
                            FileChannel src = new FileInputStream(currentDB).getChannel();
                            FileChannel dst = new FileOutputStream(backupDB).getChannel();
                            dst.transferFrom(src, 0, src.size());
                            src.close();
                            dst.close();
                            Toast.makeText(context, "Backup is successful to SD card", Toast.LENGTH_SHORT).show();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
            }
        
        }

So I install app and I add content to database. Then I also grant permission to write to external storage before calling this export method above. it shows toast message "Backup is successful... " and I can see the file created in the external storage. Then I uninstall and reinstall and I request permission again to external storage. Then call the method import above. The toast message again is seen "Database Restored.." but I don't see the database content that existed before. I tested on android 7 device and android 10 device. I will appreciate help. Thanks.


Solution

  • After testing and looking around much and thanks to @MikeT i was able to use this class below for backup and restore.

    public class BackupAndRestore {
    
            public static void importDB(Context context) {
                try {
                    File sd = Environment.getExternalStorageDirectory();
                    // by closing the database some other database files ending with -shm and -wal are deleted so that there is one database file and it has all content
                    AppDatabase.getDatabaseInstance(context).close();
    
                    if (sd.canRead()) {
                        File currentDB = context.getDatabasePath(AppDatabase.DATABASE_NAME);
                        File backupDB = new File(sd, AppDatabase.DATABASE_NAME);
    
                        transfer(context, backupDB, currentDB);
                        Toast.makeText(context, "Database Restored successfully", Toast.LENGTH_SHORT).show();
    
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
    
            public static void exportDB(Context context) {
                try {
                    File sd = Environment.getExternalStorageDirectory();
                    // by closing the database some other database files ending with -shm and -wal are deleted so that there is one database file and it has all content
                    AppDatabase.getDatabaseInstance(context).close();
    
                    if (sd.canWrite()) {
                        File currentDB = context.getDatabasePath(AppDatabase.DATABASE_NAME);
                        File backupDB = new File(sd, AppDatabase.DATABASE_NAME);
                        transfer(context, currentDB, backupDB);
    
                        Toast.makeText(context, "Backup is successful to SD card", Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            private static void transfer(Context context, File sourceFile, File destinationFile) throws IOException {
                if (sourceFile.exists()) {
                    FileChannel src = new FileInputStream(sourceFile).getChannel();
                    FileChannel dst = new FileOutputStream(destinationFile).getChannel();
                    dst.transferFrom(src, 0, src.size());
                    src.close();
                    dst.close();
                }
            }
    
        }
    

    In my main activity I call method like below

        ...
    
        if (item.getItemId() == R.id.backup) {
            BackupAndRestore.exportDB(getBaseContext());
            restartApplication();
        } else if (item.getItemId() == R.id.restore) {
            BackupAndRestore.importDB(getBaseContext());
            restartApplication();
        }
    
        ...
    

    So the restartApplication method is called after backup because I noticed the room database was not working properly after backup unless i restart the application and also after after restoring I could not see the restored data unless the application was restarted. The restart method is below

    private void restartApplication() {
        finish();
        startActivity(getIntent());
        System.exit(0);
    }