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
}
}
})
}
}
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
my connecter:
interface SettingsVMRepConnector {
fun getUserEmail(email: String)
}
in my viewmodel:
class MyViewModel: ViewModel(), SettingsVMRepConnector
{
private val repository= SettingsRepository(this)
private var inputUserEmail= MutableLiveData<String?>()
fun getInputUserEmail(): LiveData<String?> {return inputUserEmail}
...
init{
repository.findUserEmail()
}
override fun getUserEmail(email:String) {
inputUserEmail.value = email
println(inputUserEmail.value.toString()+"...")
}
}
in my fragment:
val email : String = viewModel.getInputUserEmail().value.toString()
println("here: "+email)
emailInput.setText(email)
and in repository:
class SettingsRepository(val connector: SettingsVMRepConnector){
private val userID= Hawk.get<String>(Constants.LOGGEDIN_USERID)
private val usersRef: DatabaseReference = FirebaseDatabase.getInstance().getReference().child("Users")
fun findUserEmail(){
usersRef.child(userID).addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
var email = snapshot.child(Constants.R_USEREMAIL).value.toString()
connector.getUserEmail(email)
return
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
}
output is:
here: null
james#gmail.com...
I want to see this email in fragment. Why is returns null? And how can I see this e mail in my fragment?
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
How i can optimize my code?
In every function i created valueEventListener.
Here is all code:
class TargetsPresenter(private val contract: SelectTargetViewContract) {
var firebaseUser: FirebaseUser? = null
var targetList: ArrayList<Goal> = ArrayList()
private var databaseReference: DatabaseReference? = null
private var targetsRef: DatabaseReference? = null
private var uid: String? = null
fun setInitialData() {
firebaseUser = FirebaseAuth.getInstance().currentUser
databaseReference = FirebaseDatabase.getInstance().reference
uid = firebaseUser?.uid
targetsRef = databaseReference?.child("targets")
?.child("users")?.child(uid.toString())
?.child("targets")
}
fun getTargetsFromDb() {
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
targetList.clear()
dataSnapshot.children
.mapNotNull { it.getValue(Goal::class.java) }
.toCollection(targetList)
contract.updateViewContent()
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
targetsRef?.addListenerForSingleValueEvent(valueEventListener)
}
fun getTargetsByPriority() {
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
targetList.clear()
dataSnapshot.children
.mapNotNull { it.getValue(Goal::class.java) }
.sortedBy { it.priority }
.toCollection(targetList)
contract.updateViewContent()
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
targetsRef?.addListenerForSingleValueEvent(valueEventListener)
}
fun getTargetsByDeadline() {
val valueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
targetList.clear()
dataSnapshot.children
.mapNotNull { it.getValue(Goal::class.java) }
.sortedBy { it.deadline }
.toCollection(targetList)
contract.updateViewContent()
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
targetsRef?.addListenerForSingleValueEvent(valueEventListener)
}
}
Optimization is the wrong word to describe the issue. The issue is repeating identical code (violating the DRY principle), which can be a problem because it invites error if you need to change something, and it's less readable.
In this case, it's not extreme, but I guess it could be improved somewhat. You can declare a class implementation of the listener that takes a parameter for how to sort the list.
class TargetsPresenter(private val contract: SelectTargetViewContract) {
//...
fun getTargetsFromDb() {
targetsRef?.addListenerForSingleValueEvent(MyValueEventListener<String>())
}
fun getTargetsByPriority() {
targetsRef?.addListenerForSingleValueEvent(MyValueEventListener(Goal::priority))
}
fun getTargetsByDeadline() {
targetsRef?.addListenerForSingleValueEvent(MyValueEventListener(Goal::deadline))
}
private inner class MyValueEventListener<R: Comparable<R>>(
private val sortCriteria: (Goal) -> R? = { null }
) : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
targetList.clear()
dataSnapshot.children
.mapNotNull { it.getValue(Goal::class.java) }
.sortedBy(sortCriteria)
.toCollection(targetList)
contract.updateViewContent()
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("some", "Error trying to get targets for ${databaseError.message}")
}
}
}
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...
}
});