I am building an simple chat with firebase. my firebase structure
chats
PSTQL2W3qqV8GGu7bjXhYZKrXh92&sCv3CCXOLnYrb38db4V41PoArxD2
conversatins
87483
sender: "sCv3CCXOLnYrb38db4V41PoArxD2"
time: "3:08"
title: "hey!"
type: "text"
348843
sender: "sCv3CCXOLnYrb38db4V41PoArxD2"
time: "4:33"
title: "HI!"
type: "text"
last_message: "Hey!"
last_time: "23:23 am"
My Model
data class Message(
var conversations: ArrayList<Conversations> = ArrayList(),
val last_message: String = "",
val last_time: String = "") {
data class Conversations(
var sender: String = "",
var time: String = "",
var title: String = "",
var type: String = "")
}
I want to retrieve array object in conversations, I've tried
val listenToChild = object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
val chat = p0.getValue(Message::class.java)
Log.d("message",${chat?.conversations?.size}"
}
}
mMessageReference.child(keySnapshot.toString()).addValueEventListener(listenToChild)
I get result size 0. Is there any problems with my model?
Related
val data = FirebaseDatabase.getInstance()
val refB = data.getReference("branches")
refB.addValueEventListener(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
for(n in snapshot.children){
val branch = n.getValue(Branch::class.java)
listB.add(branch!!)
}
}
override fun onCancelled(error: DatabaseError) {
}
})
my class Branch
class Branch(var id: String?, var nStudents: String, var nTeachers: String, var name:String) {
}
I can't read the data one sentence means Object,
But I can read the data each value by itself.
I see a couple of problems with your custom class:
As Frank pointed out in a comment, nStudents and nTeachers won't map correctly due to case sensitivity.
It seems like your class has no empty constructor (or default arguments) which is required for the database to properly deserialize the data, as detailed in the Firebase docs.
The data types don't seem to match: You've declared nstudents and nteachers as String, but I see it as numbers in your database, so you should probably use an Int or Long.
With all that said, your updated class should look like this:
class Branch(
var id: String? = null,
var nstudents: Int = 0,
var nteachers: Int = 0,
var name: String = ""
) {
// ...
}
And if the only purpose of this class is to hold data, you can turn it into a data class:
data class Branch(
var id: String? = null,
var nstudents: Int = 0,
var nteachers: Int = 0,
var name: String = ""
)
I'm getting this error when trying to get a child node trainer_profile from Firebase that contains a list my_pokemon.
W/ClassMapper: No setter/field for my_pokemon found on class com.tapmaxalf.poketest.model.TrainerProfile
My Firebase DB:
My valueEventListener looks like this:
private fun getTrainerProfile(userId: String) {
firebaseDatabase.child("trainer_profile").child(userId)
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
snapshot.getValue(TrainerProfile::class.java).let { trainerProfile ->
if (trainerProfile != null) {
viewModelScope.launch (Dispatchers.IO){
_state.value = state.value.copy(trainerProfile = trainerProfile)
userDao.updateTrainerProfile(trainerProfile, userId)
canProfileBeAdded(trainerProfile.timeSentToDatabase)
addProfileCountdown(trainerProfile.timeSentToDatabase)
}
}
}
}
override fun onCancelled(error: DatabaseError) {
updateError(AuthErrors.GenericError.messageResource)
}
})
}
And my TrainerProfile
data class TrainerProfile(
val trainerName: String = "",
val location: String = "",
val trainerLevel: String = "",
val trainerCode: String = "",
val profileImage: String = "",
val gifts: Boolean = false,
val trade: Boolean = false,
val raid: Boolean = false,
val timeSentToDatabase: Long = 0,
val myPokemon: List<MyPokemon> = emptyList()
)
You are getting the following warning:
W/ClassMapper: No setter/field for my_pokemon found on class com.tapmaxalf.poketest.model.TrainerProfile
Because the list in your database is called my_pokemon, while in the database is called myPokemon, which is not correct. Both names must match. The simplest solution to this problem would be to use an annotations before your field like this:
#get:PropertyName("my_pokemon")
#set:PropertyName("my_pokemon")
#PropertyName("my_pokemon")
val myPokemon: List<MyPokemon> = emptyList()
This is my code for getting data from Firebase
database?.getReference("tours")?.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
Log.d("FirstFragment", "start")
val list = ArrayList<Tours>()
if (snapshot.exists()) {
[enter image description here][1] snapshot.children.forEach { it->
var tour = it.getValue(Tours::class.java) //error is here!!
tour?.id = it.key
tour?.let {
list.add(tour)
}
}
Log.d("FirstFragment", list[0].companyName.toString())
adapter?.setTours(list)
}
}
override fun onCancelled(error: DatabaseError) {
Log.d("FirstFragment", error.toString())
}
})
It is an Tours class, and i get error herer //var tour = it.getValue(Tours::class.java)//
package com.example.mainapplication
import java.io.Serializable
class Tours : Serializable{
var id: String? = null
var tourName: String?=null
var description: String ?= null
var imageId: String?=null
var dateAndTime: String?=null
var companyName: String?= null
var price: Long?=null
var regPeople: Int? = null
var phone: String?=null
var numbersOfPeople: Int?=null
var bookedId: String? = null
}
1 [This is an error occurred]
What should i do to fix it?
This is my Firebase for Tours
I am new to kotlin. And so I need help. Thank. I have a date class Users ().
data class Users(
var ID: String = "",
var Email: String = "")
Date class I fill through initUser
lateinit var AUTH: FirebaseAuth
lateinit var UID:String
lateinit var REF_DATABASE_ROOT: DatabaseReference
lateinit var USER:Users
const val NODE_USERS = "User"
const val CHILD_ID = "ID"
const val CHILD_EMAIL = "Email"
fun initFirebase() {
AUTH = FirebaseAuth.getInstance()
REF_DATABASE_ROOT = FirebaseDatabase.getInstance().reference
UID = AUTH.currentUser?.uid.toString()
USER = Users()
}
fun initUser() {
REF_DATABASE_ROOT.child(NODE_USERS).child(UID)
.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(p0: DataSnapshot) {
USER = p0.getValue(Users::class.java) ?:Users()
}
})
}
But when I want to display the user's email from the database via text. I get the void
initFirebase()
initUser()
textViewMain.text = USER.Email.toString()
Here is new JSON:
{
"User" : {
"ZDLM84F7zYWobbhUBxsQfekrPvI3" : {
"Email" : "evgeniy1900#gmail.com",
"ID" : "ZDLM84F7zYWobbhUBxsQfekrPvI3"
}
}
}
But again I get nothing in text
UPDATE:
Ok, I wrote it all over again. And now I have:
Data class User
import com.google.firebase.database.PropertyName
data class User (
#PropertyName("id")
var id: String = "",
#PropertyName("email")
var email: String = ""
)
initUser looks like that
lateinit var AUTH: FirebaseAuth
lateinit var UID:String
lateinit var REF_DATABASE_ROOT: DatabaseReference
lateinit var USER:User
const val NODE_USERS = "users"
const val CHILD_ID = "id"
const val CHILD_EMAIL = "email"
fun initFirebase() {
AUTH = FirebaseAuth.getInstance()
REF_DATABASE_ROOT = FirebaseDatabase.getInstance().reference
UID = AUTH.currentUser?.uid.toString()
USER = User()
}
fun initUser() {
REF_DATABASE_ROOT.child(NODE_USERS).child(UID)
.addListenerForSingleValueEvent(AppValueEventListener{
USER = it.getValue(User::class.java) ?:User()
})
}
and also I decided to shorten the code using AppValueEventListener
here he is
class AppValueEventListener (val onSuccess:(DataSnapshot) -> Unit) :ValueEventListener{
override fun onCancelled(p0: DatabaseError) {}
override fun onDataChange(p0: DataSnapshot) { onSuccess(p0) }
}
and this is json
{
"users" : {
"ZDLM84F7zYWobbhUBxsQfekrPvI3" : {
"email" : "evgeniy1900#gmail.com",
"id" : "ZDLM84F7zYWobbhUBxsQfekrPvI3"
}
}
}
As you can see, I added #PropertyName ("email"). But at the same time, I still do not get anything on the screen.
enter image description here
Update again:
I used a breakpoint in order to understand if I am getting something from the database or not. As you can see in the screenshots, there is a receipt, but there is no record in the User model. Help me please.
Your JSON contains this property for a user:
"EMAIL" : "evgeniy1900#gmail.com",
Which you likely want to map to this in your code:
var Email: String = ""
But Firebase uses JavaBean naming conventions when mapping, which means that your JSON actually maps to a property in Kotlin as:
var eMAIL: String = ""
If you want to maintain both the name on JSON and in Kotlin, you can use a PropertyName annotation:
#PropertyName("EMAIL")
var Email: String = ""
Also see: Firebase #PropertyName doesn't work and probably others from this search.
I have a chat done in firestore and obviously I need to get the messages from each chat room but the messages never come sorted by the date always by the id of the user.
In the beginning I did without using #ServerTimestamp and was generating the date on the Android device itself but at the suggestion right here in Stackoverflow I changed to the firestore itself to generate the date, according to the suggestion that would solve but it does not work. It's coming in an order I did not order, it's coming in the order of the user id, lateinit var from_id: String
class Message {
lateinit var content: String
#ServerTimestamp
var timestamp: Timestamp ?= null
lateinit var from_id: String
lateinit var type: String
constructor(content: String, timestamp : Timestamp, from_id: String, type: String) {
this.content = content
this.from_id = from_id
this.timestamp = timestamp
this.type = type
}
constructor(content: String, from_id: String, type: String) {
this.content = content
this.from_id = from_id
this.type = type
}
constructor()
}
ControllerChat
...
override fun sendMessageText(idChatRoom: String, from_id: String, text: String, listenerSendMessage: ListenerSendChatMessage) {
var message = Message(text, from_id, Message.TEXT)
chatChannelsCollectionRef
.document(idChatRoom)
.collection(MESSAGES)
.add(message).addOnSuccessListener {
listenerSendMessage.onSendChatMessageSucess()
}.addOnFailureListener {
listenerSendMessage.errorSendChatMessage(it)
}
}
...
override fun getAllMessageFromChatRoom(idChatRoom: String, listenerGetAllChatMessage: ListenerGetAllChatMessage) {
Log.d(TAG, "ChatController - getAllMessageFromChatRoom")
listenerSnapshotAllMessageFromChatRoom = chatChannelsCollectionRef
.document(idChatRoom)
.collection(MESSAGES)
.orderBy("timestamp", Query.Direction.ASCENDING)
.addSnapshotListener(object : EventListener<QuerySnapshot> {
override fun onEvent(querySnapshot: QuerySnapshot?, p1: FirebaseFirestoreException?) {
querySnapshot?.let { qSnap ->
if (!qSnap.isEmpty) {
var documentChange = qSnap.documentChanges
for (doc in documentChange) {
var message = doc.document.toObject(Message::class.java)
Log.i(TAG, "Document Change: " + message.content)
listenerGetAllChatMessage.onChatMessage(message)
}
}
}
}
})
}