I am implementing a quiz app in Android studio using kotlin. I am communicating with firebase where I store users who signs up. This is how it is structured in firebase:
And this is how I save a user when they signed up:
class User(val uid: String, val Username: String, var highscore: Int)
private fun saveUserToDatabase(){
val uid: String? = FirebaseAuth.getInstance().uid
val ref: DatabaseReference = FirebaseDatabase.getInstance().getReference( "/Users/$uid")
val user = User(uid.toString(), signUpUsername.text.toString(), 0)
ref.setValue(user)
.addOnSuccessListener {
Log.d("RegisterActivity", "User was saved in the database")
}
}
}
When a user has logged in and have played a round I want to retrieve the highscore with the current users userId and update the highscore if the score is greater than the highscore. This is my function that handles that:
private fun updateScore(score: Int, userId: String, isLoggedIn: Boolean){
if(isLoggedIn) {
var ref = FirebaseDatabase.getInstance().reference
ref.child(userId).addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(error: DatabaseError) {
Log.e("onCancelledError", "onCancelled", error.toException())
}
override fun onDataChange(dataSnapShot: DataSnapshot) {
var highscore = dataSnapShot.child("highscore").getValue(Int::class.java)
Log.d("highscore", highscore.toString())
if(highscore != null){
if (highscore < score) {
highscore = score
dataSnapShot.ref.setValue(highscore)
}
}
}
})
}
}
But this does not work because highscore is null, when it should be 0. My userId is right so it is not that, I do not know what is wrong. Since I am new to firebase I have a hard time understanding the syntax. Any suggestions what could be wrong?
Thanks!
You're not building the reference to the user's node correctly. You probably meant to do this:
ref.child('Users').child(userId).addListenerForSingleValueEvent(...)
Note child('Users').
Related
Hello can someone that can help me to retrieve the data of selected value from generate key or push in Realtime Database Firebase. Nothings happen when I clicking the button I think my child is not order correctly. This is the collection tree from firebase;
val btnSyncing = findViewById<TextView>(R.id.btnSync)
btnSyncing.setOnClickListener {
val user = FirebaseAuth.getInstance().currentUser
val userid = user!!.uid
database = FirebaseDatabase.getInstance()
reference = database.getReference("Profile")
val timeTextView = findViewById<TextView>(R.id.txtTime)
val dateTextView = findViewById<TextView>(R.id.txtDate)
reference.child(userid)
.child("Delivery Details").orderByChild("Date").equalTo("24/9/22")
.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val time = dataSnapshot.child("Time").value as String?
val date = dataSnapshot.child("Details").value as String?
timeTextView.text = time
dateTextView.text = date
}
override fun onCancelled(error: DatabaseError) {
Toast.makeText(baseContext, "Something wrong happened!", Toast.LENGTH_LONG)
.show()
}
})}
I want to perform a compound query in firestore where I would like to get all documents with field bloodgroup equal to A+ and with field createdBy not equal to email. This email is that of the logged in user. When I perform the query I get NullPointerException. How to perform the query correctly 021-07-24 19:50:24.746 17550-17550/com.example.bloodbankcompany E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.bloodbankcompany, PID: 17550 java.lang.NullPointerExceptionatcom.example.bloodbankcompany.UserlistActivity$EventChangeListener3$1.onEvent(UserlistActivity.kt:217) I am storing the document snapshot inside the userArrayList array. Without the whereNotEqualTo query I am getting output where my documents get listed in recyclerview.
private fun EventChangeListener2(){
val sharedPreferences1 = getSharedPreferences("email", Context.MODE_PRIVATE)
val email: String? = sharedPreferences1.getString("email","null")?.trim()
Toast.makeText(this, "ssrae$email", Toast.LENGTH_SHORT ).show()
mFireStore.collection("applicationForm").whereNotEqualTo("createdBy",email).whereEqualTo("bloodgroup","A+").addSnapshotListener(object : EventListener<QuerySnapshot>{
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if (error!= null){
Log.e("firestore error", error.message.toString())
}
for(dc: DocumentChange in value?.documentChanges!!){
if (dc.type== DocumentChange.Type.ADDED){
userArrayList.add(dc.document.toObject(User1::class.java))
var number=userArrayList
var number1 =userArrayList
}
// Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()
}
myAdapter.notifyDataSetChanged()
}
})
}
Well, I have edited a little bit of your code, if it still doesn't work add a comment.
Also, an explanation about changes is commented below.
private fun EventChangeListener2() {
val sharedPreferences1 = getSharedPreferences("email", Context.MODE_PRIVATE)
val email: String? = sharedPreferences1.getString("email", "null")?.trim()
Log.d("firestore email", email.toString())
Toast.makeText(this, "ssrae$email", Toast.LENGTH_SHORT).show()
// try and catch will avoid your app to crash.
try {
//ref
var ref = mFireStore.collection("applicationForm")
.whereEqualTo("bloodgroup", "A+")
/**
* I believe since your email is of type nullable and there may be
* maybe a chance that email is null and is given to whereNotEqualTo
* I am just making an assumption here since I don't know what you
* recieve from sharedPreferences and whether it is null or not
*
* So, what I have done here is,
* firstly, I have split the firestore call into 2 parts and
* Secondly, I have a null-check for email, if it is
* not-null ref will also include this query
*
*/
//null Check for email
if (email != null) ref = ref.whereNotEqualTo("createdBy", email)
// Snapshot Listener
ref.addSnapshotListener(object : EventListener<QuerySnapshot> {
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if (error != null) {
Log.e("firestore error", error.message.toString())
}
for (dc: DocumentChange in value?.documentChanges!!) {
if (dc.type == DocumentChange.Type.ADDED) {
userArrayList.add(dc.document.toObject(User1::class.java))
var number = userArrayList
var number1 = userArrayList
}
// Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()
}
myAdapter.notifyDataSetChanged()
}
})
} catch (e: Exception) {
Log.e("firestore error", "Error", e)
}
}
EDIT:
According to firebase docs,
https://firebase.google.com/docs/firestore/query-data/indexing#exemptions
If you attempt a compound query with a range clause that doesn't map to an existing index, you receive an error. The error message includes a direct link to create the missing index in the Firebase console.
I want to get the address from another user out of my database but i can't call it because I don't know how to get it, because I have to call it over the id. Do you know how to get a specific information from another user or like all users? Until now I can only get all the informations like so:
mDatabase = FirebaseDatabase.getInstance().getReference("User")
mDatabase.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val data = snapshot.value as? Map<String, *>
Log.e("User", data.toString())
// data is a map of { uid to User }
val locoloco = snapshot.child("Adresse").value.toString()
if(!locoloco.isEmpty()) {
val adresseUser = snapshot.child("Adresse").value as? Map<String, *>?
val wasauchimmer = snapshot.key
val haha = snapshot.getValue()
Log.e("Key",wasauchimmer.toString())
Log.e("Address", adresseUser.toString())
}
}
override fun onCancelled(error: DatabaseError) {
Log.e(TAG, "Loading user data failed: \n" + error.message)
}
})
and this is the database I'm referring to:
This is my outcome of the log I am getting right now:
2021-02-15 16:47:41.977 24358-24358/com.example.discoverme E/Address: null
2021-02-15 16:47:41.977 24358-24358/com.example.discoverme E/User: {q946wkGYXVRdYPLppv4j51cIQxp1={UserID=q946wkGYXVRdYPLppv4j51cIQxp1, Anwendertyp=Fotograf/Videograf, Name=buesra}, ZzmI1VsENEULsCX9NjSMtW064Mm1={UserID=ZzmI1VsENEULsCX9NjSMtW064Mm1, Email=eva.schumacher#gmail.de, Spezialisierung=[Familien, Architektur, Interior], Geburtstag=26.06.1999, Anwendertyp=Fotograf/Videograf, Telefon=022150055025, Stundenlohn=62€, Adresse=Zülpicher Str.386, Infotext=Hallo, ich heiße Eva und bin Fotografin., Name=Eva Schumacher}, NAzZGnwiAfaiEkEGRGyzRla0Cwo2={UserID=NAzZGnwiAfaiEkEGRGyzRla0Cwo2, Spezialisierung=[Architektur, Passfotos, Film], Anwendertyp=Fotograf/Videograf, Name=Frederik Löhmann}, bnc3GmwTS9RackTkbjOMd2H2pz72={UserID=bnc3GmwTS9RackTkbjOMd2H2pz72, Anwendertyp=Suchender, Name=Marion Ewert}}
To load the data for a specific user, you'll need to know the UID of that specific user. With that, you can then load their data with:
mDatabase = FirebaseDatabase.getInstance().getReference("User")
mDatabase.child("MAzZGnwiAfaiEkEGRGyzRla0Cwo2").addListenerForSingleValueEvent(object : ValueEventListener {
...
If you don't know the user's UID, all you can do is load all users and loop over them. That last part of missing in your current code, and looks like:
mDatabase = FirebaseDatabase.getInstance().getReference("User")
mDatabase.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (userSnapshot in snapshot.children) {
val data = userSnapshot.value as? Map<String, *>
Log.d("User", data.toString())
...
}
}
override fun onCancelled(error: DatabaseError) {
Log.e(TAG, "Loading user data failed: \n" + error.message)
}
})
Also see the Firebase documentation on listening for value events.
im working with firebase for a couple months and so far i had no issues until now. im using kotlin and my problem is simple but i cant find a way out. i storage strings in database: path"/user/friends" , but i cant change the variable name and the strings were overwriting itselves. My solution was use "push()" until the "setValue()", but with this i have the following firebase structure:
"users": {
"yvrYpjMwVSPBvMAvDGo26hPlWWQ2": {
"email": "vinibarros.sp#gmail.com",
"friends": {
"-LfD9z6ke7FXFjxUb4td": {
"email": "teste#gmail.com"
},
"-LfDA-NaAYAMoWiPhXy4": {
"email": "teste2#gmail.com"
}
},
"primeiroLogin": true,
"stars": 0,
"tutorialComplete": false,
"uid": "yvrYpjMwVSPBvMAvDGo26hPlWWQ2",
"username": "Vinicius Barros"
}
}
basically hashmaps inside a hashmap ps:lol mindblow
how do i get the pushcode.value into an arraylist?
i have a class user that have the friend variable, until now this variable was typed as hashMap. and the call to get the email was "user.friends.value"
this worked because was one friend....
com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String
When I added more than one user I got this error that references my class user, where have a "hashMap". But the firebase gives me another hashmap instead of string. I was thinking about: hashMap<hashMap<String,String>, null>.
i 've tried this:
class friends:
#Parcelize
class Friend(val hashMap: HashMap < String, String > ? ): Parcelable {
constructor(): this(null)
}
The activity where i show the friends:
val ref2 = FirebaseDatabase.getInstance().getReference("/users/" + cUid + "/friends/")
ref2.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
}
override fun onDataChange(p0: DataSnapshot) {
p0.children.forEach {
val friend = it.getValue(Friend::class.java)
Log.d("teste", it.toString())
if (friend != null) {
Log.d("teste", friend.hashMap ? .values.toString())
//friends.add(friend.hashMap?.values.toString())
}
}
}
})
this keeps returning null....
With your Friend class, the Firebase client looks for a JSON for each friend with this structure:
"-LfD9z6ke7FXFjxUb4td": {
"hashMap": {
...
}
},
This is because you're defining your Friend class with a property hashMap like this: class Friend(val hashMap: HashMap < String, String > ? ).
To be able to read your current structure, you'll need to define a data class like this:
data class Friend (
val email: String? = null
}
Now the email in the Friend class matched the email property in the JSON. And since email has a default value, the Friend class will have a default no-argument constructor, which Firebase relies on.
Solved!
After get into /friends
i did this:
var friends : ArrayList<String> = arrayListOf()
the onDataChanged where i get the string friend
override fun onDataChange(p1: DataSnapshot) {
p1.children.forEach { it1 ->
val friend = it1.value as String
friends.add(friend)
}
}
I'm trying to retrieve a document by a specific id passed by parameter and I'm 100% sure the document exists but Firestore says the opposite.
Here's the code of my function
val db = FirebaseFirestore.getInstance()
private fun retrieveUsersFromParticipantsId(participant: String) {
db.collection("Usuarios").document(participant).get().addOnCompleteListener {
if (it.isSuccessful) {
val user = it.result.toObject(User::class.java)
participantsArray.add(user!!)
}
}
}