Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save and retrieve Latitude and Longitude from a Location object in Room Database

I'm using AndroidX Room component for a small offline database in my app. I want to be able to save the Location (latitude and longitude) of the user to the database and use it later. How to do it and what is the best practices ?

I've never done that before and couldn't find any help on the web.

This is how I'm actually doing it (and obviously the wrong way) :

@ColumnInfo(name = "session_location")
var sessionLocation: Location

I get an error Cannot figure out how to save this field into database

like image 806
Lyam.D Avatar asked Oct 15 '25 18:10

Lyam.D


2 Answers

What is your Location class? Is it android.location.Location or is it some data class that you defined?

In any case I would have used @Embedded POJO classes instead of TypeConverters as others recommend.

If Location is a class that you already defined then just add @Embedded annotation on top of your sessionLocation

@Embedded
@ColumnInfo(name = "session_location")
var sessionLocation: Location

Else if Location is the android.location.Location then you don't need to store all the information in that class. You must need basic ones which are lat & long.

I would have just created a class Location and store those basic information and add it as @Embedded. Something like below

class Location {
    var latitude: Double = 0
    var longitude: Double = 0
}

class User {
    @Embedded
    @ColumnInfo(name = "session_location")
    var sessionLocation: Location
}

As others suggested TypeConverter is a solution but there is no need serialize/deserialize a POJO when you can simply save it directly.

like image 69
musooff Avatar answered Oct 17 '25 07:10

musooff


You should define your own converter for types that are not supported by Room. Basically SQLite supports only primitive types as column fields. For each complex data type you have to define a custom converter, since Room doesn't know how to serialize your complex type in database columns. To do so, you need to create a converter which is responsible to convert your complex structured type in primitive fields:

E.g. (from android documentation)

class Converters {
    @TypeConverter
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time?.toLong()
    }
}

In your case the simpliest way would be using GSON to serialize your object as a JSON string (when you are writing to your database - Room supports string), then parsing the string from the database to your Location object when you read from the database

In your case I would do something like:

class LocationConverter {
   @TypeConverter
    fun toLocation(locationString: String?): Location? {
        return try {
            Gson().fromJson(locationString, Location::class.java)
        } catch (e: Exception) {
            null
        }
    }

    @TypeConverter
    fun toLocationString(location: Location?): String? {
        return Gson().toJson(location)
    }
}

Once your done with the converter, annotate your database with the LocationConverter you've just defined and you're done!

@TypeConverters(LocationConverter::class)
abstract class YourDatabase : RoomDatabase() {
  // your code
}
like image 22
Nicola Gallazzi Avatar answered Oct 17 '25 08:10

Nicola Gallazzi