Rename Realm DB file name in Android - android

I have a Realm DB file, with name "abc.realm". How to change this name to something else? Should I just replace the file name using IO operations or can I do it with migrations? Not able to find any satisfactory answer neither on the web nor on StackOverflow.

Realm stores 2 files, the realm itself and a .lock file. So if you call your realm "abc.realm", then next to this file there is also "abc.realm.lock".
The way to go about renaming your realm file is,
Make sure you find the location of both files
Rename both files with the same name but keeping the ".lock" extension on the lock file
Modify the path to the realm that you pass to the RealmConfigurationBase inheritor
Clearly before doing any of this, make sure to backup your database, just in case.
I don't know what programming language you're writing your android application in, so I'll go with a skeleton in pseudocode
private void BackupRealmFile(string realmLocation, string saveLocation)
{
// make a copy of the file and store it somewhere
}
void YourMainMethod()
{
BackupRealmFile("some/path", "your/backup/path");
IOLib.RenameFile("some/path/abc.realm", "some/path/newName.realm");
IOLib.RenameFile("some/path/abc.realm.lock", "some/path/newName.realm.lock");
var config = new RealmConfiguration("some/path/newName.realm");
// maybe some more settings on your conf
var realm = Realm.GetInstance(config);
}
I hope this helps.

Related

java.lang.FileNotFoundException in Android/Kotlin even though file is present

