Firebase RealtimeDatabase retrieve snapshot object exception - android

This is my model class
#Parcel
data class ClientModel(
var name: String? = "",
var phone: String? = "",
var princpalAddresse: String? = "",
var homeAddresse: String? = "",
var travailleAddresse: String? = "",
var email: String? = "",
var userToken: String? = "",
var principalAddresseCoords: Pair<Double, Double>? = null,
var homeAddresseCoords: Pair<Double, Double>?= null,
var workAddresseCoords: Pair<Double, Double>? = null,
)
My proGuard file keep the class :
-keep class com.olivier.oplivre.models.ClientModel
But! when I try to get the snapshot with a singleValueEventListener I got exception because of the Pair<Double,Double> variables
val utilisationInfo = snapshot.getValue(ClientModel::class.java) //todo CRASH
Exception :
com.google.firebase.database.DatabaseException: Class kotlin.Pair does not define a no-argument constructor. If you are using ProGuard, make sure these constructors are not stripped.
Database Structure :

I think firebase Realtime database treat your principalAddresseCoords as a list of long so in your ClientModel change the value of principalAddresseCoords to emptyList() and the type List

As #Sami Shorman said , firebase took my Pair instance and transform it but not as list, as Hashmap<,> ! so I changed my class model like that :
var principalAddresseCoords: HashMap<String,Double>? = null,
var homeAddresseCoords: HashMap<String,Double >? = null,
var workAddresseCoords: HashMap<String,Double >? = null,
To put the data as Hashmap I just had to do :
clientModel.workAddresseCoords = HashMap<String,Double>().apply {
put("lat",lat)
put("long",long)
}

Related

How to create a pdf from data in android?

I'm building a resume builder. I've made everything else that I'm not able to write the resume data to a pdf and give it to the use.
I have a class user and an object constants that contains data.
data class User(
var id : String? = null,
var email : String? = null,
var profileHeadline : String? = "",
var profileSummary : String? = "",
var profilePhoto : String? = "",
var personalInfo: PersonalInfo? = PersonalInfo(),
var education: MutableList<Education>? = null,
var experience: MutableList<Experience>? = null,
var skills : MutableList<Skills>? = null,
var languages: MutableList<Languages>? = null,
var interest : MutableList<Interest>? = null,
var awardAndAchievements: MutableList<AwardAndAchievements>? = null,
var licenceAndCertification: MutableList<LicenceAndCertification>? = null,
var projects : MutableList<Projects>? = null,
var publications: MutableList<Publications>? = null,
var patents : MutableList<Patents>? = null,
var volunteerExperience : MutableList<VolunteerExperience>? = null,
var recommendations: MutableList<Recommendations>? = null
) : Parcelable
I want to create a well structured pdf with the data. A well structured pdf means Think about your own resume.
I know some about canvas and pdfdocument in kotlin - Android and also about creating pdfs with activities.
But i don't know which approach should I use and how to make it happen.
Please help!
It will be so nice of you if you can give me an example by creating some resume pdf.

Realm migration on Android - add new table

