I`m new around here and i have a question about my little project.
I set the database reference (mDatabase) for this activity pointed to the name child and attached an addValueEventListener() to listen to the datasnapshot from the firebase database console to fetch the name value from the database, but when i run to app , it displays like the following -
Thanks you all,
register activity
class RegisterScreenActivity : AppCompatActivity() {
val mAuth = FirebaseAuth.getInstance()
lateinit var mDatabase : DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.register_page)
val regBtn = findViewById<View>(R.id.regBtn)as Button
mDatabase = FirebaseDatabase.getInstance().getReference("Names")
regBtn.setOnClickListener { view -> register()
}
}
private fun register(){
val emailTxt = findViewById<View>(R.id.emailTxt) as EditText
val nameTxt = findViewById<View>(R.id.nameTxt) as EditText
val passwordTxt = findViewById<View>(R.id.passwordTxt) as EditText
var email = emailTxt.text.toString()
var name = nameTxt.text.toString()
var password = passwordTxt.text.toString()
if (!name.isEmpty() && !password.isEmpty() && !email.isEmpty()){
mAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(this) { task ->
if (task.isSuccessful){
val user = mAuth.currentUser
val uid = user!!.uid
mDatabase.child(uid).child("Name").setValue(name)
Toast.makeText(this,"xxxxx",Toast.LENGTH_LONG).show()
startActivity(Intent(this, LoginPage::class.java))
}else{
Toast.makeText(this,"xxxx",Toast.LENGTH_LONG).show()
}
}
}else{
Toast.makeText(this,"xxxxx!",Toast.LENGTH_LONG).show()
}
}
i hold user info and after that comes login activity
class LoginPage : AppCompatActivity() {
val mAuth = FirebaseAuth.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_page)
val loginBtn = findViewById<View>(R.id.loginBtn) as Button
val regTxt = findViewById<View>(R.id.regTxt)as Button
loginBtn.setOnClickListener { view -> login()
}
regTxt.setOnClickListener { view -> register()
}
}
private fun login() {
val emailTxt = findViewById<View>(R.id.emailTxt) as EditText
val passwordTxt = findViewById<View>(R.id.passwordTxt) as EditText
var email = emailTxt.text.toString()
var password = passwordTxt.text.toString()
if (!email.isEmpty() && !password.isEmpty()) {
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
startActivity(Intent(this, Timeline::class.java))
Toast.makeText(this, "xxxxx", Toast.LENGTH_LONG).show()
startActivity(Intent(this,Timeline::class.java))
} else {
Toast.makeText(this, "xxxx",Toast.LENGTH_LONG).show()
}
}
} else {
Toast.makeText(this, "xxxxx", Toast.LENGTH_LONG).show()
}
}
private fun register (){
startActivity(Intent(this,RegisterScreenActivity::class.java))
}
}
and if info is correct next activity timeline
class Timeline : AppCompatActivity() {
lateinit var mDatabase: DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.time_line)
val dspTxt = findViewById<View>(R.id.dispTxt) as TextView
mDatabase = FirebaseDatabase.getInstance().getReference("Names")
mDatabase.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(snapshot: DataSnapshot) {
snapshot.child("Name").toString()
dspTxt.text ="Welcome " + snapshot.value.toString()
}
})
}
}
There is no attribute value on the DataSnapshot object (see documentation)
Please refer to the documentation on how to read values. You should use the function getValue().
myDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.getValue(String.class);
}
#Override
public void onCancelled(DatabaseError error) {
// TODO...
}
});
Related
This question already has answers here:
getContactsFromFirebase() method return an empty list
(1 answer)
Setting Singleton property value in Firebase Listener
(3 answers)
Why does my function that calls an API or launches a coroutine return an empty or null value?
(4 answers)
Closed 1 year ago.
I receive null snapshot in only this two method
private fun getUserName() {
databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
databaseReference.child(uAuth.currentUser?.uid.toString()).addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var userList :User
userList = snapshot.getValue(User::class.java)!!
userName=userList?.cid.toString()
Toast.makeText(this#ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
}
override fun onCancelled(error: DatabaseError) {
}
})
}
private fun getProductPic(prodImageURL:String) {
storageReference= FirebaseStorage.getInstance().reference.child(prodImageURL)
val localFile = File.createTempFile("tempImage","jpg")
storageReference.getFile(localFile).addOnSuccessListener {
val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
viewBinding.picViewProd.setImageBitmap(bitMap)
}
}
class ProductDetail : AppCompatActivity() {
private lateinit var databaseReference: DatabaseReference
private lateinit var uAuth:FirebaseAuth
private lateinit var storageReference: StorageReference
private lateinit var viewBinding:ActivityProductDetailBinding
private lateinit var adapter:commentAdapter
private lateinit var tc:String
private lateinit var commentList:ArrayList<commentContain>
private lateinit var thisProductID:String
private lateinit var dateTage :String
private var userName :String=""
private var tailorUID :String=""
private var tailorName :String=""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityProductDetailBinding.inflate(layoutInflater)
val view = viewBinding.root
setContentView(view)
tc=getIntent().getStringExtra("tc").toString()
thisProductID = getIntent().getStringExtra("prodNo").toString()
uAuth = FirebaseAuth.getInstance()
//Comment adapter and recycler view code
commentList= ArrayList()
getTailorName()
getComment()
adapter= commentAdapter(this,commentList)
viewBinding.commentList.layoutManager=LinearLayoutManager(this)
viewBinding.commentList.adapter=adapter
getTimeTag()
val currentUser = uAuth.currentUser?.uid
val currentUserURL = "Users/$currentUser.jpg"
getProductData()
if(tc=="tailor"){
viewBinding.btnOrderProduct.isVisible=false
}
viewBinding.btnOrderProduct.setOnClickListener {
addOrder()
}
viewBinding.picViewTailor.setOnClickListener {
val intent = Intent(this, TailorProfile::class.java)
intent.putExtra("tc",tc)
intent.putExtra("tuid",tailorUID)
startActivity(intent)
}
viewBinding.sendButton.setOnClickListener{
getUserName()
val comment = viewBinding.messageBox.text.toString()
addComment(thisProductID,userName,comment,dateTage,currentUserURL)
}
}
private fun getUserName() {
databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
databaseReference.child(uAuth.currentUser?.uid.toString()).addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var userList :User
userList = snapshot.getValue(User::class.java)!!
userName=userList?.cid.toString()
Toast.makeText(this#ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
}
override fun onCancelled(error: DatabaseError) {
}
})
}
private fun getProductData() {
databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").reference
databaseReference.child("Product").child(thisProductID).addValueEventListener(object: ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val productData = snapshot.getValue<Product>()
viewBinding.tvViewPrice.setText(productData?.price.toString())
viewBinding.tvViewClothspants.setText(productData?.clothsPants.toString())
viewBinding.tvViewFabric.setText(productData?.fabric.toString())
viewBinding.tvViewHeight.setText(productData?.height.toString())
viewBinding.tvViewHipBust.setText(productData?.hipBust.toString())
viewBinding.tvViewSleeve.setText(productData?.sleeve.toString())
viewBinding.tvViewStyleName.setText(productData?.styleName.toString())
viewBinding.tvViewWaist.setText(productData?.waist.toString())
tailorUID = productData?.tailorID.toString()
getTailorPic(productData?.tailorID.toString())
getProductPic(productData?.imageURL.toString())
}
override fun onCancelled(error: DatabaseError) {
Toast.makeText(this#ProductDetail,"Some Things wrong in the database", Toast.LENGTH_SHORT).show()
}
}
)
}
private fun getProductPic(prodImageURL:String) {
storageReference= FirebaseStorage.getInstance().reference.child(prodImageURL)
val localFile = File.createTempFile("tempImage","jpg")
storageReference.getFile(localFile).addOnSuccessListener {
val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
viewBinding.picViewProd.setImageBitmap(bitMap)
}
}
private fun getTailorName() {
databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
databaseReference.child(tailorUID).addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val userList = snapshot.getValue(User::class.java)!!
tailorName=userList.cid.toString()
viewBinding.tvPViewTailorName.setText(tailorName)
Toast.makeText(this#ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
}
override fun onCancelled(error: DatabaseError) {
}
})
}
private fun getTailorPic(tailorUID:String){
storageReference= FirebaseStorage.getInstance().reference.child("Users/$tailorUID.jpg")
val localFile = File.createTempFile("tempImage","jpg")
storageReference.getFile(localFile).addOnSuccessListener {
val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
viewBinding.picViewTailor.setImageBitmap(bitMap)
}
}
private fun getComment() {
databaseReference=FirebaseDatabase.getInstance().getReference()
databaseReference.child("Comment").addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
commentList.clear()
for(postSnapshot in snapshot.children){
val currentComment = postSnapshot.getValue(commentContain::class.java)
if(currentComment?.productID==thisProductID){
commentList.add(currentComment!!)
}
}
adapter.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {
}
})
}
private fun addOrder() {
val intent = Intent(this, NewCustomOrder::class.java)
intent.putExtra("tc",tc)
intent.putExtra("prodNo",thisProductID)
startActivity(intent)
}
private fun addComment(productID:String,senderID:String?,comment:String,dateTage:String,currentUserURL:String){
val newComment = commentContain(uAuth.currentUser?.uid,senderID,comment,dateTage,currentUserURL,productID)
databaseReference=FirebaseDatabase.getInstance().reference
databaseReference.child("Comment").child(commentList.size.toString()).setValue(newComment).addOnFailureListener{
Toast.makeText(this,"Some thing wrong for real time database", Toast.LENGTH_SHORT).show()
}.addOnSuccessListener {
Toast.makeText(this,"Comment is added", Toast.LENGTH_SHORT).show()
}
}
private fun getTimeTag() {
val formatter = SimpleDateFormat("yyyy_MM_dd", Locale.getDefault())
val now = Date()
dateTage=formatter.format(now).toString()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
getMenuInflater().inflate(R.menu.all_menu,menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
super.onOptionsItemSelected(item)
if(item.itemId==R.id.toProfile){
val intent = Intent(this, TailorProfile::class.java)
intent.putExtra("tc",tc)
intent.putExtra("tuid",uAuth.currentUser?.uid)
finish()
startActivity(intent)
}
else if(item.itemId == R.id.toHome){
val intent = Intent(this, ProductList::class.java)
intent.putExtra("tc",tc)
finish()
startActivity(intent)
}else if(item.itemId == R.id.logout){
val intent = Intent(this, Ground::class.java)
uAuth.signOut()
finish()
startActivity(intent)
}
return true
}
}
The only problem is the getUserName and getTailorName return null at all,which is cause by the snapshot return a null value. I have tried all the method of get data from firebase realtime database, but all of them meets same problem. The weird thing is only the two function meet that problem. Any one can help me please?
below is the picture output
enter image description here
I have the following data class that holds the child values of a specific reference from the Firebase Realtime Database:
data class Users(
val uid: String = "",
var firstName: String = "",
var lastName: String = "",
)
This is my ViewModel:
class UsersViewModel : ViewModel() {
private val uid = Firebase.auth.currentUser!!.uid
private val USERS_REF: DatabaseReference = FirebaseDatabase.getInstance().getReference("/users/$uid")
private val liveData: FirebaseQueryLiveData = FirebaseQueryLiveData(USERS_REF)
private val usersLiveData: MediatorLiveData<Users> = MediatorLiveData()
init {
usersLiveData.addSource(liveData, object : Observer<DataSnapshot> {
override fun onChanged(dataSnapshot: DataSnapshot?) {
if (dataSnapshot != null) {
usersLiveData.postValue(dataSnapshot.getValue(Users::class.java))
} else {
usersLiveData.value = null
}
}
})
}
#NonNull
fun getUsersLiveData() : LiveData<Users> {
return usersLiveData
}
}
This is my extended LiveData:
class FirebaseQueryLiveData(ref: DatabaseReference) : LiveData<DataSnapshot>() {
private val query: Query = ref
private val listener: MyValueEventListener = MyValueEventListener()
private var listenerRemovePending = false
private val removeListener = object : Runnable {
override fun run() {
query.removeEventListener(listener)
listenerRemovePending = false
}
}
override fun onActive() {
super.onActive()
if (listenerRemovePending) {
Handler(Looper.getMainLooper()).removeCallbacks(removeListener)
} else {
query.addValueEventListener(listener)
}
listenerRemovePending = false
}
override fun onInactive() {
super.onInactive()
Handler(Looper.getMainLooper()).postDelayed(removeListener, 2000)
query.removeEventListener(listener)
}
private inner class MyValueEventListener : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
value = snapshot
}
override fun onCancelled(error: DatabaseError) {
return
}
}
}
For reading the values from my database in my Activity or Fragment, this is what I've done:
val usersViewModel = ViewModelProvider(this).get(UsersViewModel::class.java)
val usersLiveData = usersViewModel.getUsersLiveData()
usersLiveData.observe(this, object : Observer<Users> {
override fun onChanged(users: Users?) {
if (users != null) {
firstNameTextView.text = users.firstName
lastNameTextView.text = users.lastName
}
}
})
This all works, but my question is how do I write to a specific child for my database in my Activity or Fragment? For example, let's say I want to only modify the lastName child? How do I do that? I don't have any references to FirebaseDatabase in my activities and fragments because the ViewModel and LiveData ensure that I don't need them anymore.
I am getting issues of getting my USER KEY and it returned as null even if there's a username.
Thing is I am just trying to get my username.
I am currently using firebase database
class NewMessageActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_message)
supportActionBar?.title="Select User"
/*
val adapter = GroupAdapter<ViewHolder>()
adapter.add(UserItem())
adapter.add(UserItem())
adapter.add(UserItem())
new_message_list.adapter = adapter
*/
fetchusers()
}
companion object {
val USER_KEY = "USER_KEY"
}
private fun fetchusers(){
val ref = FirebaseDatabase.getInstance().getReference("/users")
ref.addListenerForSingleValueEvent(object: ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
val adapter = GroupAdapter<ViewHolder>()
p0.children.forEach {
Log.d("NewMessage", it.toString())
val user = it.getValue(User::class.java)
if (user != null){
adapter.add(UserItem(user))
}
}
adapter.setOnItemClickListener { item, view ->
val userItem = item as UserItem
val intent = Intent(view.context, ChatLogActivity::class.java)
intent.putExtra(USER_KEY, userItem.user.username)
startActivity(intent)
finish()
}
new_message_list.adapter = adapter
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
}
class UserItem(val user: User): Item<ViewHolder>() {
override fun bind(viewHolder: ViewHolder, position: Int){
//list stuff
viewHolder.itemView.username_textview_new.text = user.username
Picasso.get().load(user.profileImageUrl).into(viewHolder.itemView.imageview_new_msg)
}
override fun getLayout(): Int {
return R.layout.user_row_new_message
}
}
This one really frustrated me for hours. I needed this for my chat log title for each person
Maybe I should skip this?
I am just new to android development
Can anyone help?
error in debug
I am creating a new user with authentication, and setting the User Key in the database as the User UID.
private fun writeNewUser(name: String, email: String?) {
val user = User(name, email)
mDatabase.child("Users").child(mAuth.currentUser!!.uid).setValue(user)
}
This works fine and produces the following result:
I'm now trying to login and read that user's information.
I'm trying to set the UID as the database reference (after having successfully logged in).*My Login process is working.
I'm getting an error on MainActivity where I'm trying to display the data:
Error:
None of the following functions can be called with the arguments supplied:
Line:
key?.let { getValue(mAuth.uid) }
Here's my MainActivity code where I'm trying to read and display the data.
class MainActivity : AppCompatActivity() {
private lateinit var mUser: User
private lateinit var mAuth : FirebaseAuth
private lateinit var mDatabase: DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAuth = FirebaseAuth.getInstance()
mDatabase = FirebaseDatabase.getInstance().reference
fun currentUserReference(): DatabaseReference =
mDatabase.child("users").child(mAuth.currentUser!!.uid)
currentUserReference().addListenerForSingleValueEvent(
ValueListenerAdapter{
mUser = it.asUser()!!
tv_main_name.setText(mUser.name)
tv_main_email.setText(mUser.email)
}
)
}
fun DataSnapshot.asUser(): User? =
//error on this line ↓
key?.let { getValue(mAuth.uid) }
}
Edit 1
Existing ValueListenerAdapter.kt
class ValueListenerAdapter(val handler: (DataSnapshot) -> Unit): ValueEventListener {
private val TAG = "ValueListenerAdapter"
override fun onDataChange(data: DataSnapshot) {
handler(data)
}
override fun onCancelled(error: DatabaseError) {
Log.e("onCancelled", TAG, error.toException())
}
}
Edit 2
class MainActivity : AppCompatActivity() {
private lateinit var mUser: User
private lateinit var mAuth : FirebaseAuth
private lateinit var mDatabase: DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAuth = FirebaseAuth.getInstance()
mDatabase = FirebaseDatabase.getInstance().reference
mDatabase.child("Users").child(mAuth.currentUser!!.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("Not yet implemented")
}
override fun onDataChange(p0: DataSnapshot) {
//Declare mUser as chosen DB User
tv_main_name.setText(mUser.name)
tv_main_email.setText(mUser.email)
}
})
}
}
Edit 3
override fun onDataChange(p0: DataSnapshot) {
if (p0.hasChildren()) {
//Declare mUser as chosen DB User
tv_main_name.setText(mUser.name)
tv_main_email.setText(mUser.email)
}
}
mDatabase.child("users").child(mAuth.currentUser!!.uid).addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
//handle error
}
override fun onDataChange(p0: DataSnapshot) {
if (p0.hasChildren()) {
//If you have model for your user data object then do it like this.
val user = p0.getValue(YourModel::class.java)
}
})
That's all you need to do to get current logged in user data from users node
Working Solution
class MainActivity : AppCompatActivity() {
private lateinit var mUser: User
private lateinit var mAuth : FirebaseAuth
private lateinit var mDatabase: DatabaseReference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAuth = FirebaseAuth.getInstance()
mDatabase = FirebaseDatabase.getInstance().reference
mDatabase.child("Users").child(mAuth.currentUser!!.uid)
.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onCancelled(p0: DatabaseError) {
TODO("Not yet implemented")
}
override fun onDataChange(p0: DataSnapshot) {
if (p0.hasChildren()) {
val user = p0.getValue(User::class.java)
tv_main_name.text = user?.name
tv_main_email.text = user!!.email
}
}
})
}
}
I add targets to the database this way:
private fun addTarget(name: String, description: String) {
if (!TextUtils.isEmpty(name)) {
val target = Target(guid = "some", name = name, description = description)
databaseReference?.child("users")
?.child(mUserId.toString())?.child("targets")?.push()?.setValue(target)
} else Log.d("some", "Enter a name")
}
And get the following structure in my firebase database:
Next, I try to display my list of targets in TargetsFragment
In onViewCreated i call next functions:
private fun updateListData() {
databaseReference = FirebaseDatabase.getInstance().getReference()
getTargetsFromDb()
}
private fun getTargetsFromDb() {
databaseReference?.child("users")?.child(mUserId.toString())?.
child("targets")?.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (targetSnapshot in dataSnapshot.children) {
val target = targetSnapshot.getValue(Target::class.java)
target?.let { targetList.add(it) }
}
recyclerView?.adapter = adapter
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
})
}
As I said, because I cannot see what changes do you make, I wrote the code that can help you get the data from the database:
val uid = FirebaseAuth.getInstance().currentUser!!.uid
val rootRef = FirebaseDatabase.getInstance().reference
val targetsRef = rootRef!!.child("targets").child("users").child(uid).child("targets")
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (ds in dataSnapshot.children) {
val target = ds.getValue(Target::class.java)
targetList.add(target)
}
adapter.notifyDataSetChanged()
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d(TAG, databaseError.getMessage()) //Don't ignore errors!
}
}
targetsRef.addListenerForSingleValueEvent(valueEventListener)
The output in the logcat will be:
uuuuu
yyyyy
Even if you are using two nodes with the same name targets, both should be mentioned in the reference.