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) {}
})
Related
So I have a movie app. If I liked the movie I'm gonna save its id to firebase. And my goal is to get all movie_id's and display them on screen.
This is the saving code.
firebaseDb.getReference("Users").child(uid).child("movie")
.push().child("movie_id")
.setValue(args.movie.id)
And this is the firebase display
So how to get all movie_id's? I tried this but nothing happened.
firebaseDb.getReference("Users").child(uid).child("movie").addValueEventListener(object :
ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val map: Map<String, Any> = snapshot.getValue() as Map<String, Any>
val mapSize = map.keys.size
for (i in 1..mapSize) {
val keys = map.filterKeys { it == map.keys.toTypedArray()[i - 1] }
}
}
If want to create a list of movie IDs, then use the following lines of code:
val uid = FirebaseAuth.getInstance().currentUser?.uid
val db = FirebaseDatabase.getInstance().reference
val movieRef = db.child("Users").child(uid).child("movie")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val movieIds = mutableListOf<String>()
for (ds in dataSnapshot.children) {
val movieId = ds.child("movie_id").getValue(String::class.java)
movieIds.add(movieId)
}
Log.d("TAG", movieIds.size.toString())
}
override fun onCancelled(error: DatabaseError) {
Log.d("TAG", error.getMessage()) //Never ignore potential errors!
}
}
movieRef.addListenerForSingleValueEvent(valueEventListener)
The result in the logcat will be:
2
As I only see two movies in the screenshot.
I want to update the Name-based from User Input NIK then show the data to the field and by pressing the update button it will update the data inside the Database.
I'm using this Constructor Class :
import com.google.firebase.database.Exclude
import com.google.firebase.database.IgnoreExtraProperties
#IgnoreExtraProperties
class DatabaseModelUpdate(
var nama : String = ""
) {
#Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"nama" to this.nama
)
}
}
and my source code is :
val nama = findViewById<EditText>(R.id.editNama).text.toString().trim()
val model = DatabaseModelUpdate(nama)
val post = model.toMap()
var query = reference.orderByKey().equalTo(NIK)
query.addListenerForSingleValueEvent(object : ValueEventListener {
#SuppressLint("SetTextI18n")
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.exists()) {
for (userSnapshot in dataSnapshot.children) {
var keys = userSnapshot.ref.key.toString()
val updates = hashMapOf<String, Any>(
"/Users/$keys" to post
)
userSnapshot.ref.updateChildren(updates)
}
}
My JSON :
But, after I pressed the Update Button nothing change.
UPDATE
Codes:
private fun updating() {
val NIK = findViewById<EditText>(R.id.inputNik).text.toString().trim()
val nama = findViewById<EditText>(R.id.editNama).text.toString().trim()
var query = reference.orderByChild("nik").equalTo(NIK)
query.addListenerForSingleValueEvent(object : ValueEventListener {
#SuppressLint("SetTextI18n")
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.exists()) {
for (userSnapshot in dataSnapshot.children) {
var keys = userSnapshot.ref.key.toString()
val updates = hashMapOf<String, Any?>(
"Users/$keys/nama" to nama
)
dataSnapshot.ref.updateChildren(updates)
Database :
The codes just making a new nodes instead updating the data
UPDATES 2
using
"nama" to nama
database :
To update the "nama" property of the object which has the key equal to "NIK", you can directly point to that particular property and set the new name as shown in the following lines of code:
val query = reference.orderByKey().equalTo(NIK)
val listener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (ds in dataSnapshot.children) {
ds.child("nama").getRef().setValue("newNama")
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
}
}
query.addListenerForSingleValueEvent(listener)
So there is no need at all to create any additional classes for a simple update.
Edit:
You might also consider trying this:
for (userSnapshot in dataSnapshot.children) {
val updates = hashMapOf<String, Any>(
"nama" to "newNama"
)
userSnapshot.ref.updateChildren(updates)
}
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.
Created next structure in my database, and now want to display data in my list
Tried to add next code in onViewCreated:
databaseReference = FirebaseDatabase.getInstance().reference
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
topWordsList.clear()
for (wordsSnapshot in dataSnapshot.children) {
val topWord = wordsSnapshot.getValue(TopWord::class.java)
topWord?.let { topWordsList.add(it) }
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
wordsRef?.addListenerForSingleValueEvent(valueEventListener)
Method onDataChanged was called, but i can't get name for example.
My model:
data class TopWord(
val name: String = "",
val description: String = ""
)
You aren't getting something because you are adding the name of your project as a child in the reference and there is no need for that. So please change the following line of code:
val wordsRef = databaseReference?.child("talk-6e3c0")?.child("words")
to
val wordsRef = databaseReference?.child("words")
I just removed the call to .child("talk-6e3c0")?.
I display a list of my targets in fragmentA, when I click on one of them, I pass the guid of this target to the fragmentB
After that, I try in the fragmentB display the data of this target for this guid:
private fun fetchTarget(guid: String) {
val uid = firebaseUser!!.uid
// Attach a listener to read the data at the target id
databaseReference?.child("targets")?.child("users")
?.child(uid)?.child("targets")?.child(guid)?.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data = dataSnapshot.value as? HashMap<String, String>?
val name = data?.get("name") ?: ""
val description = data?.get("description") ?: ""
if (name.isEmpty()) Log.d("some", "nameIsEmpty")
else updateViewsContent(name = name, description = description)
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", databaseError.message)
}
})
}
Here I get the guid: -LmfEVnwgqCUqt7beHDg
And in my console i have next structure:
Unfortunately I can't display data of target, though like all the chains I installed
Q: How i can download -LmfEVnx-y7c3oh8_U9F ?
To display the data that belongs to a single guid, you should use a query and then iterate through the DataSnapshot object like in the following lines of code:
val uid = FirebaseAuth.getInstance().currentUser!!.uid
val rootRef = FirebaseDatabase.getInstance().reference
val targetsRef = rootRef!!.child("targets").child("users").child(uid).child("targets")
val query = targetsRef.orderByChild("guid").equalTo("-LmfEVnwgqCUqt7beHDg")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (ds in dataSnapshot.children) {
val target = ds.getValue(Target::class.java)
Log.d(TAG, target.name)
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d(TAG, databaseError.getMessage()) //Don't ignore errors!
}
}
query.addListenerForSingleValueEvent(valueEventListener)
The result in the logcat will be:
fgg
You are not getting any data because to get above data your guid value in query should be "-LmfEVnx-y7c3oh8_U9F" but you are passing "-LmfEVnwgqCUqt7beHDg".
You can try below query to get above data:
val uid = firebaseUser!!.uid
// Attach a listener to read the data at the target id
databaseReference?.child("targets")?.child("users")?.child(uid)?.child("targets")?.orderByChild("guid").equalTo(guid)?.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data = dataSnapshot.value as? HashMap<String, String>?
val name = data?.get("name") ?: ""
val description = data?.get("description") ?: ""
if (name.isEmpty()) Log.d("some", "nameIsEmpty")
else updateViewsContent(name = name, description = description)
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", databaseError.message)
}
})