Is it possible to add a new table without specifying every field "manually" like this:
schema.create("LoyaltyActivity")
.addField("id", String::class.java, FieldAttribute.PRIMARY_KEY)
.addField("source", String::class.java)
.addField("date", String::class.java)
.addField("points", String::class.java)
.addField("reference", String::class.java
Realm class looks like this:
open class LoyaltyActivity(
#PrimaryKey var id: String? = null,
var source: String? = null,
var date: String? = null,
var points: String? = null,
var reference: String? = null
) : RealmObject()
On iOS, it is possible with method provided in SDK: migration.create(typeName: String, value: <Any>)

Add Map to JSON Object for Saving to Firestore

Can't see how to do this and getting rather confused!
I am saving 'site' objects to firestore, but I want to add a list of users associated to each site.
I have added a Map of users to my JSON object as below:
#IgnoreExtraProperties
data class SiteObject(
var siteReference: String,
var siteAddress: String,
var sitePhoneNumber: String,
var siteEmail: String,
var invoiceAddress: String,
var invoicePhoneNumber: String,
var invoiceEmail: String,
var website: String,
var companyNumber: String,
var vatNumber: String,
var recentProjectsText: String,
//not set up yet:
var sitePriority: Boolean,
var siteRating: Int,
var plusCode: String,
var users: Map<String, Boolean>?, // This is the map I have added
#ServerTimestamp
var dateCreatedTimestamp: Date?,
#ServerTimestamp
var dateEditedTimestamp: Date?,
#Exclude
var siteID: String?
) : Serializable {
private constructor() : this(
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
false,
1,
"",
null,
null,
null,
null
)
override fun toString(): String {
return "$siteReference"
}
}
And in my respository I am trying to add the current user to this list of users as below:
// save sites to firebase
fun saveSite(site: SiteObject) {
site.users?.plus(Pair(firebaseUser?.uid.toString(), true)) // This is where I expected the user Id to be added to Map of users..
val documentReference = firestore.collection("sites").document().set(site)
.addOnCompleteListener {
if(it.isSuccessful){
Log.d(TAG, "${site.toString()} saved")
lastOperationText.value = "New site, ${site.siteReference}, saved!"
} else {
Log.d(TAG, "${site.toString()} saved")
lastOperationText.value = "Save new site failed"
}
}
}
However, I still seeing null for users in the Firestore console.
Your code never gives an initial value to users. It starts off null. Since it doesn't get assigned a value, this code will not make a change to it, because it's first checking to see if users is null using the ?. operator:
site.users?.plus(Pair(firebaseUser?.uid.toString(), true))
You will need to assign it an initial value before trying to modify it. It should probably never be null and just start empty.
var users = HashMap<String, Boolean>()
For completeness, below is my updated data class. This initialises the values when it is created and also includes #Exclude #set:Exclude #get:Exclude on siteID to prevent this being saved to Firestore (used to store generated id when read from Firestore):
#IgnoreExtraProperties
data class SiteObject(
var siteReference: String = "",
var siteAddress: String = "",
var sitePhoneNumber: String = "",
var siteEmail: String = "",
var invoiceAddress: String = "",
var invoicePhoneNumber: String = "",
var invoiceEmail: String = "",
var website: String = "",
var companyNumber: String = "",
var vatNumber: String = "",
var recentProjectsText: String = "",
var sitePriority: Boolean = false,
var siteRating: Int = 1,
var plusCode: String = "",
var users: HashMap<String, Boolean> = hashMapOf(),
#ServerTimestamp
var dateCreatedTimestamp: Date? = null,
#ServerTimestamp
var dateEditedTimestamp: Date? = null,
#Exclude #set:Exclude #get:Exclude
var siteID: String = ""
) : Serializable {
override fun toString(): String {
return "$siteReference, $siteAddress, $siteRating, $siteID"
}
fun siteDetailsText(): String {
var siteDetailsText = siteAddress
if (sitePhoneNumber.isNotEmpty()) siteDetailsText.plus("\n\n$sitePhoneNumber")
if (website.isNotEmpty()) siteDetailsText.plus("\n\n$website")
return siteDetailsText
}
fun invoiceDetailsText(): String {
var invoiceDetailsText = invoiceAddress
if (invoicePhoneNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$invoicePhoneNumber")
if (companyNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$companyNumber")
if (vatNumber.isNotEmpty()) invoiceDetailsText.plus("\n\n$vatNumber")
return invoiceDetailsText
}
}

Parse Mutable Live Data to Array in Kotlin

There is a mutableLiveData Holding 2 array "deal" and "category" I need to parse this both in different adapters.
Is there a way I can convert 1 mutable live data to 2 array and then parse them to two different adapters
Suppose There is MutableVariable Name se
private lateinit var mHomePojo: MutableLiveData<List<HomePojo>>
having parse Json as below
{
"status": 0,
"response": "success",
"category": [
{
"categoryName": "demo",
"categoryDesc": "demo"
},
{
"categoryName": "demo1",
"categoryDesc": "demo"
}
],
"deal": [
{
"dealImg": "https://aiotechnology.in/Aditechweb/upload/153102117.jpg",
"dealDesc": "gd",
"dealStartDate": "2019-10-18",
"dealEndDate": "2019-10-19"
}
]
}
Is there any way to parse private lateinit var mHomePojo: MutableLiveData<List<HomePojo>> to lateinit var mDealModel: MutableLiveData<List<DealModel>> and
lateinit var mCategoryModel: MutableLiveData<List<CategoryModel>>
I am new to MVVM please help
I think Transformations might be able to help you separate your home live data to two separate livedata object with specified properties. below is piece of code for this. (NOTE : not used lateinit var for example)
private val homeLiveData: LiveData<HomePojo> = MutableLiveData<HomePojo>()
//Category Live data
private val categoryPojo = Transformations.map(homeLiveData) {
it.category
}
//Deal live data
private val dealPojo = Transformations.map(homeLiveData) {
it.deal
}
data class HomePojo(
/*-- Other fields --*/
val category: List<CategoryPojo>? = null,
val deal: List<DealPojo>? = null)
data class CategoryPojo(
val categoryName: String? = null,
val categoryDesc: String? = null)
data class DealPojo(
val dealImg: String? = null,
val dealDesc: String? = null,
val dealStartDate: String? = null,
val dealEndDate: String? = null)

Kotlin parse Object array using JSONParser from Gson

I have these classes written in kotlin, Location, and the rest is in the Application.kt
#RealmClass
open class Location(
#PrimaryKey
#SerializedName("id")
var id: Int = 0,
#SerializedName("city_name")
var city_name: String? = null,
#SerializedName("elevation")
var elevation: Int = 0,
#SerializedName("state_code")
var state_code: String? = null,
#SerializedName("state_name")
var state_name: String? = null,
#SerializedName("country_code")
var country_code: String? = null,
#SerializedName("country_name")
var country_name: String? = null
):RealmObject()
and the rest:
private fun loadStuff() {
val inputStream = this.resources.openRawResource(R.raw.city_json)
val jsonReader = JsonReader(InputStreamReader(inputStream, "UTF-8"))
val gson = Gson()
Realm.getDefaultInstance().executeTransactionAsync(Realm.Transaction { realm ->
val weatherList = gson.fromJson<List<Location>>(jsonReader , Array<Location>::class.java).toList()
//realm.insertOrUpdate(location)
jsonReader.endArray()
jsonReader.close()
}, Realm.Transaction.OnSuccess {
Log.d("TAG", "Success")
})
}
and I keep getting exception:
com.example.android.sunshine.data.Location[] cannot be cast to java.lang.Iterable
what am I doing wrong ?
the object looks like this:
[
{
"id":3040051,
"city_name":"les Escaldes",
"elevation":0,
"state_code":"08",
"state_name":"ParrĂ²quia d'Escaldes-Engordany",
"country_code":"AD",
"country_name":"Andorra"
},
{
"id":3041563,
"city_name":"Andorra la Vella",
"elevation":0,
"state_code":"07",
"state_name":"ParrĂ²quia d'Andorra la Vella",
"country_code":"AD",
"country_name":"Andorra"
}
]
This:
List<Location>
Is a List of Location. List implements Iterable.
This:
Array<Location>
is an Array of Location. Array does not implement Iterable.
The differences are bigger than that, but his is the one your error is for.
It was enough to swap List with Array and remove .toList() and it worked like magic

Categories

Resources