I am having some issues with Firebase auth. I'm building an app using using Kotlin but keep retrieving the error 'W/System: Ignoring header X-Firebase-Locale because its value was null.'
I had this working previously, when I had set up the application using activities. I've now moved towards MVP architecture, but this seems to have broken my firebase authentication. I have also ensured that Email/Password sign in method has been enabled in the Firebase console.
If anyone could please take a look and hopefully you can see where I am going wrong. Many thanks.
SignInView
package org.wit.hikingtrails.views.signIn
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import org.wit.hikingtrails.databinding.ActivitySignInBinding
import com.google.firebase.auth.FirebaseAuth
import org.wit.hikingtrails.activities.SignUpActivity
import org.wit.hikingtrails.views.hikeList.HikeListView
import org.wit.hikingtrails.views.signUp.SignUpView
class SignInView : AppCompatActivity() {
lateinit var presenter: SignInPresenter
private lateinit var binding: ActivitySignInBinding
private lateinit var firebaseAuth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
presenter = SignInPresenter( this)
super.onCreate(savedInstanceState)
binding = ActivitySignInBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
binding.textView.setOnClickListener {
val intent = Intent(this, SignUpView::class.java)
startActivity(intent)
}
binding.button.setOnClickListener {
val email = binding.emailEt.text.toString()
val pass = binding.passET.text.toString()
if (email.isNotEmpty() && pass.isNotEmpty()) {
presenter.doLogin(email, pass)
} else {
Toast.makeText(this, "Empty Fields Are not Allowed !!", Toast.LENGTH_SHORT).show()
}
}
}
override fun onStart() {
super.onStart()
if(firebaseAuth.currentUser != null){
val intent = Intent(this, HikeListView::class.java)
startActivity(intent)
}
}
}
SignInPresenter:
package org.wit.hikingtrails.views.signIn
import android.content.ContentValues.TAG
import android.content.Intent
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.google.firebase.auth.FirebaseAuth
import org.wit.hikingtrails.views.hikeList.HikeListView
import timber.log.Timber
import timber.log.Timber.i
class SignInPresenter (val view: SignInView) {
private lateinit var loginIntentLauncher : ActivityResultLauncher<Intent>
init{
registerLoginCallback()
}
var auth: FirebaseAuth = FirebaseAuth.getInstance()
fun doLogin(email: String, pass: String) {
// view.showProgress()
auth.signInWithEmailAndPassword(email, pass).addOnCompleteListener(view) { task ->
if (task.isSuccessful) {
val launcherIntent = Intent(view, HikeListView::class.java)
loginIntentLauncher.launch(launcherIntent)
} else {
i("Login failed:")
// val launcherIntent = Intent(view, HikeListView::class.java)
// loginIntentLauncher.launch(launcherIntent)
}
// view.hideProgress()
}
}
private fun registerLoginCallback(){
loginIntentLauncher =
view.registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{ }
}
}
For anyone that was having the same issue: The issue was with my API key. In kotlin, to debug, I used Timber.i( "signInWithCredential:failure ${task.exception?.message}") within the else statement of doLogin() in the presenter
Related
When I click "sign in button" I got
"W/System: Ignoring header X-Firebase-Locale because its value was null"
"D/TrafficStats: tagSocket(90) with statsTag=0xffffffff, statsUid=-1" in run tab
This is my signin page codes
package com.deniz.cywm
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.EditText
import android.widget.Toast
import com.deniz.cywm.databinding.ActivityMainBinding
import com.deniz.cywm.databinding.ActivityMainKayitOlBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.FirebaseDatabase
class MainKayitOl : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainKayitOlBinding = ActivityMainKayitOlBinding.inflate(layoutInflater)
val view = binding.root
auth = FirebaseAuth.getInstance() /
setContentView(view)
binding.girisDon.setOnClickListener(){
intent = Intent(applicationContext,MainActivity::class.java)
startActivity(intent)
}
binding.kytButon.setOnClickListener(){
var kemail = binding.email.text.toString()
var ksifre = binding.sifre.text.toString()
auth.createUserWithEmailAndPassword(kemail, ksifre)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
Log.d("TAG", "createUserWithEmail:success")
val user = auth.currentUser
} else {
Log.w("TAG", "createUserWithEmail:failure", task.exception)
Toast.makeText(baseContext, "Authentication failed.",
Toast.LENGTH_SHORT).show()
}
}
}
}
}
I am creating an app that right now is just supposed to be able to use Firebase authentication with mvvm as a standard to get some kind of seperation of concerns. So i have a database class that uses Firebase and gets an injection from Dagger hilt to be able to use Authentication from firebase. Now i am trying to check if the user is logged in. So i type the auth.getCurrentUser(). This does only give me the possibility to check if a user exist and with firebase when you check this and you have deleted the user while you are testing it does not update the value so it's still logged in for another hour when you have deleted the user. If you check around the internet about this you get the answer to use the authstatelistener. My question is though how to use this together with mvvm? is there a way to do this when i have my clases seperated by a viewmodel a repository and a database.
My classes look like this right now.
Database: //This has a comment written in it that has some use for the problem
import com.google.android.gms.tasks.Task
import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.lang.Exception
import javax.inject.Inject
import javax.security.auth.callback.Callback
class FirDatabase #Inject constructor(var auth : FirebaseAuth) {
suspend fun register(user: User) : Task<AuthResult>{
return auth.createUserWithEmailAndPassword(user.email, user.password)
}
suspend fun checkIfUserExist() : Boolean? {
//i would like to be able to check it right here somehow
println("Currentuser " + auth.currentUser?.uid)
return auth.currentUser != null
}
}
Repository:
import androidx.lifecycle.MutableLiveData
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks.await
import com.google.firebase.auth.AuthResult
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class AuthRepository #Inject constructor (private val database: FirDatabase) : IAuthRepository {
override suspend fun register(user: User) : Resource<AuthResult> {
return try{
val response = database.register(user)
val result = response.result
if(response.isSuccessful && result != null){
Resource.Success(result)
}else{
Resource.Error(response.exception?.message.toString())
}
}catch (e: Exception){
Resource.Error(e.message ?: "An Error occurred")
}
}
override suspend fun CheckIfloggedIn() : Resource<Boolean>{
return try{
val user = database.checkIfUserExist()
if(user != false){
Resource.IsLoggedIn("User is already logged in" )
}else{
Resource.IsNotLoggedIn("User is not logged in")
}
}catch(e: Exception){
Resource.Error(e.message ?: "An Error occurred")
}
}
}
ViewModel:
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
#HiltViewModel
class AuthViewModel #Inject constructor(private val repository: AuthRepository, private val dispatchers: DispatcherProvider) : ViewModel(){
sealed class AuthEvent{
class Success(val result: String): AuthEvent()
class Failure(val errorText: String): AuthEvent()
object Loading : AuthEvent()
object LoggedIn : AuthEvent()
object NotRegistered : AuthEvent()
object NotLoggedIn : AuthEvent()
object Empty : AuthEvent()
}
private val _registering = MutableStateFlow<AuthEvent>(AuthEvent.Empty)
val registering : StateFlow<AuthEvent> = _registering
private val _checkUserIsLoggedIn = MutableStateFlow<AuthEvent>(AuthEvent.Empty)
val checkUserIsLoggedIn : StateFlow<AuthEvent> = _checkUserIsLoggedIn
fun register(user: User){
viewModelScope.launch(dispatchers.io) {
_registering.value = AuthEvent.Loading
when(val authResponse = repository.register(user)){
is Resource.Error -> _registering.value = AuthEvent.Failure(authResponse.message!!)
is Resource.Success -> {
val response = authResponse.data!!.user
_registering.value = AuthEvent.Success("Success")
}
}
}
}
fun CheckIfUserIsLoggedIn()
{
viewModelScope.launch(dispatchers.io) {
when(val isUserLoggedIn = repository.CheckIfloggedIn()){
is Resource.IsLoggedIn -> _checkUserIsLoggedIn.value = AuthEvent.LoggedIn
is Resource.IsNotLoggedIn -> _checkUserIsLoggedIn.value = AuthEvent.NotLoggedIn
is Resource.Error -> _checkUserIsLoggedIn.value = AuthEvent.Failure(isUserLoggedIn.message!!)
}
}
}
}
I have followed tutorials from this dude https://www.youtube.com/watch?v=ct5etYgB5pQ
and i have already seen alot of the documentation on this page like this for example Firebase: how to check if user is logged in?
and here How does the firebase AuthStateListener work?. So with further investigations into the answer you gave me i have come up with this solution... but it is not really working? why is this?
Repository function:
override fun CheckIfloggedIn() = callbackFlow<Resource<Boolean>>{
val isUserLoggedIn = flow<Resource<Boolean>>{
database.checkIfUserExist().collect { isLoggedIn ->
if(isLoggedIn){
Resource.Success(isLoggedIn)
}else{
Resource.Error("User is not logged in")
}
}
}
}
Database function:
fun checkIfUserExist() = callbackFlow {
val authStatelistener = FirebaseAuth.AuthStateListener {auth ->
trySend(auth.currentUser == null)
}
auth.addAuthStateListener(authStatelistener)
awaitClose {
auth.removeAuthStateListener(authStatelistener)
}
}
I created a simple login and sup app and connect it to firebase.
so far the logging layout does not even show up it's just crushing while lanching which makes me so confused?
[![eroo message][1]][1]
this is my login/main activity
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
class MainActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
val button: Button = findViewById(R.id.buGotosub)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
button.setOnClickListener {
startActivity(Intent(this,SubscribAcc::class.java))
finish()
}
}
public override fun onStart() {
super.onStart()
// Check if user is signed in (non-null) and update UI accordingly.
val currentUser = auth.currentUser
updarUI(currentUser)
}
fun updarUI(currentUser : FirebaseUser?){
}
} ```
I created a new empty activity for my project but I am getting an error. The activity file as well as the layout file is shown in red color. I tried creating an intent object from MainActivity, in order to start this activity but received the following error
Classifier 'Details' does not have a companion object, and thus must
be initialized here
I've attached a screenshot of my android studio.
Code for new activity
package com.example.safetyapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class Details : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
}
}
package com.example.safetyapp
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.firebase.ui.auth.AuthUI
import com.google.firebase.auth.FirebaseAuth
class MainActivity : AppCompatActivity() {
final val AUTH_REQUEST_CODE = 7192
lateinit var firebaseAuth:FirebaseAuth
lateinit var listener: FirebaseAuth.AuthStateListener
lateinit var providers: List<AuthUI.IdpConfig>
override fun onStart(){
super.onStart()
firebaseAuth.addAuthStateListener(listener)
}
override fun onStop(){
super.onStop()
if(listener!=null){
firebaseAuth.removeAuthStateListener(listener)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button2 = findViewById<Button>(R.id.button2)
val defence = findViewById<Button>(R.id.Defence)
button2.setOnClickListener{
val myintent = Intent(this, Details::class.java)
}
init()
}
private fun init() {
providers = arrayListOf(AuthUI.IdpConfig.PhoneBuilder().build(),
AuthUI.IdpConfig.EmailBuilder().build())
firebaseAuth = FirebaseAuth.getInstance()
listener = object:FirebaseAuth.AuthStateListener{
override fun onAuthStateChanged(p0: FirebaseAuth) {
val user = p0.currentUser
if(user!= null){
// Do something
}
else{
startActivityForResult(AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.setLogo(R.drawable.logo)
.build(),AUTH_REQUEST_CODE)
}
}
}
}
}
You didn't import the Details class, add this line between your MainActivity class imports
import com.example.safetyapp.Details
I'm trying to figure out how to add more users in a Login app made with Kotlin, there's no database or whatever, the accounts are hardcoded into the program, I heard about using arrays but I'm not too sure on how to implement it in this context.
Thank you to anyone who reads this.
package com.example.textandviewbinding
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import android.widget.Toast
import com.example.textandviewbinding.databinding.ActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import java.util.*
import kotlin.system.exitProcess
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.btnSubmit.setOnClickListener {
validateUser(it)
}
}
private fun addTextView(text:String){
val textView1 = TextView(this)
textView1.text = text
textView1.textSize = 16f
textView1.textAlignment = View.TEXT_ALIGNMENT_CENTER
binding.myLayout.addView(textView1)
}
private fun validateUser(it: View) {
val username = binding.editUsername.text
val password = binding.editPassword.text
if (username.toString().equals("joed", ignoreCase = true) && password.toString().equals("1234")) {
// Toast.makeText(this, "Logged In!", Toast.LENGTH_SHORT).show()
val message = getString(R.string.welcome_message,username)
Snackbar.make(it, message, Snackbar.LENGTH_LONG)
.setAction("Show details.. ", { addTextView("Login Successful: ${Calendar.getInstance().time}" ) })
.show()
} else {
Toast.makeText(this, "Invalid Details", Toast.LENGTH_SHORT).show()
exitProcess(-1)
}
}
private fun displayToast() {
Toast.makeText(this, "Login Successful ${Calendar.getInstance().time}", Toast.LENGTH_SHORT).show()
}
}
1- Create a class called User , ex:
data class User(
var id : Int
var name : String
)
2- Create an Array of users using the User model in your MainActivity :
private val users = ArrayList<User>()
3- Add users to the array :
users.add(User(1,"Alex"))
users.add(User(2,"Andrei"))