Architecture-components-samples: How to Export and Import the database/data using Android Room Library?

Created on 22 Apr 2018  Â·  16Comments  Â·  Source: android/architecture-components-samples

I have developed two android application using the _ActiveAndroid_ library. Currently, I am posting all database tables' data to Server (MS SQL Server) for some reasons some data is not synced to the server. I want to backup the database file to sd card and also on the google drive and ask the user to share the database via email from sd card/google drive. So that I can see unsynced data and track the issue and sync/insert the data manually via queries in the server database.

I have googled a lot and found that many android database libraries have no built-in functionality for exporting and importing the SQLite database.

Is Android Room library has the functionality of export and imports the database? If not please add this functionality in the library it will be helpful for developers to handle database and related issues also for clients to share the database easily.

Most helpful comment

If Any have soluation about how to export roomdb to sdcard then give sample code

Note: You also need to copy the "-shm" and "-wal" files

(Reason: https://stackoverflow.com/questions/50372487/android-room-database-file-is-empty)

Based on @or-dvir 's answer, here is the modified version for import and export database:

fun exportDatabaseFile(context: Context) {
    try {
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT).path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT)
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-shm").path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-shm")
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-wal").path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-wal")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun importDatabaseFile(context: Context) {
    try {
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT, context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT).path)
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-shm", context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-shm").path)
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-wal", context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-wal").path)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun copyDataFromOneToAnother(fromPath: String, toPath: String) {
    val inStream = File(fromPath).inputStream()
    val outStream = FileOutputStream(toPath)

    inStream.use { input ->
        outStream.use { output ->
            input.copyTo(output)
        }
    }
}

All 16 comments

Hi @hasnain-ahmad , Is this issue still open?
Hi @yigit , I would like to work on this issue and fix it. Please let me know the process.

@MONIKA-KUMAR-JETHANI Yes the above mentioned issue/functionality is still pending!

I've the same problem, and i would like to find a way to solve that.

The function was implemented? Somebody know anything about this?

Anybody knows the answer please?

warnings

1) i have literally just figured this out and have not yet fully tested this but for now it seems to work.
so far i have only tested that a file with some content is being created in local storage, sd card, and google drive.
2) im not sure whether you have to close your db or not before backing up

solution

1) let user choose location using ACTION_CREATE_DOCUMENT(required API 19)
2) get db file using getDatabasePath(DATABASE_NAME)
3) use contentResolver wiht input/output streams to copy contents.

this code sample is shortened for brevity.
this sample is in kotlin, but the java version should be similar

//somewhere in the code:
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intnet.type = "*/* // this line is a must when using ACTION_CREATE_DOCUMENT
startActivityForResult(intent, REQUEST_CODE)


override fun onActivityResult(...)
{
    //null and exception handling omitted for brevity

    val userChosenUri = data.data
    val inStream = getDatabasePath(DATABASE_NAME).inputStream()
    val outStream = contentResolver.openOutputStream(userChosenUri)

    inStream.use { input ->
        outStream.use { output ->
                            input.copyTo(output)
        }
     }
}

edit

I have also successfully implemented importing of an existing file (at least it seems to be working):
1) choose the file to import (either yourself or let user choose)
2) do same as export, but reverse (copy from userChosenUri to getDataBasePath(...)
3) now you need to "restart" your DB or it will still load your old data. Due to the way my app is built, the easiest thing for me is to "restart" my app and therefore reloading the (now new) DB.
I do this by launching my MainActivity using FLAG_NEW_TASK and FLAG_CLEAR_TASK

If Any have soluation about how to export roomdb to sdcard then give sample code

@KathiriyaHP does my solution not work for sd card?

If Any have soluation about how to export roomdb to sdcard then give sample code

Note: You also need to copy the "-shm" and "-wal" files

(Reason: https://stackoverflow.com/questions/50372487/android-room-database-file-is-empty)

Based on @or-dvir 's answer, here is the modified version for import and export database:

fun exportDatabaseFile(context: Context) {
    try {
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT).path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT)
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-shm").path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-shm")
        copyDataFromOneToAnother(context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-wal").path, Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-wal")
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun importDatabaseFile(context: Context) {
    try {
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT, context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT).path)
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-shm", context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-shm").path)
        copyDataFromOneToAnother(Environment.getExternalStorageDirectory().path + "/Download/" + "backup_" + Constant.DATABASE_NAME_WITH_FORMAT + "-wal", context.getDatabasePath(Constant.DATABASE_NAME_WITH_FORMAT + "-wal").path)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun copyDataFromOneToAnother(fromPath: String, toPath: String) {
    val inStream = File(fromPath).inputStream()
    val outStream = FileOutputStream(toPath)

    inStream.use { input ->
        outStream.use { output ->
            input.copyTo(output)
        }
    }
}

This is a non-working solution. Root rights are required to copy the database created by Room.databaseBuilder. On the line val inStream = getDatabasePath("base.db").InputStream(), we get FileNotFoundException. getDatabasePath returns the correct path, the file is there, but the application does not see it. Or am I doing something wrong. Checked on emulators and a real smartphone. android.arch.persistence.room:runtime:1.1.1

Sorry my mistake. The database is not available for download, if you create it by the standard path, such as /data/user/0/com.app/databases/base.db. But if when creating a database, specify the path such as /storage/emulated/0/folder/base.db - your solution is work! Thanks.

@pravbeseda i am also getting file not found exception... what do you mean by "specify the path"? do we have to specify the path when building room database with "Room.databaseBuilder?"

do we have to specify the path when building room database with "Room.databaseBuilder?"

Yes.

Room.databaseBuilder<AppDatabase>(context, AppDatabase::class.java, databasePath)

This doesn't seem to be an issue with the samples. You can file an issue against Room on the issue tracker if you're still having an issue.

This doesn't seem to be an issue with the samples. You can file an issue against Room on the issue tracker if you're still having an issue.

I have posted at the following link.
https://issuetracker.google.com/issues/154588984

Solved the issue

On Tue, 21 Apr, 2020, 11:04 PM Hasnain Ahmad, notifications@github.com
wrote:

This doesn't seem to be an issue with the samples. You can file an issue
against Room on the issue tracker
https://issuetracker.google.com/issues/new?component=413107 if you're
still having an issue.

I have posted at the following link.
https://issuetracker.google.com/issues/154588984

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/android/architecture-components-samples/issues/340#issuecomment-617307241,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ACBARZ72GZR6YLT3XSJZMQDRNXKKTANCNFSM4E336DFQ
.

Was this page helpful?
0 / 5 - 0 ratings