Search code examples
androidsqlitebackup

Restoring sqlite database android


I'm trying to add a backup funcionality in my app, but I have some problem with that.

This is my code:

    public void importDB() {
        try {
            File sd = Environment.getExternalStorageDirectory();
            File data = Environment.getDataDirectory();

            if (sd.canWrite()) {
                String currentDBPath = "/data/" + "com.example" + "/databases/" + "clinic_database";
                String backupDBPath = "clinic_database";
                File currentDB = new File(data, currentDBPath);
                File backupDB = new File(sd, backupDBPath);

                if (true) {
                    FileChannel src = new FileInputStream(backupDB).getChannel();
                    FileChannel dst = new FileOutputStream(currentDB).getChannel();
                    dst.transferFrom(src, 0, src.size());
                    src.close();
                    dst.close();
                    Toast.makeText(getActivity(), "Database Restored successfully", Toast.LENGTH_SHORT).show();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_LONG)
                    .show();
        }
    }

    private void exportDB() {
        try {
            File sd = Environment.getExternalStorageDirectory();
            File data = Environment.getDataDirectory();

            if (sd.canWrite()) {
                String currentDBPath = "/data/" + "com.example" + "/databases/" + "clinic_database";
                String backupDBPath = "clinic_database";
                File currentDB = new File(data, currentDBPath);
                File backupDB = new File(sd, backupDBPath);

                int permissionCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);

                if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(
                            getActivity(),
                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                            123);
                } else {
                    FileChannel src = new FileInputStream(currentDB).getChannel();
                    FileChannel dst = new FileOutputStream(backupDB).getChannel();
                    dst.transferFrom(src, 0, src.size());
                    src.close();
                    dst.close();
                    Toast.makeText(getActivity(), "DB saved! sdcard/" + backupDBPath, Toast.LENGTH_LONG).show();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getActivity(), "nope", Toast.LENGTH_SHORT).show();
        }
    }

I have 3 default patients in my database. First, I export my database file to sdcard. In next step I remove patients from my database. Then I click on import button, everything looks fine (database file in app data folder is updated), but I still don't have any patients in my database.

Maybe it's because in my app I have 3 database files: clinic_database, clinic_database-shm and clinic_database-wal, but I think that shm and wal file are temporary.

So, am I doing something wrong? Should I "reload" my database somehow? Thanks in advance!


Solution

  • Maybe it's because in my app I have 3 database files: clinic_database, clinic_database-shm and clinic_database-wal, but I think that shm and wal file are temporary.

    Although they are temporary as such, the -wal file and the -shm file may well persist if they contain any transactions, thus those transactions will be applied if the -wal file remains.

    The correct way to backup the database, if using WAL, is to

    • either backup the -wal and -shm files along with the database and restore all 3 files.

    • or to ensure that the database is fully checkpointed and then only backup the database file and when restoring ensure that the -wal and -shm files are deleted if they exist.

      • closing the database will fully checkpoint the database.
      • alternately you you use the wal_checkpoint pragma to checkpoint.