I am trying to store data in my Firebase database but the app crashes when I call the function saveUserToFirebaseDatabase(). The performRegister() function works fine which stores the email and password using FirebaseAuth but when I call performRegister() then saveUserToFirebaseDatabase() right under it, the performRegister() doesn't execute all the way though. performRegister() is suppose to make a log.d tag which tells the uid and that it successfully stored the email and password. It does that but when I call saveUserToFirebaseDatabase() under performRegister() in the onCreate function, it doesn't log the uid like it did without the saveUserToFirebaseDatabase(). Instead the performRegister() Log displays the username and passowrd then skips to the saveUserToFirebaseDatabase() which logs display the username, first name, and last name from the previous activities the user had to enter when signing up for the account. Then it crashes. Here is my code. I want to be able to call performRegister() then saveUserToFirebaseDatabase() to save the user's email and password using FirebaseAuth then save the user's other information in the database using saveUserToFirebaseDatabase().
class Password_Activity : AppCompatActivity() {
lateinit var editPasswordText: EditText
lateinit var editConfirmPasswordText: EditText
lateinit var btnOpenActivity: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_password)
editPasswordText = findViewById(R.id.edit_password)
editConfirmPasswordText = findViewById(R.id.edit_confirm_password)
btnOpenActivity = findViewById(R.id.password_continue_btn)
// btnOpenActivity.isEnabled=false
val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
var passwordinput: String = editPasswordText.text.toString().trim()
var confirmpasswordinput: String = editConfirmPasswordText.text.toString().trim()
btnOpenActivity.isEnabled = passwordinput.isNotEmpty() && confirmpasswordinput.isNotEmpty()
}
}
editPasswordText.addTextChangedListener(textWatcher)
editConfirmPasswordText.addTextChangedListener(textWatcher)
// var intent = intent
// val username = intent.getStringExtra("username")
// val firstname = intent.getStringExtra("firstname")
// val lastname = intent.getStringExtra("lastname")
// val emailaddress = intent.getStringExtra("emailaddress")
val btnOpenActivity: Button = findViewById(R.id.password_continue_btn)
btnOpenActivity.setOnClickListener {
performRegister()
saveUserToFirebaseDatabase()
// val intent = Intent(this, Main2Activity_welcome_after_signup_dashboard::class.java)
// startActivity(intent)
// overridePendingTransition(R.anim.slide_in_right,R.anim.slide_out_left)
}
}
// Save user's email and password
private fun performRegister(){
var intent = intent
val email = intent.getStringExtra("email")
val password = editPasswordText.text.toString().trim()
if (email.isEmpty() && password.isEmpty()) {
Toast.makeText(this, "Please enter email and password", Toast.LENGTH_SHORT).show()
return
}
Log.d("SignUpActivity","Email is "+ email)
Log.d("SignUpActivity","Password is $password")
// Initialize Firebase Auth
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
.addOnCompleteListener {
if (!it.isSuccessful) {
Log.d("SignUp", "Account creation unsuccessful")
return#addOnCompleteListener
}
//else if successful
Log.d("SignUp", "Successfully created user with uid: ${it.result?.user?.uid}")
}
.addOnFailureListener {
Log.d("SignUp", "Failed to create user: ${it.message}")
}
}
// Save user's username, first name, and last name to database
private fun saveUserToFirebaseDatabase(){
var intent = intent
val username = intent.getStringExtra("username")
val firstname = intent.getStringExtra("firstname")
val lastname = intent.getStringExtra("lastname")
Log.d("Signup","Storing user information in password activity: $username, $firstname, $lastname")
val uid = FirebaseAuth.getInstance().uid ?: ""
val ref = FirebaseDatabase.getInstance().getReference("/users/$uid")
val user = User(uid, username, firstname, lastname)
ref.setValue(user)
.addOnSuccessListener {
Log.d("Signup","We saved the user to Firebase Database")
}
.addOnFailureListener {
Log.d("Signup", "Failed to save user to Firebase Database")
return#addOnFailureListener
}
}
//Animation for back button
override fun finish() {
super.finish()
overridePendingTransition(R.anim.slide_in_left,R.anim.slide_out_right)
}
}
data class User(val uid: String, val username: String, val firstname: String, val lastname: String)
Your performRegister call happens aysnc in the background. This is why saveUserToFirebaseDatabase is getting called before it completes. Instead, just call it when performRegister is complete in the onCompleteListener.
Change this:
btnOpenActivity.setOnClickListener {
performRegister()
saveUserToFirebaseDatabase()
}
To:
btnOpenActivity.setOnClickListener {
performRegister()
}
and add saveUserToFirebaseDatabase() to:
.addOnCompleteListener {
if (!it.isSuccessful) {
Log.d("SignUp", "Account creation unsuccessful")
return#addOnCompleteListener
}
//else if successful
saveUserToFirebaseDatabase()
Log.d("SignUp", "Successfully created user with uid: ${it.result?.user?.uid}")
}
Related
I want to get the UID after I create a user fun createUserWithEmailAndPassword and initialize it to usrID in my user object type of UserProfile after that I call fun addUser
fun createUserWithEmailAndPassword(email: String, password: String,user: UserProfile) {
viewModelScope.launch(Dispatchers.IO) {
auth
.createUserWithEmailAndPassword(email, password)
.await()
}
//user.userID = userID
//addUser(user)
}
fun addUser(user: UserProfile) {
viewModelScope.launch(Dispatchers.IO) {
UserRepository.addUser(user)
}
}
private val usersDocumentRef by lazy {
UserRepository.db.collection("usersProfiles")
}
suspend fun addUser(user: UserProfile) {
usersDocumentRef.document(user.userID).set(user).await()
}
When the Firebase user with the given email address and password is successfully created, then it means that it is also signed in. That being said, you can get the UID of the user right from the FirebaseUser object like this:
auth.createUserWithEmailAndPassword(email, password).await()
user.userID = auth.currentUser?.uid
addUser(user)
My Authentication is working fine but I am not able to store and retrive data from realtime database. Below is the firebase rule(I am using locked mode and Usa server) and my signup Activity class. Please help me with this thing. I am taking database refernce and giving setValue method but still its not working. I have also tried different solution given on stackoverflow flow but still no luck.
Firebase Rule
{
"rules": {
".read": "true", // 2022-8-22
".write": "true"
}
}
SignUp Acitvity
class SignUpActivity : AppCompatActivity() {
private lateinit var mAuth : FirebaseAuth
private lateinit var mDBRef : DatabaseReference
private lateinit var binding: ActivitySignIntoBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySignIntoBinding.inflate(layoutInflater)
setContentView(binding.root)
mAuth = FirebaseAuth.getInstance()
binding.edtSignUp.setOnClickListener{
val name = binding.edtName.text.toString()
val email = binding.edtEmail.text.toString()
val password = binding.edtPassword.text.toString()
signUp(name, email, password)
}
binding.tvLogin.setOnClickListener {
val intent = Intent(this, Login::class.java)
finish()
startActivity(intent)
}
}
private fun signUp(name: String, email: String, password: String) {
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
addUserToDatabase(name, email, mAuth.currentUser?.uid!!)
val intent = Intent(this#SignUpActivity, MainActivity::class.java)
startActivity(intent)
} else {
Toast.makeText(this#SignUpActivity, "Some Error Occurred. Try Again", Toast.LENGTH_LONG ).show()
}
}
}
private fun addUserToDatabase(name: String, email: String, uid: String) {
mDBRef = FirebaseDatabase.getInstance("https://chatapplication-ad542-default-rtdb.firebaseio.com/").getReference()
mDBRef.child("User").child(uid).push().setValue(User(name, email, uid))
}
}
i have 3 progress activities for signup. I take the informations at first activity and then trying to send directly third activity to signup with firebase. I tried every way that i research but i can't figure it out.
This is my first activity
signUpNextButton.setOnClickListener {
val name = signUpFullname.text.toString()
val email = signUpEmail.text.toString()
val password = signUpPassword.text.toString()
val repassword = signUpPasswordRepeat.text.toString()
//Sending datas with this method
val intent = Intent(this, SignUp_Page3::class.java)
intent.putExtra("user_email", email)
intent.putExtra("user_password", password)
startActivity(Intent(this, SignUp_Page2::class.java))
}
this is the second one
signUpGetCode.setOnClickListener {
startActivity(Intent(this, SignUp_Page3::class.java)) }
and this is the last one:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.signup3)
val intent = getIntent()
val email = intent.getStringExtra("user_email")
val password = intent.getStringExtra("user_password")
signUpComplete.setOnClickListener {
//Firebase Authentication to create user
FirebaseAuth.getInstance()
.createUserWithEmailAndPassword(
email,
password
)
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this, LogIn_Page::class.java))
Toast.makeText(
this,
"Account successfully created, please log in.",
Toast.LENGTH_LONG
).show()
finish()
} else {
Toast.makeText(this, "Something went wrong.", Toast.LENGTH_SHORT).show()
return#addOnCompleteListener
}
}
}
It looks like you are passing to the second page via Intent, but never pass from second to third page.
First retrieve the info in your second and third page.
private var email: String? = null
private var password: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (intent != null) {
email = intent.getStringExtra("user_email")
password = intent.getStringExtra("user_password")
} else if (savedInstanceState != null){
email = savedInstanceState.getString("user_email")
password = savedInstanceState.getString("user_password")
}
//TODO rest of onCreate
}
Try passing the info into the third page Intent.
Be careful about storing this data in the Intent. If you don't implement onSaveInstanceState in your second and third page, then you are going to lose the data on a rotation.
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("user_email", email)
outState.putString("user_password", password)
}
Also consider using Static String constants for your keys it will make everything much more manageable.
First1:
signUpNextButton.setOnClickListener {
val name = signUpFullname.text.toString()
val email = signUpEmail.text.toString()
val password = signUpPassword.text.toString()
//Sending datas with this method
val intent = Intent(this, SignUp_Page2::class.java)
intent.putExtra("user_email", email)
intent.putExtra("user_password", password)
//Starting another activity
startActivity(intent)
}
second1:
private var email: String? = null
private var password: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.signup2)
val intent = getIntent()
if (intent != null) {
email = intent.getStringExtra("user_email")
password = intent.getStringExtra("user_password")
} else if (savedInstanceState != null){
email = savedInstanceState.getString("user_email")
password = savedInstanceState.getString("user_password")
}
signUpGetCode.setOnClickListener {
val phone = signUpPhoneNumber.text.toString()
startActivity(Intent(this, SignUp_Page3::class.java))
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("user_email", email)
outState.putString("user_password", password)
}
third1:
private var email: String? = null
private var password: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.signup3)
val intent = getIntent()
if (intent != null) {
email = intent.getStringExtra("user_email")
password = intent.getStringExtra("user_password")
} else if (savedInstanceState != null) {
email = savedInstanceState.getString("user_email")
password = savedInstanceState.getString("user_password")
}
signUpComplete.setOnClickListener {
Toast.makeText(this, email + password, Toast.LENGTH_SHORT).show()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("user_email", email)
outState.putString("user_password", password)
}
Toast message give me the null null output.
FirebaseAuth.getInstance()
.createUserWithEmailAndPassword(
email.toString(),
password.toString()
)
.addOnCompleteListener {
if (it.isSuccessful) {
startActivity(Intent(this, LogIn_Page::class.java))
Toast.makeText(
this,
"Account successfully created, please log in.",
Toast.LENGTH_LONG
).show()
} else {
Toast.makeText(this, "Something went wrong.", Toast.LENGTH_SHORT).show()
return#addOnCompleteListener
}
}
this returns "something went wrong" to me
I have created an app in Android Studio (Kotlin) that registers users:
User Interface
An email/password user is created (Authentication) along with a corresponding database record (Realtime Database):
Datbase Structure
I have the login procedure working and I'm able to display the logged-in user's email address on MainActivity, BUT, I don't know how to display the user's name and favourite colour (from the database).
Can anyone help?
Thanks in advance for your time.
RegisterActivity.kt
class RegisterActivity : AppCompatActivity() {
private lateinit var mAuth : FirebaseAuth
private lateinit var viewModel: UserViewModel
public val USER: String = "user"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_register)
mAuth = FirebaseAuth.getInstance()
viewModel = ViewModelProvider(this).get(UserViewModel::class.java)
register_button.setOnClickListener {
val email = register_email.text.toString().trim()
val password = register_password.text.toString().trim()
val name = register_name.text.toString().trim()
val colour = register_colour.text.toString().trim()
mAuth.createUserWithEmailAndPassword(email, password)
val user = User()
user.email = email
user.name = name
user.colour = colour
viewModel.addUser(user)
}
}
}
LoginActivity.kt
class LoginActivity : AppCompatActivity() {
private lateinit var mAuth : FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
mAuth = FirebaseAuth.getInstance()
login_button.setOnClickListener {
val email = login_email.text.toString().trim()
val password = login_password.text.toString().trim()
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
//Login Success
val intent = Intent (this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TASK
}
startActivity(intent)
}else{
//Login Failure
task.exception?.message?.let {
toast(it)
}
}
}
}
}
}
MainActivity.kt (to display User details)
class MainActivity : AppCompatActivity() {
private val currentUser = FirebaseAuth.getInstance().currentUser
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
currentUser?.let { user ->
main_email.setText(user.email)
main_name.setText("Don't Know")
main_colour.setText("Don't Know")
}
}
}
Edit 3
LoginActivity.kt
class LoginActivity : AppCompatActivity() {
private lateinit var mAuth : FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
mAuth = FirebaseAuth.getInstance()
login_button.setOnClickListener {
val email = login_email.text.toString().trim()
val password = login_password.text.toString().trim()
loginUser (email, password)
}
}
private fun loginUser(email: String, password: String) {
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
//Login Success
val intent = Intent(this,MainActivity::class.java)
intent.putExtra("username",user.displayName)
intent.putExtra("email",user.email)
startActivity(intent)
}else{
//Login Failure
task.exception?.message?.let {
toast(it)
}
}
}
}
override fun onStart() {
super.onStart()
mAuth.currentUser?.let {
login()
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
//I have commented out the line below because it may not be required...
// private val currentUser = FirebaseAuth.getInstance().currentUser
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//I have commented out the lines below because they may not be required...
//currentUser?.let { user ->
//main_email.setText(user.email)
//main_name.setText("Don't Know")
//main_colour.setText("Don't Know")
//}
}
}
ERROR 1 : Overload resolution ambiguity on putExtra
ERROR 2 : Unresolved Reference on user.
When you launch at your login stage
mAuth.signInWithEmailAndPassword(email, password)
It has a callback that will be completed and successful when the user has been logged in, inside that callback, you are already logged in and that user now corresponds to one unique user ID, you can access that user ID by doing
val user = FirebaseAuth().getInstance().currentUser.uid
Then, here you can fetch that user data and pass it as an extra or bundle to your MainActivity, so the login process will take the time to log the user, fetch its data and send it to the MainActivity, this way you are not delaying any more time the user at your MainActivity
You can see that the user has been created once that successful callback is launch, and then in the Firebase console you can check for that user in the authentication tab
Edit
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
//Login Success, here you can get currentUser
val user = FirebaseAuth().getInstance().currentUser
login(user.displayName,user.email)
}else{
//Login Failure
task.exception?.message?.let {
toast(it)
}
}
}
Then, just add these two parameters to the login() method and just do a putExtra with those values and send those values as an extra to the main activity, so you are not fetching in your mainactivity and just sending the values from the login
Keep in mind that after .addonCompleteListener() the result is your current logged in user, so from here, you can get the currentUser information or the currentUser id
Edit 2
Inside the onComplete , just pass the data to the MainActivity
val intent = Intent(this,MainActivity::class.java)
intent.putExtra("username",user.displayName)
intent.putExtra("email",user.email)
startActivity(intent)
Then in your MainActivity get this extras
val extras = getIntent().extras
val userName: String?
val email: String?
if (extras != null) {
userName = extras.getString("userame")
email = extras.getString("email")
}
Then you already have the data from login into your MainActivity
Edit 3
To change the color, just change it from the MainActivity
your_text_view.setTextColor(ContextCompat.getColor(this,R.color.yourColor)
Please read this
I want to get The name of the user and his email from the database, i use this to set the data to the database :
createUser
fun createUser( name:String, email: String, password: String) {
mProgressbar.setMessage("Please wait..")
mProgressbar.show()
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = User(
name,
email
)
FirebaseDatabase.getInstance().getReference("Users")
.child(FirebaseAuth.getInstance().currentUser!!.uid)
.setValue(user).addOnCompleteListener(OnCompleteListener<Void> { task ->
if (task.isSuccessful) {
Toast.makeText(this, "Registered Successfully", Toast.LENGTH_LONG).show()
val Intent = Intent(applicationContext, MainActivity::class.java)
startActivity(Intent)
finish()
mProgressbar.dismiss()
} else {
//display a failure message
}
})
} else {
Toast.makeText(this, "Authentication failed.${task.exception}", Toast.LENGTH_SHORT).show()
mProgressbar.dismiss()
}
}
}
User
class User ( name: String, email: String) {
private var name: String? = name
private var email: String? = email
fun setName(Name: String) {
this.name = Name
}
fun getName(): String? {
return name
}
fun setEmail(Email: String) {
this.email = Email
}
fun getEmail(): String? {
return email
}
}
I need help please.I need help please.I need help please.I need help please.I need help please.I need help please.I need help please.I need help please.
internal var user: User? = null // declare user object outside onCreate Method
var ref = FirebaseDatabase.getInstance().getReference("Users").child(FirebaseAuth.getInstance().currentUser!!.uid)
val menuListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
user = dataSnapshot.getValue() as User
textView.text = user?.getName()
}
override fun onCancelled(databaseError: DatabaseError) {
// handle error
}
}
ref.addListenerForSingleValueEvent(menuListener)
The Code to get values from database
val menuListener = object : ValueEventListener {
override fun onCancelled(databaseError: DatabaseError) {
// handle error
}
override fun onDataChange(dataSnapshot: DataSnapshot) {
user = dataSnapshot.getValue(User::class.java)
textView.text = user?.name
}
}
and i have to change User Class code to:
#IgnoreExtraProperties
data class User(
var name: String? = "",
var email: String? = ""
) {
#Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
"uid" to name,
"author" to email
)
}
}