2020-06-26 21:49:44 +02:00
# Android-Room-Database-Backup
2020-06-25 20:23:56 +02:00
2020-10-11 11:57:04 +02:00

2021-12-09 13:39:03 +01:00
[](https://maven-badges.herokuapp.com/maven-central/de.raphaelebner/roomdatabasebackup)
2024-01-16 21:12:22 +01:00
[](https://developer.android.com/jetpack/androidx/releases/room#2 .6.1)
2021-03-23 22:13:03 +01:00
[](https://android-arsenal.com/api?level=21)
2020-06-25 20:23:56 +02:00

[](https://github.com/rafi0101/Android-Room-Database-Backup/pulls)
2022-10-30 10:59:26 +01:00
[](https://github.com/rafi0101/Android-Room-Database-Backu/blob/master/LICENSE)
2020-06-25 20:23:56 +02:00
<div align="center">
<sub>Built with ❤︎ by
<a href="https://github.com/rafi0101">Raphael Ebner</a>
</div>
<br/>
Simple tool to backup and restore your room database in Android
2024-04-21 17:36:18 +02:00
## Features
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- Create simple backups of your room database
- Encrypt the backup file with AES encryption
- Save the backup to any type of storage (some types are in beta)
- Material design
- Written in Kotlin
## Content
- [Features ](#Features )
- [Changelog ](#Changelog )
- [Getting started ](#Getting-started )
- [Usage ](#Usage )
- [Sample app ](#Sample-app )
- [Developed by ](#Developed-by )
- [License ](#License )
## Changelog
2020-06-25 20:23:56 +02:00
2021-12-07 21:21:01 +01:00
[Changelog and Upgrading notes ](CHANGELOG.md )
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
## Getting started
2021-12-09 13:39:03 +01:00
2023-03-11 18:46:15 +01:00
Android-Room-Database-Backup library is pushed
2024-12-03 21:19:29 +01:00
to [Maven Central ](https://central.sonatype.com/artifact/de.raphaelebner/roomdatabasebackup/1.0.2/versions )
2023-03-11 18:46:15 +01:00
.
2022-01-06 11:34:02 +01:00
Add the dependency for `Android-Room-Database-Backup ` to your app-level `build.gradle` file.
2021-12-09 13:39:03 +01:00
```groovy
2024-12-03 21:19:29 +01:00
implementation 'de.raphaelebner:roomdatabasebackup:1.0.2'
2021-12-09 13:39:03 +01:00
```
2024-04-21 17:23:11 +02:00
**If the version makes any technical problems please feel free to contact me. I made some changes in
Gradle/Kotlin DSL and not sure if everything is working as excepted**
2024-01-16 21:12:22 +01:00
2024-04-21 17:36:18 +02:00
## Usage
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- [Properties ](#Properties )
- [Exit Codes ](#Exit-Codes )
- [Example Activity (Kotlin and Java) ](#example-activity-kotlin-and-java )
- [Example Fragment (Java and Kotlin) ](#example-fragment-kotlin-and-java )
2020-06-25 20:23:56 +02:00
### Properties
**Required**
2024-04-21 17:36:18 +02:00
- Current context
2021-11-14 18:38:50 +01:00
**Attention**
2024-04-21 17:36:18 +02:00
Must be declared outside of an onClickListener before lifecycle state changes to started
2020-06-26 21:43:10 +02:00
2024-04-21 17:36:18 +02:00
```kotlin
RoomBackup(this)
` ``
2024-04-21 17:23:11 +02:00
2024-04-21 17:36:18 +02:00
- Instance of your room database
2020-06-26 21:43:10 +02:00
2020-06-25 20:29:02 +02:00
` ``kotlin
.database(*YourDatabase*.getInstance(this))
` ``
2020-06-25 20:23:56 +02:00
2022-01-06 11:34:02 +01:00
e.g. [` YourDatabase.kt`](app/src/main/java/de/raphaelebner/roomdatabasebackup/sample/database/main/FruitDatabase.kt)
2020-06-25 20:23:56 +02:00
**Optional**
The following options are optional and the default options
2024-04-21 17:36:18 +02:00
- Enable logging, for debugging and some error messages
2020-06-26 21:43:10 +02:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.enableLogDebug(false)
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Set custom log tag
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.customLogTag("debug_RoomBackup")
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Enable and set maxFileCount
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- if file count of Backups > maxFileCount all old / the oldest backup file will be deleted
- can be used with internal and external storage
- default: infinity
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.maxFileCount(5)
` ``
2020-06-26 21:43:10 +02:00
2024-04-21 17:36:18 +02:00
- Encrypt your backup
2020-06-26 21:43:10 +02:00
2024-04-21 17:36:18 +02:00
- Is encrypted with AES encryption
- uses a random 15 digit long key with alphanumeric characters
- this key is saved in [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences)
- backup name is default backup name + ".aes"
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.backupIsEncrypted(false)
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Encrypt your backup with your own password / key
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- This property is only working, if ` .backupIsEncrypted(true)` is set
- If you use the key to encrypt the backup, you will also need it to decrypt
- Example: If you want to create an encrypted backup, export it and import it to another device. Then you need a custom key, else the backup is encrypted with a random key, and you can not decrypt it on a new device
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
**Attention**
i do not assume any liability for the loss of your key
2021-12-07 21:21:01 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.customEncryptPassword("YOUR_SECRET_PASSWORD")
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Save your backup to different storage
2021-11-14 18:38:50 +01:00
2024-04-21 17:36:18 +02:00
- External
- storage path: /storage/emulated/0/Android/data/_package_/files/backup/
- This files will be deleted, if you uninstall your app
- ` RoomBackup.BACKUP_FILE_LOCATION_EXTERNAL`
- Internal
- Private, storage not accessible
- This files will be deleted, if you uninstall your app
- ` RoomBackup.BACKUP_FILE_LOCATION_INTERNAL`
- Custom Dialog (beta)
- You can choose to save or restore where ever you want. A CreateDocument() or OpenDocument() Activity will be launched where you can choose the location
2024-04-21 17:55:02 +02:00
- If your backup is encrypted I reccomend you using a custom encrption password else you can't
restore your backup
- ` RoomBackup.BACKUP_FILE_LOCATION_CUSTOM_DIALOG`
2024-04-21 17:36:18 +02:00
- Custom File (beta)
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- You can choose to save or restore to/from a custom File.
- If your backup is encrypted I reccomend you using a custom encrption password else you can't restore your backup
- Please use ` backupLocationCustomFile(File)` to set a custom File
- ` RoomBackup.BACKUP_FILE_LOCATION_CUSTOM_FILE`
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
**Attention**
For custom dialog and custom file I only verified the functionality for local storage. For thirt party storage please try and contact me if it is not working. I hope I can find a solution and fix it :)
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL)
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Set a custom File to save/restore to/from
Only working if ` backupLocation` is set to ` BACKUP_FILE_LOCATION_CUSTOM_FILE`
You have to define a File withe Filename and extension
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.backupLocationCustomFile(backupLocationCustomFile: File)
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Set a custom dialog title, when showing list of available backups to restore (only for external or internal storage)
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.customRestoreDialogTitle("Choose file to restore")
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Set your custom name to the Backup files
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
**Attention**\
If a backup file with the same name already exists, it will be replaced
2020-06-26 21:43:10 +02:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.customBackupFileName(*DatabaseName* + *currentTime* + ".sqlite3")
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Run some code, after backup / restore process is finished
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- success: Boolean (If backup / restore was successful = true)
- message: String (message with simple hints, if backup / restore failed)
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
.onCompleteListener { success, message, exitCode ->
}
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- Restart your Application. Can be implemented in the onCompleteListener, when "success == true"
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
**Attention**\
it does not always work reliably!\
But you can use other methods.\
Important is that all activities / fragments that are still open must be closed and reopened\
Because the Database instance is a new one, and the old activities / fragments are trying to
work with the old instance
` ``kotlin
.restartApp(Intent(this@MainActivity, MainActivity::class.java))
` ``
2020-06-25 20:23:56 +02:00
2022-01-06 14:32:39 +01:00
### Exit Codes
Here are all exit codes for the onCompleteListener.
2024-04-21 17:36:18 +02:00
They can be calles using ` OnCompleteListener.$NAME$`
2022-01-06 14:32:39 +01:00
2024-04-21 17:36:18 +02:00
| Exit Code | Name | Description |
| --------- | :----------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| 0 | ` EXIT_CODE_SUCCESS` | No error, action successful |
| 1 | ` EXIT_CODE_ERROR` | Other Error |
| 2 | ` EXIT_CODE_ERROR_BACKUP_FILE_CHOOSER` | Error while choosing backup to restore. Maybe no file selected |
| 3 | ` EXIT_CODE_ERROR_BACKUP_FILE_CREATOR` | Error while choosing backup file to create. Maybe no file selected |
| 4 | ` EXIT_CODE_ERROR_BACKUP_LOCATION_FILE_MISSING` | [BACKUP_FILE_LOCATION_CUSTOM_FILE] is set but [RoomBackup.backupLocationCustomFile] is not set |
| 5 | ` EXIT_CODE_ERROR_BACKUP_LOCATION_MISSING` | [RoomBackup.backupLocation] is not set |
| 6 | ` EXIT_CODE_ERROR_BY_USER_CANCELED` | Restore dialog for internal/external storage was canceled by user |
| 7 | ` EXIT_CODE_ERROR_DECRYPTION_ERROR` | Cannot decrypt provided backup file |
| 8 | ` EXIT_CODE_ERROR_ENCRYPTION_ERROR` | Cannot encrypt database backup |
| 9 | ` EXIT_CODE_ERROR_RESTORE_BACKUP_IS_ENCRYPTED` | You tried to restore a encrypted backup but [RoomBackup.backupIsEncrypted] is set to false |
| 10 | ` EXIT_CODE_ERROR_RESTORE_NO_BACKUPS_AVAILABLE` | No backups to restore are available in internal/external sotrage |
| 11 | ` EXIT_CODE_ERROR_ROOM_DATABASE_MISSING` | No room database to backup is provided |
| 12 | ` EXIT_CODE_ERROR_STORAGE_PERMISSONS_NOT_GRANTED` | Storage permissions not granted for custom dialog |
| 13 | ` EXIT_CODE_ERROR_WRONG_DECRYPTION_PASSWORD` | Cannot decrypt provided backup file because the password is incorrect |
2022-01-06 14:32:39 +01:00
2022-01-26 22:33:09 +01:00
### Example Activity (Kotlin and Java)
#### Kotlin
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- ##### Backup
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
` ``kotlin
val backup = RoomBackup(this)
...
backup
.database(FruitDatabase.getInstance(this))
.enableLogDebug(true)
.backupIsEncrypted(true)
.customEncryptPassword("YOUR_SECRET_PASSWORD")
.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL)
.maxFileCount(5)
.apply {
onCompleteListener { success, message, exitCode ->
Log.d(TAG, "success: $success, message: $message, exitCode: $exitCode")
if (success) restartApp(Intent(this@MainActivity, MainActivity::class.java))
}
}
.backup()
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- ##### Restore
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``kotlin
val backup = RoomBackup(this)
...
backup
.database(FruitDatabase.getInstance(this))
.enableLogDebug(true)
.backupIsEncrypted(true)
.customEncryptPassword("YOUR_SECRET_PASSWORD")
.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL)
.apply {
onCompleteListener { success, message, exitCode ->
Log.d(TAG, "success: $success, message: $message, exitCode: $exitCode")
if (success) restartApp(Intent(this@MainActivity, MainActivity::class.java))
}
}
.restore()
` ``
2020-06-25 20:23:56 +02:00
2022-01-26 22:33:09 +01:00
#### Java
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- ##### Backup
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``java
final RoomBackup roomBackup = new RoomBackup(MainActivityJava.this);
...
roomBackup.database(FruitDatabase.Companion.getInstance(getApplicationContext()));
roomBackup.enableLogDebug(enableLog);
roomBackup.backupIsEncrypted(encryptBackup);
roomBackup.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL);
roomBackup.maxFileCount(5);
roomBackup.onCompleteListener((success, message, exitCode) -> {
Log.d(TAG, "success: " + success + ", message: " + message + ", exitCode: " + exitCode);
if (success) roomBackup.restartApp(new Intent(getApplicationContext(), MainActivityJava.class));
});
roomBackup.backup();
` ``
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
- ##### Restore
2021-11-15 21:05:36 +01:00
2024-04-21 17:36:18 +02:00
` ``java
final RoomBackup roomBackup = new RoomBackup(MainActivityJava.this);
...
roomBackup.database(FruitDatabase.Companion.getInstance(getApplicationContext()));
roomBackup.enableLogDebug(enableLog);
roomBackup.backupIsEncrypted(encryptBackup);
roomBackup.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL);
roomBackup.onCompleteListener((success, message, exitCode) -> {
Log.d(TAG, "success: " + success + ", message: " + message + ", exitCode: " + exitCode);
if (success) roomBackup.restartApp(new Intent(getApplicationContext(), MainActivityJava.class));
});
roomBackup.restore();
` ``
2020-06-25 20:23:56 +02:00
2022-01-26 22:33:09 +01:00
### Example Fragment (Kotlin and Java)
##### Kotlin
[` FragmentActivity.kt`](app/src/main/java/de/raphaelebner/roomdatabasebackup/sample/FragmentActivity.kt)
[` MainFragment.kt`](app/src/main/java/de/raphaelebner/roomdatabasebackup/sample/MainFragment.kt)
##### Java
[` FragmentActivityJava.java`](app/src/main/java/de/raphaelebner/roomdatabasebackup/sample/FragmentActivityJava.java)
[` MainFragmentJava.java`](app/src/main/java/de/raphaelebner/roomdatabasebackup/sample/MainFragmentJava.java)
2024-04-21 17:36:18 +02:00
## Sample app
2022-01-26 22:33:09 +01:00
2020-06-25 20:23:56 +02:00
1. Download this repo
2022-01-26 22:33:09 +01:00
2. Unzip
2020-06-25 20:23:56 +02:00
3. Android Studio --> File --> Open --> select this Project
4. within the app folder you find the sample app
2024-04-21 17:36:18 +02:00
## Developed by
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
- Raphael Ebner
- [paypal.me/raphaelebner ](https://www.paypal.me/raphaelebner )
2020-06-25 20:23:56 +02:00
2024-04-21 17:36:18 +02:00
## License
2020-06-25 20:23:56 +02:00
2021-03-23 21:32:58 +01:00
MIT License
2024-01-16 20:56:37 +01:00
Copyright (c) 2024 Raphael Ebner
2021-03-23 21:32:58 +01:00
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.