How to properly close and reopen Room Database : <p>Hello I have 2 apps that rely on making and restoring the backups of the app's databases just by copying the databases files in and out the sdcard and am having a hard time figuring out how to reopen the Room Database singleton after closing it to make the databases' copies.</p>

<p>Building the database:</p>

<pre><code>@Database(version = 15, exportSchema = true, entities = [list of entities])
abstract class AppDatabase : RoomDatabase() {

//list of DAOs

companion object {

    @Volatile private var INSTANCE: AppDatabase? = null

    fun getInstance(context: Context): AppDatabase =
            INSTANCE ?: synchronized(this) {
                INSTANCE ?: buildDatabase(context).also {
                    INSTANCE = it
                }
            }

    private fun buildDatabase(context: Context) =

            Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "Fazendao.sqlitedb"
            )
            .addMigrations(Migration1315)
            .build()

    }
}
</code></pre>

<p>Closing the database:</p>

<pre><code>fun closeDatabase() {
    if(db.isOpen) {
        db.openHelper.close()
    }
}
</code></pre>

<p>Making the database file copy (inside a ViewModel):</p>

<pre><code>fun exportaBkpObservable(nome: String, auto: String, storage: File, database: File) {
    disposable.clear()
    setFlagsNull()

    flagSubject.onNext(false)

    disposable.add(
            Observable.fromCallable {
                repo.recordBkpName(nome)
            }
            .subscribeOn(Schedulers.io())
            .flatMap {
                return@flatMap try {

                    //closing the database
                    repo.closeDatabase()

                    Observable.just(
                        database.copyTo(File(storage, auto), true)
                    )
                    .flatMap {

                        val myDb = SQLiteDatabase.openOrCreateDatabase(it, null)
                        val ok = myDb.isDatabaseIntegrityOk

                        if(myDb.isOpen) myDb.close()

                        if(ok) {
                            Observable.just(ok)
                        } else {
                            Observable.error&lt;Throwable&gt;(Throwable("CORRUPTED DATABASE"))
                        }
                    }

                } catch (t: Throwable) {
                    Observable.error&lt;Throwable&gt;(t)
                }
            }
            .subscribe(
                    {},
                    {
                        errorFlag = "exportDB: " + it.message
                        errorSubject.onNext("exportDB: " + it.message)
                    },
                    {
                        //trying to reopen database
                        repo.openDatabase()

                        trueFlag = true
                        flagSubject.onNext(true)
                    }
            )
    )

}
</code></pre>

<p>The repo is the repository where the AppDatabase is injected, and in its turn is injected in the ViewModelFactory.</p>

<p>Injection:</p>

<pre><code>object MainInjection {
    private fun providesIORepo(context: Context): IORepo {

        return IORepo(AppDatabase.getInstance(context))
    }

    fun provideIOViewModelFactory(context: Context): IOViewModelFactory {

        val data = providesIORepo(context)

        return IOViewModelFactory(data)
    }
}
</code></pre>

<p>And in the AppCompatActivity onCreate:</p>

<pre><code>val modelFactory = MainInjection.provideIOViewModelFactory(this)
viewModel = ViewModelProviders.of(this, modelFactory).get(IOViewModel::class.java)
</code></pre>

<p>Reopening the database:</p>

<pre><code>fun openDatabase() {
    if(!db.isOpen){
        db.openHelper.writableDatabase
    }
}
</code></pre>

<p>Now the error messages:</p>

<p>Trying to reopen the database:</p>

<pre><code>E/ROOM: Invalidation tracker is initialized twice :/.
</code></pre>

<p>And consequently the crash when I try to access it from another function:</p>

<pre><code>Cannot perform this operation because the connection pool has been closed.
</code></pre>

<p>Sometimes after closing the database I have also:</p>

<pre><code>E/ROOM: Cannot run invalidation tracker. Is the db closed?
</code></pre>

<p>In this post <a href="https://medium.com/google-developers/incrementally-migrate-from-sqlite-to-room-66c2f655b377" rel="noreferrer">Incrementally migrate from SQLite to Room</a> the author opens and closes the database for each access to it, so I don't understand why my implementation is not working.</p>

<p>So where am I wrong ? Is there a way of deactivating the InvalidationTracker too ?</p>

<p>Should I use the following code to close the database and clear the Room instance every time I have to copy the database file. Is it safe ?:</p>

<pre><code>fun destroyInstance() {

        if (INSTANCE?.isOpen == true) {
            INSTANCE?.close()
        }

        INSTANCE = null
    }
</code></pre>

<p>Thanks for the attention.</p>