I have a data class called Contact which has a companion object property 'allContacts: List' which returns contacts after parsing them from a JSON file.
Relevant code:
val allContacts: List<Contact>
get() {
val json = JSONObject(File("app/src/main/res/data/contacts.json").readText()).getJSONArray("contacts")
val contacts = mutableListOf<Contact>()
...
I do indeed have a contacts.json in res/data package. (data package created manually).
Here's the proof:
Why is this happening? Is the contacts.json file not included in the final .apk?
I have tried logging the current path of the app using
Log.i('.MainActivity', System.getProperty('user.dir'))
But always get . in Logcat.
EDIT: I decompiled the apk in Android Studio and found no traces of contacts.json
Your file doesn't exist in the same project directory you expect it to.
You have to create a resource directory raw and paste your file in there.
Then, you can reference your file as R.raw.contacts wherever you need to reference the file.
Reading the file is another story.
I found it best to create a separate top-level extension function for reading and returning the file contents
fun Activity.readFile(fileID: Int): String {
val inputStream = this.resources.openRawResources(fileID)
return inputStream.use{it.readText()} // Returns entirety of file contents as string.
}

Android: SQLite database created with room shows no tables when opening with sqlte-browser

I am using Room Persistence Library 1.1.0. I could find the database file at /data/data/<package_name>/databases/ using Android Studio's Device File Explorer.
It contains multiple tables and I can access contents of that tables without any problem using room-DAOs. However when opening with sqlite-browser, is shows no table.
What might be the reason? Is it possible to resolve the issue without switching back to old SQLiteOpenHelper from room?
Solution
To open such databases* with sqlite-browser, you need to copy all three files. All must be in the same directory.
* Databases stored in multiple files as stated in the question.
Why three files?
As per docs, Starting from version 1.1.0, Room uses write-ahead logging as default journal mode for devices which has sufficient RAM and running on API Level 16 or higher. It was Truncate for all devices until this version. write-ahead logging has different internal structure compared to Truncate.
Take a look at the files temporary files used by SQLite now and then :
Until version 1.1.0
From version 1.1.0
If you want to change the journal mode explicitly to Truncate, you can do it this way. But, it is not recommended because WAL is much better compared to Truncate.
public static void initialize(Context context) {
sAppDatabase = Room.databaseBuilder(
context,
AppDatabase.class,
DATABASE_NAME)
.setJournalMode(JournalMode.TRUNCATE).build();
}
Is it possible to move it to single file without changing to Truncate ?
Yes, it is. Query the following statement against the database.
pragma wal_checkpoint(full)
It is discussed in detail here here.
Copy all three files from Device File Explorer in AndroidStudio to your PC directory and open the db file in Db Browser for SQLite (http://sqlitebrowser.org). Make sure all three files are in the same folder.
You can use the wal_checkpoint pragma to trigger a checkpoint which will move the WAL file transactions back into the database.
theRoomDb.query("pragma wal_checkpoint(full)", null)
or
// the result
// contains 1 row with 3 columns
// busy, log, checkpointed
Cursor cursor = theRoomDb.query("pragma wal_checkpoint(full)", null)
See PRAGMA Statements for more details about the pragma parameter values and results.
If the WAL is not enabled the pragma does nothing.
By the way, I tested with Room 1.1.1, and the WAL mode was not used by default, I had to enable it.
Room database Export and Import Solution
Im facing same problem in one of my project, i spend two days to resolve this issue.
Solution
Don't create multiple instance for Room library. Multiple instance creating all the problems.
MyApplication
class MyApplication: Application()
{
companion object {
lateinit var mInstanceDB: AppDatabase
}
override fun onCreate() {
super.onCreate()
mInstanceDB = AppDatabase.getInstance(this)
}
}
AppDatabase
fun getInstance(context: Context): AppDatabase
{
if (sInstance == null) {
sInstance = Room.databaseBuilder(context.applicationContext,AppDatabase::class.java, "database").allowMainThreadQueries().build()
return sInstance!!
}
}
Now use this instance in any number of activity or fragment just like that
{
var allcustomer = MyApplication.mInstanceDB.customerDao.getAll()
}
Export and Import use this library
implementation 'com.ajts.androidmads.sqliteimpex:library:1.0.0'
Github link

RealmConfiguration.Builder with DocumentFile

I'm struggling with storing a realm db on the sd card. The point is that I have to use DocumentFile instead of simple File object to have write access. Another words:
Uri uri = getUriInstanceToSaveDB(); // my inner method
new File(uri.getPath()).canWrite() == false
DocumentFile.fromTreeUri(getActivity(), uri).canWrite() == true
Therefore I can't just store data using RealmConfiguration.Builder() (cause it uses File object as storing mechanism). Of course, I've also tried to use simple String there instead of File object - no result.
Real doesn't support DocumentFile at this point in time, so I'm afraid you are currently out of luck unless you can find a way to map a DocumentFile to a local File reference.
Also one of the problems with DocumentFile is that it might reference a file that doesn't exist locally, which would prevent Realm from using it. So it is unclear if Realm could ever support this.

How for Android to load / read local Realm file?

I have a Test.realm file inside the asset folder. But I don't know how to load the Realm file inside an activity. I have tried this
RealmConfiguration config = new RealmConfiguration.Builder(this)
.name("Test.realm").build();
Realm realm = Realm.getInstance(config);
RealmResults<RealmTestClass0> results = realm.where(RealmTestClass0.class)
.findAll();
But it was crashing on setting config line (second line). From the log it says
Caused by: io.realm.exceptions.RealmMigrationNeededException: RealmMigration must be provided
So how is the right way to load Realm file?
Thanks in advance.
Realm.getInstance() is correct method for getting Realm's instance.
It looks that you change some of your Realm objects or add new one. Realm detected it and tells that you have new data schema and have to migrate (RealmMigrationNeededException).
If you are only developing now - delete application and install it again. It should start to work fine. If your application is in production - you should write some migration code (https://realm.io/docs/java/latest/#migrations)

Where can I find the default Realm Database file

I started working on the logic for my migration, using this code:
https://github.com/realm/realm-java/blob/master/examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/MigrationExampleActivity.java
And after writing the code, I get an error at this line:
String path3 = MigrationClass.copyBundledRealmFile(this, this.getResources().openRawResource(R.raw.default1), "default1");
It can't find the R.raw.default1 file, because until now, I used the default Realm like this:
Realm realm = Realm.getInstance(context);
My question is where can I get the file path for this realm file?
Realm just uses the Context to call getFilesDir() and the default Realm is called default.realm. So in your case you should use:
String realmPath = new File(context.getFilesDir(), "default.realm").getAbsolutePath();
Realm.migrateRealmAtPath(realmPath, new CustomMigration());
You can get the path of your realm file by calling the "getPath()" method:
Here an Example:
realm.getPath()

Categories

Resources