i tried to split a string to two variable, one is string and one is Long. it work, when i Log it i can see it and i can insert it to Room Database, but i don't know why "sometime" i get this error.
the string like this
m8fw5sMdAcaX4Ezv7vzImeRAjkq2_1635234951781
java.lang.NumberFormatException: For input string: "m8fw5sMdAcaX4Ezv7vzImeRAjkq2"
at java.lang.Long.parseLong(Long.java:594)
at java.lang.Long.parseLong(Long.java:636)
at com.animals.snowy.MainActivity$insertMessage$1$messageListener$1.onChildAdded(MainActivity.kt:88)
my Model
#IgnoreExtraProperties
#Entity(tableName = "message_table")
data class MessageModel(
#NonNull
#PrimaryKey
var messageId: String = "",
var messageType: String? = null,
var messageTimestamp: Long? = null,
var messageData: String? = null,
var messageSenderId: String? = null,
var roomId: String = "",
var isSeen: Boolean = false,
var uploadSuccess : Boolean = false
) : Serializable {
}
and this is my code , i want to get new message of friends, so i get list friend from Room Database and use for loop to get roomId(name of child container message of me and my friend).
private fun insertMessage() {
viewModel.readRoomIdFriendsDAO().observe(this, { listRoomId ->
if (listRoomId != null && listRoomId.isNotEmpty()) {
for (item in listRoomId) {
val messageListener = object : ChildEventListener {
override fun onChildAdded(snapshot:DataSnapshot,previousChildName: String?) {
val messageModel: MessageModel? =
snapshot.getValue(MessageModel::class.java)
if (messageModel != null) {
messageModel.messageId = snapshot.key.toString().trim()
messageModel.roomId = item
messageModel.uploadSuccess = true
val listTemp = messageModel.messageId.split("_")
messageModel.messageSenderId = listTemp[0]
messageModel.messageTimestamp = listTemp[1].trim().toLong()
Log.e(TAG,"senderId: ${messageModel.messageSenderId}")
Log.e(TAG,"timestamp: ${messageModel.messageTimestamp}")
// messageViewModel.insertMessageDAO(messageModel)
}
}
override fun onChildChanged(
snapshot: DataSnapshot,
previousChildName: String?
) {
}
override fun onChildRemoved(snapshot: DataSnapshot) {
}
override fun onChildMoved(
snapshot: DataSnapshot,
previousChildName: String?
) {
TODO("Not yet implemented")
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
}
messageRef
.child(item)
.addChildEventListener(messageListener)
}
}
})
}
java.lang.NumberFormatException is thrown whenever the compiler tries to type cast an invalid input to number.
For example:
String validInputToCast = "123456789";
Long validInputToCast = validInputToCast.toLong(); // this casting will succeed.
String invalidInputToCast = "abce124";
Long invalidCastedInput = inputToCast.toLong(); // compiler will throw number exception on this line.
Try debugging the line below and hopefully you will find the error.
messageModel.messageTimestamp = listTemp[1].trim().toLong()
Related
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()
I am using Firebase Database to populate a recyclerview. and i'm facing problem in fetching data.
the error
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.Long to type com.massino.pfeadelramzi.models.Meuble
my code:
var mdatabase : DatabaseReference?=null
var listMeubles = mutableListOf<Meuble>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_liste_meuble3_d)
mdatabase = FirebaseDatabase.getInstance().reference.child("Bureau")
mdatabase!!.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (sna: DataSnapshot in snapshot.children){
val lis: Meuble? = sna.getValue(Meuble::class.java) //THE PROBLEME IS HERE
listMeubles.add(lis!!)
}
mon_recycler.setHasFixedSize(true)
mon_recycler.layoutManager = LinearLayoutManager(this#ListeMeuble3DActivity)
mon_recycler.adapter = MeubleAdapter(listMeubles.toTypedArray()){}
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
My data Class Meuble:
data class Meuble(val imageResource: Int, val nom: String, val prix: Int,val stock:Int)
my Firebase data (now i'm just trying to find a solution so i created just one child
Code to add data to Firebase
button4.setOnClickListener{
var nomUI = spinner.selectedItem.toString()
var prixUI = textView2.text.toString().toInt()
var stockUI= textView3.text.toString().toInt()
var databaseref = firebaseDatabase.getReference(nomUI)
if ( nomUI != null || !TextUtils.isEmpty(prixUI.toString()) || !TextUtils.isEmpty(stockUI.toString())){
var meuble = Meuble(R.drawable.fauteuille2,nomUI,prixUI,stockUI)
databaseref.setValue(meuble)
}else {
Toast.makeText(this,"Remplissez la case manquante",Toast.LENGTH_LONG).show()
}
}
Please help to solve this exception.
As Ticherhaz commented: since you only have the properties for one child nodes under /Bureau, you should use loop over the child nodes in onDataChange.
Right now your loop means that sna points to each individual property, and that's why it fails. There is (for example) no way to parse the value of prix into a `` object.
The code for when you have a single child is:
mdatabase = FirebaseDatabase.getInstance().reference.child("Bureau")
mdatabase!!.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val lis: Meuble? = snapshot.getValue(Meuble::class.java)
listMeubles.add(lis!!)
mon_recycler.setHasFixedSize(true)
mon_recycler.layoutManager = LinearLayoutManager(this#ListeMeuble3DActivity)
mon_recycler.adapter = MeubleAdapter(listMeubles.toTypedArray()){}
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
Error Handling :
So to handle my error:
i had to add a Default Value to each parametre in the constructor of my Data class :
data class Meuble(val imageResource: Int = -1, val nom: String="", val prix: Int=-1,val stock:Int=-1)
I am trying to display the current username from the Realtime Database but whenever I am running my code it gives me null. Here is my code:
val reference =FirebaseDatabase.getInstance().reference
currentUserUid = auth?.currentUser?.uid
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val username =
dataSnapshot.child(auth!!.currentUser!!.uid).child("Users")
.child("username")
.getValue(String::class.java)
if (username == null)
fragmentView?.name?.setText("Hello, Anonymous")
else
fragmentView?.name?.setText("Hello, $username")
}
override fun onCancelled(databaseError: DatabaseError) {}
})
This is my content to code
package com.example.videoapp.Model
data class ContentDTO(var explain : String? = null,
var imageUrl : String? = null,
var uid : String? = null,
var userId : String? = null,
var username : String? = null,
var timestamp : Long? = null,
var favoriteCount : Int = 0,
var favorites : MutableMap<String,Boolean> = HashMap()){
data class Comment(var uid : String? = null,
var userId : String? = null,
var comment : String? = null,
var timestamp : Long? = null)
}
This is my code where I can upload the pics. I have taken a little bit of help from the internet to do that. I am trying to display the name here but it's returning nothing
val storageRef = storage?.reference?.child("images")?.child(imageFileName)
storageRef?.putFile(photoUri!!)?.continueWithTask { task: com.google.android.gms.tasks.Task<com.google.firebase.storage.UploadTask.TaskSnapshot> ->
return#continueWithTask storageRef.downloadUrl
}?.addOnSuccessListener { uri ->
val contentDTO = com.example.videoapp.Model.ContentDTO()
//Insert downloadUrl of image
contentDTO.imageUrl = uri.toString()
//Insert uid of user
contentDTO.uid = auth?.currentUser?.uid
//Insert userId
contentDTO.userId = auth?.currentUser?.email
contentDTO.username = auth?.currentUser?.displayName
//Insert explain of content
contentDTO.explain = addphoto_edit_explain2.text.toString()
//Insert timestamp
contentDTO.timestamp = System.currentTimeMillis()
firestore?.collection("images")?.document()?.set(contentDTO)
setResult(android.app.Activity.RESULT_OK)
finish()
}
As I see in your database, the key of all User objects that are stored within Users node, are not added using the UID that comes from the authentication process, those key as generated with the push() method, because all of them start with -.
The most appropriate solution might be to change those keys and get then the data accordingly. To add a User object, you should some lines of code that looks like this:
val uid = FirebaseAuth.getInstance().currentUser!!.uid
val rootRef = FirebaseDatabase.getInstance().reference
val usersRef = rootRef.child("Users")
usersRef.child(uid).setValue(user)
To display the name of the logged-in users, simply use the following lines of code:
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val name = dataSnapshot.child("name").getValue(String::class.java)
Log.d("TAG", name)
//Do what you need to do with the value of name
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("TAG", databaseError.getMessage()) //Don't ignore errors!
}
}
usersRef.child(uid).addListenerForSingleValueEvent(valueEventListener)
Try this code instead :
val reference = FirebaseDatabase.getInstance().getReference("Users").child(auth?.currentUser?.uid)
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for(snapshot in dataSnapShot.children){
val username =
snapshot.child("username").value.toString()
if (username == null)
fragmentView?.name?.setText("Hello, Anonymous")
else
fragmentView?.name?.setText("Hello, $username")
}
}
override fun onCancelled(databaseError: DatabaseError) {}
})
I have been developing a chatting app in Android using Kotlin and Firebase. Registering, searching and sending message to a user, all of this has been successful. But I'm unable to generate a chatlist which is a list of the recent chats of the user. The user can tap on it to access that particular chat, just like any other chatting app.
The user is stored in a User model and the data is registered in the database in that same format.
I am able to display the profile picture of the user using the addValueEventListener method but when the similar method is invoked for the chatlist, it throws an error -
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
This is the code where the error occurs -
val user = snapshot.getValue<User>(User::class.java!!)
present in the function - chatList()
Database view
MainActivityChat code >
class MainActivityChat : Fragment() {
lateinit var profile_image: CircleImageView
lateinit var firebaseUser: FirebaseUser
lateinit var reference: DatabaseReference
lateinit var referenceusers: DatabaseReference
lateinit var referenceuserschats: DatabaseReference
lateinit var referencechatlist: DatabaseReference
var root: View? = null
lateinit var auth: FirebaseAuth
lateinit var fragment: Fragment
var recyclerView: RecyclerView? = null
var userAdapter: UserAdapter? = null
var mUsers: MutableList<User>? = null
var fuser: FirebaseUser?=null
private var usersList: MutableList<Chatlist>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
root = inflater.inflate(R.layout.activity_mainchat, container, false)
setHasOptionsMenu(true)
firebaseUser = FirebaseAuth.getInstance().currentUser!!
val uid = firebaseUser.uid
val floatingActionButton = root!!.findViewById(R.id.searchPerson) as FloatingActionButton
floatingActionButton.setOnClickListener {
val intent = Intent(activity, SearchActivity::class.java)
startActivity(intent)
}
fuser = FirebaseAuth.getInstance().currentUser!!
usersList = ArrayList()
reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
referencechatlist = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
profile_image = root!!.findViewById(R.id.profile_image)
firebaseUser = FirebaseAuth.getInstance().currentUser!!
FirebaseDatabase.getInstance().reference.child("Users").child(uid)
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val user = dataSnapshot.getValue(User::class.java)
// usernamedisplay.text = user!!.username
if (user!!.profileImageUrl == "default") {
profile_image.setImageResource(R.mipmap.ic_launcher)
Log.d(ProfileFragment.TAG, "No image retrieved/found")
} else {
//change this
context?.let { Glide.with(it).load(user.profileImageUrl).into(profile_image) }!!
Log.d(ProfileFragment.TAG, "Image set")
}
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
reference = FirebaseDatabase.getInstance().getReference("Chats")
reference.addValueEventListener(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onDataChange(dataSnapshot: DataSnapshot) {
var unread = 0
for (snapshot in dataSnapshot.children) {
val chat = snapshot.getValue<Chat>(Chat::class.java!!)
if (chat!!.receiver == firebaseUser!!.uid && !chat!!.isIsseen!!) {
unread++
}
}
reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(fuser!!.uid)
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
usersList!!.clear()
for (snapshot in dataSnapshot.children) {
val chatlist = snapshot.getValue<Chatlist>(Chatlist::class.java!!)
usersList!!.add(chatlist!!)
}
chatList()
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
}
})
updateToken(FirebaseInstanceId.getInstance().token)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view!!.findViewById(R.id.recycler_viewmain)
recyclerView!!.setHasFixedSize(true)
recyclerView!!.layoutManager = LinearLayoutManager(context)
}
private fun updateToken(token: String?) {
val reference = FirebaseDatabase.getInstance().getReference("Tokens")
val token1 = Token(token!!)
reference.child(fuser!!.uid).setValue(token1)
}
private fun chatList() {
mUsers = ArrayList()
reference = FirebaseDatabase.getInstance().getReference("Users")
reference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
mUsers!!.clear()
for (snapshot in dataSnapshot.children) {
**val user = snapshot.getValue<User>(User::class.java!!)**
for (chatlist in usersList!!) {
if (user!!.id == chatlist.id) {
mUsers!!.add(user)
}
}
}
userAdapter = UserAdapter(context!!, mUsers!!, true)
recyclerView!!.adapter = userAdapter
}
override fun onCancelled(databaseError: DatabaseError) {
}
})
}
private fun status(status: String) {
reference = FirebaseDatabase.getInstance().getReference("Users").child(firebaseUser!!.uid)
val hashMap = HashMap<String, Any>()
hashMap["status"] = status
reference.updateChildren(hashMap)
}
override fun onResume() {
super.onResume()
status("online")
}
override fun onPause() {
super.onPause()
status("offline")
}
companion object {
val TAG = "MainActivityChat"
}
}
User Model
class User {
var id: String? = null
var phoneno: String? = null
var profileImageUrl: String? = null
var search: String? = null
var status: String? = null
var username: String? = null
constructor(id: String, phoneno: String, profileImageUrl: String, search: String, status: String, username: String) {
this.id = id
this.phoneno = phoneno
this.profileImageUrl = profileImageUrl
this.search = search
this.status = status
this.username = username
}
constructor() {
}
}
Chatlist model
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
#Parcelize
class Chatlist(val id: String):
Parcelable {
constructor() : this("")
}
Logcat
2019-03-02 22:20:52.446 20562-20562/kushwaha.samir.boop E/AndroidRuntime: FATAL EXCEPTION: main
Process: kushwaha.samir.boop, PID: 20562
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database##16.0.5:423)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database##16.0.5:214)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database##16.0.5:79)
at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database##16.0.5:212)
at kushwaha.samir.boop.MainActivityChat$chatList$1.onDataChange(MainActivityChat.kt:187)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##16.0.5:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##16.0.5:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##16.0.5:55)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
According to your comment, you say that when you try to log the content of your snapshot object you get:
{ key = status, value = offline }
Which obviously means that you are using a wrong reference. So you get that result because you are getting a reference in database for the status property which of type String and that's why you get that error:
com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type kushwaha.samir.boop.models.User
To solve this, please change the following line of code:
reference.addValueEventListener(object : ValueEventListener {}
to
val rootRef = FirebaseDatabase.getInstance().getReference()
val usersRef = rootRef.child("Users")
usersRef.addValueEventListener(object : ValueEventListener {}
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)
}
}
}
}
})
}