my app keep crashing after tryed to connect it to firebase kotlin - android

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?){
}
} ```

Related

Firebase authentication issues, Kotlin

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

Restrict User for only Fingerprint Authentication

Hy, I am a newbie currently learning Mobile development.
I am developing an application in which when the user presses the login button it will only give the option of Fingerprint authentication. but in my case, It gives options to the user to either uses Fingerprint or face authentication. How can I restrict the user to only Fingerprint authentication?
Here I am using the following Code:
package com.example.fingerprintauth
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.biometric.BiometricPrompt
import android.widget.Button
import android.widget.Toast
import androidx.core.content.ContextCompat
import java.util.concurrent.Executor
class MainActivity : AppCompatActivity() {
private lateinit var executor: Executor
private lateinit var biometricPrompt: BiometricPrompt
private lateinit var prompt: BiometricPrompt.PromptInfo
//private var flag =0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
executor=ContextCompat.getMainExecutor(this)
biometricPrompt= BiometricPrompt(this#MainActivity,executor,object:BiometricPrompt.AuthenticationCallback(){
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
//authStatusTv.text = "Authentication Error: $errString"
Toast.makeText(this#MainActivity,"Authentication Error: $errString",Toast.LENGTH_SHORT).show()
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Toast.makeText(this#MainActivity,"Authentication Success",Toast.LENGTH_SHORT).show()
startActivity(
Intent(
this#MainActivity, Home::class.java
)
)
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
//authStatusTv.text = "Authentication Failed"
Toast.makeText(this#MainActivity,"Authentication Failed",Toast.LENGTH_SHORT).show()
}
})
val promptInfo=BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Login Using Fingerprint authentication")
.setDeviceCredentialAllowed(true)
//.setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
.build()
var authbtn = findViewById<Button>(R.id.authbtn)
authbtn.setOnClickListener {
biometricPrompt.authenticate(promptInfo)
}
}
}

How to set up autoCompleteTextView in dialog in Kotlin? I am fetching the data from firebase and using that to populate the autocomplete suggestions

** This is what I have tried till now. I am creating a list of items from firebase and using that I want to populate autoCompleteParticularName from the dialog. The dialog is popping up but there is no response. My autocompleteAdapter is fine as when I initialized it from the addNewParticularBtn.setOnClickListener, then it is responding but I don't want that as I want to update the contents from onStart().
I request help, I am very new to Android Development. **
package com.sushant.quickbills.activity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.AutoCompleteTextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.ktx.database
import com.google.firebase.ktx.Firebase
import com.sushant.quickbills.R
import com.sushant.quickbills.data.AutoCompleteParticularNameAdapter
import com.sushant.quickbills.data.ITEMS_FIELD
import com.sushant.quickbills.data.ITEMS_NAME_FIELD
import com.sushant.quickbills.model.Item
import kotlinx.android.synthetic.main.activity_new_bill.*
import kotlinx.android.synthetic.main.pop_up_new_particular.view.*
enter code here
class NewBillActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
private lateinit var dialogBuilder: AlertDialog.Builder
private lateinit var dialog: AlertDialog
private lateinit var database: DatabaseReference
private val itemList = arrayListOf<Item>()
private lateinit var addNewParticularView: View
private lateinit var autoCompleteParticularName: View
private lateinit var autoCompleteParticularNameAdapter: AutoCompleteParticularNameAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_bill)
//Initialise the variables:-
database = Firebase.database.reference
auth = Firebase.auth
addNewParticularView = layoutInflater.inflate(R.layout.pop_up_new_particular, null, false)
autoCompleteParticularName = addNewParticularView.choose_new_particular_name_pop_up
autoCompleteParticularNameAdapter =
AutoCompleteParticularNameAdapter(this, ArrayList(itemList))
dialogBuilder = AlertDialog.Builder(this).setView(addNewParticularView)
dialog = dialogBuilder.create()
//Set up Adapters
(autoCompleteParticularName as AutoCompleteTextView?)?.setAdapter(autoCompleteParticularNameAdapter)
//Set up click listeners
addNewParticularBtn.setOnClickListener {
//Show the dialog
dialog.show()
}
}
override fun onStart() {
//Item Listener for autocomplete suggestions and fast response
val currItemRef =
database.child(ITEMS_FIELD).child(auth.currentUser!!.uid).orderByChild(
ITEMS_NAME_FIELD
)
val itemListener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
itemList.clear()
for (child in snapshot.children) {
val item = child.getValue(Item::class.java)
if (item != null)
itemList.add(item)
autoCompleteParticularNameAdapter.notifyDataSetChanged()
}
}
override fun onCancelled(error: DatabaseError) {
Log.w("Error", "loadItemList:onCancelled", error.toException())
}
}
currItemRef.addValueEventListener(itemListener)
super.onStart()
}
}
Looks like you need to set a list of items to the adapter before you invoke:
autoCompleteParticularNameAdapter.notifyDataSetChanged()

I am not able to validate my new activity

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

Why when update data in firebase the data in recyclerView duplicated

if I any change in firebase like delete, update. The data in recyclerView is duplicated if any of those CRUD occur, so I added temporary swipeRefresh to refresh the activity but this solution doesn't make sense.
This image below explain when I update data in firebase and what happend in RecyclerView
MainDashBoard.kt
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
class MainDashBoard : AppCompatActivity(), OnItemPatientClickListener{
data class PatientDataItem(val patientName: String, val patientMessage: String)
private lateinit var auth: FirebaseAuth
lateinit var swipeRefreshLayout: SwipeRefreshLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_dash_board)
var database = FirebaseDatabase.getInstance().reference
var patientDataItems = ArrayList<PatientDataItem>()
val patientRecycler = findViewById<RecyclerView>(R.id.patient_recycler)
val patienDashboardprogressBar = findViewById<ProgressBar>(R.id.patientDashboardprogressBar)
val noDataMain = findViewById<TextView>(R.id.no_data_main_dashboard)
swipeRefreshLayout = findViewById(R.id.swipe)
patientRecycler.layoutManager = LinearLayoutManager(this)
patientRecycler.adapter = MainDashboardAdapter(patientDataItems, this)
auth = FirebaseAuth.getInstance()
val user = auth.currentUser
val patientsListener = object : ValueEventListener {
override fun onDataChange(p0: DataSnapshot) {
val patients = p0.child("users").child(user!!.uid)
if (p0.value == null ){
noDataMain.visibility = View.VISIBLE
}else{
noDataMain.visibility = View.GONE
for (i in p0.children){
var patientName = i.key.toString()
var patientMessage = i.value.toString()
patientDataItems.add(PatientDataItem(patientName, patientMessage))
}
}
patientRecycler.scrollToPosition(patientDataItems.size-1)
patienDashboardprogressBar.visibility = View.GONE
}
override fun onCancelled(error: DatabaseError) {
println("error")
}
}
database.child("location").child("users").child(user!!.uid).addValueEventListener(patientsListener)
// database.child("location").addValueEventListener(postListener)
swipeRefreshLayout.setOnRefreshListener {
startActivity(intent);
Handler(Looper.getMainLooper()).postDelayed(Runnable {
swipeRefreshLayout.isRefreshing = false
}, 4000)
}
}
override fun onItemClick(patientDataItems: PatientDataItem) {
val patientMacAddressName = patientDataItems.patientName
val dashboardIntent = Intent(this, DashboardActivity::class.java)
dashboardIntent.putExtra("macAddressNamePatient", patientMacAddressName)
startActivity(dashboardIntent)
}
}
MainDashBoardAdapter.kt
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.example.ard_here.R
class MainDashboardAdapter(private val patientDataSet: ArrayList<MainDashBoard.PatientDataItem>,
private val onPatientClickListener: OnItemPatientClickListener): RecyclerView.Adapter<MainDashboardAdapter.PatientCustomHolder>(){
override fun getItemCount(): Int {
return patientDataSet.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PatientCustomHolder {
var layoutInflater = LayoutInflater.from(parent?.context)
var cellForRow = layoutInflater.inflate(R.layout.main_patient_layout, parent, false)
return PatientCustomHolder(cellForRow)
}
override fun onBindViewHolder(holder: PatientCustomHolder, position: Int) {
holder.bindItems(patientDataSet[position])
holder.patientLayout.setOnClickListener {
onPatientClickListener.onItemClick(patientDataSet[position])
}
}
class PatientCustomHolder(v: View): RecyclerView.ViewHolder(v){
val patientLayout: ConstraintLayout = v.findViewById(R.id.patient_layout)
val patientName: TextView = v.findViewById(R.id.patient_name)
val patientMessage : TextView = v.findViewById(R.id.patient_message)
fun bindItems(data_item: MainDashBoard.PatientDataItem){
patientName.text = data_item.patientName
patientMessage.text = data_item.patientMessage
}
}
}
OnItemPatientClickListener.kt
interface OnItemPatientClickListener {
fun onItemClick(patientDataItems: MainDashBoard.PatientDataItem)
}
clear your data container then bind it again in recyclerview.
or you have mvvm pattern, you can use live data to observe data source and if there is any changes, your activity will easily notified and make some ui changes
Since you're reading the data with addValueEventListener, which means that:
The data from the path is read from the database right away, and passed to your onDataChange.
The client the continues monitor the path, and if anything changes it calls your onDataChange again with all data at the path.
In your onDataChange you're only ever adding data to patientDataItems. That works well the first time the data is loaded, so #1 above. But if you add or change a single child node (#2 above), you get called with all data at the path again. So that's when you end up duplicating the items in the view.
The simplest solution is to clear patientDataItems whenever onDataChange get called:
override fun onDataChange(p0: DataSnapshot) {
patientDataItems.clear()
...

Categories

Resources