Probem while reading field in document from firestore in kotlin - android

private fun logInRegisteredUser() {
if (validateLoginDetails()) {
// Show the progress dialog.
showProgressDialog(resources.getString(R.string.please_wait))
// Get the text from editText and trim the space
val email = et_email.text.toString().trim { it <= ' ' }
val password = et_password.text.toString().trim { it <= ' ' }
// Log-In using FirebaseAuth
FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
// Hide the progress dialog
hideProgressDialog()
if (task.isSuccessful) {
val currrentUser= FirebaseAuth.getInstance().currentUser
/* if (currrentUser != null) {
val washingtonre = mFireStore.collection("use").document(currrentUser.uid)
washingtonre.get().addOnSuccessListener(object: OnSuccessListener<DocumentSnapshot> {
override fun onSuccess(documentSnapshot:DocumentSnapshot) {
if (documentSnapshot.exists())
{
var arrList = ArrayList<String>()
arrList = documentSnapshot.get("organization") as ArrayList<String>
Toast.makeText(applicationContext,"$arrList",Toast.LENGTH_SHORT).show()
for (i in 0 until arrList.size)
{
//Traversing the list
}
}
}
})
}*/
if (currrentUser != null) {
val c = FirebaseFirestore.getInstance()
val d = c.collection("users").document(currrentUser.uid)
d.get().addOnSuccessListener { document ->
if (document != null) {
arrList = document.get("organization") as ArrayList<String>
if (arrList.size>1) {
val intent = Intent(this#LoginActivity, companyDetails::class.java)
intent.putStringArrayListExtra("key", arrList)
startActivity(intent)
Toast.makeText(applicationContext, "$arrList", Toast.LENGTH_SHORT).show()
}
else if (arrList.size<=1) {
val intent = Intent(this#LoginActivity, MainActivity::class.java)
startActivity(intent)
}
} else {
Log.d("Tag", "No such document")
}
}
.addOnFailureListener { exception ->
Log.d("TAG", "get failed with ", exception)
}
}
} else {
showErrorSnackBar(task.exception!!.message.toString(), true)
}
}
}
}
This is my code to validate login details. When login button is pressed this code is executed.
Now I want to check an array field named 'organization' in firestore to check wheather the user has two or more companies to his credits. Now when I run the app if organization field doesnt exist my app crashes. I want the app to work even if the organization field doesnt exist. How to change the codes for that?enter image description here

Related

How to manage Login Validation with Room in Kotlin?

I'm trying to make work the Login Validation form, but the program stops then reaches the second if, and I have Invalid email output. Run is clear and out of mistakes. Can't figure out what I'm doing wrong and why emailList is null
private fun logIn() {
val email = binding.editEmailAddress.text.toString()
val password = binding.editPassword.text.toString()
if (inputCheck(email, password)) {
mLoginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
val emailList = mLoginViewModel.getUserEmail(email)
if (emailList != null) {
if (emailList.password == password) {
Toast.makeText(requireContext(), "Logged in as $email", Toast.LENGTH_LONG)
.show()
findNavController().navigate(R.id.action_loginFragment_to_listFragment)
} else {
Toast.makeText(requireContext(), "Invalid password", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(requireContext(), "Invalid email", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(requireContext(), "Fill out blank fields", Toast.LENGTH_LONG).show()
}
}
private fun inputCheck(email: String, password: String): Boolean {
return !(TextUtils.isEmpty(email) || TextUtils.isEmpty(password))
}
LoginViewModel
fun getUserEmail(email: String): User? {
var checker: User? = null
viewModelScope.launch(Dispatchers.IO) {
checker = repository.getUserEmail(email)
}
return checker
}
fun getUserEmail(email: String): User? {
var checker: User? = null
viewModelScope.launch(Dispatchers.IO) {
checker = repository.getUserEmail(email)
}
return checker
// Will return null always because this is not waiting to assign value by above repository method
}
Insted you can do this
suspend fun getUserEmail(email: String): User? {
return repository.getUserEmail(email)
}
And in Activity Or Fragment
mLoginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
lifecycleScope.launch {
val emailList = mLoginViewModel.getUserEmail(email)
}
Don't Know what error you are getting on above code if that not works then use below code
mLoginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
CoroutineScope(Dispatchers.IO).launch {
val emailList = mLoginViewModel.getUserEmail(email)
withContext(Dispatchers.Main){
//Do whatever with emailList
}
}

Why is the user details vanishes from the Firestore?

I am using Firebase PhoneAuth for user registration with my app. Users are verified successfully and started using the app without any issues. But, It happened to me a couple of times that user details vanished from Firestore database, not all users details have gone though. When I check the collection users in the Firestore, the document does exist for the user but some data was gone, in fact, it's overwritten the old data as if this is new user registration (However, the User UID under the Authentication is remain same). For example, the default value is user_type = "customer", as you can see in the fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential). Later I change this value accordingly to my need and when this issue happens the changes I made to this field and other fields are changed back to the default values.
Following is the code in my SignInWithPhone which will be called from the SplashScreen
class SigninWithPhoneActivity: BaseActivity() {
private lateinit var binding: ActivitySignInWithPhoneBinding
private lateinit var mAuth: FirebaseAuth
var code = ""
var number = ""
var phoneNumber = ""
var storedOtpID = ""
private lateinit var resendToken: PhoneAuthProvider.ForceResendingToken
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySignInWithPhoneBinding.inflate(layoutInflater)
setContentView(binding.root)
}
mAuth = FirebaseAuth.getInstance()
binding.btnGetOtp.setOnClickListener {
code = binding.etCountryCode.text.toString().trim()
number = binding.etMobileNumber.text.toString().trim()
phoneNumber = code + number
if (number.isNotEmpty()) {
binding.etMobileNumber.isEnabled = false
binding.flOtp.visibility = View.VISIBLE
binding.btnGetOtp.visibility = View.GONE
binding.btnSignIn.visibility = View.VISIBLE
sendVerificationCode(phoneNumber)
} else {
Toast.makeText(this, "Please enter a valid mobile number", Toast.LENGTH_LONG).show()
}
}
binding.btnSignIn.setOnClickListener {
val otp = binding.etOtp.text.toString().trim()
if (otp.isNotEmpty() || otp.length != 6) {
verifyVerificationCode(otp)
} else {
Toast.makeText(this, "Please enter the OTP received through SMS", Toast.LENGTH_LONG)
.show()
}
}
}
private val mCallBack: PhoneAuthProvider.OnVerificationStateChangedCallbacks =
object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
val code = credential.smsCode
if (code != null) {
binding.etOtp.setText(code)
binding.pbOtp.visibility = View.GONE
}
}
override fun onVerificationFailed(p0: FirebaseException) {
binding.etMobileNumber.isEnabled = true
binding.flOtp.visibility = View.GONE
binding.btnGetOtp.visibility = View.VISIBLE
binding.btnSignIn.visibility = View.GONE
Toast.makeText(this#SigninWithPhoneActivity, "Login Failed", Toast.LENGTH_LONG)
.show()
}
override fun onCodeSent(otpID: String, token: PhoneAuthProvider.ForceResendingToken) {
super.onCodeSent(otpID, token)
Toast.makeText(
this#SigninWithPhoneActivity,
"OTP is send to your number",
Toast.LENGTH_LONG
).show()
storedOtpID = otpID
resendToken = token
}
}
private fun sendVerificationCode(phoneNumber: String) {
binding.pbOtp.visibility = View.VISIBLE
Toast.makeText(this#SigninWithPhoneActivity, "Sending OTP", Toast.LENGTH_LONG).show()
val options = PhoneAuthOptions.newBuilder(mAuth!!)
.setPhoneNumber(phoneNumber)
.setTimeout(60L, TimeUnit.SECONDS)
.setActivity(this)
.setCallbacks(mCallBack)
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
}
private fun verifyVerificationCode(code: String) {
Toast.makeText(
this#SigninWithPhoneActivity,
"Verifying credentials",
Toast.LENGTH_LONG
).show()
val credential = PhoneAuthProvider.getCredential(storedOtpID, code)
signInWithPhoneAuthCredential(credential)
}
private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val firebaseUser: FirebaseUser = task.result!!.user!!
val userPreliminaryDetails = User(
firebaseUser.uid,
user_type = "customer",
mobile = binding.etMobileNumber.text.toString()
)
FirestoreClass().checkIfUserAlreadyExist(
this#SigninWithPhoneActivity,
firebaseUser.uid,
userPreliminaryDetails
)
} else {
showErrorSnackBar(task.exception!!.message.toString(), true)
if (task.exception is FirebaseAuthInvalidCredentialsException) {
binding.etMobileNumber.isEnabled = true
binding.flOtp.visibility = View.GONE
binding.etOtp.text?.clear()
binding.btnGetOtp.visibility = View.VISIBLE
binding.btnGetOtp.text = "Resend OTP"
binding.btnSignIn.visibility = View.GONE
Toast.makeText(this, "OTP entered is wrong", Toast.LENGTH_LONG).show()
}
}
}
}
fun userRegistrationSuccess() {
finish()
startActivity(Intent(this, ServiceAreaActivity::class.java))
Toast.makeText(this, "Signed Up successful", Toast.LENGTH_LONG).show()
}
fun userSignInSuccess() {
finish()
startActivity(Intent(this, ServiceAreaActivity::class.java))
Toast.makeText(this, "Signed in successfully", Toast.LENGTH_LONG).show()
}
}
EDIT:
The following function is called to check if the user already exists and accordingly sign in or register a new user.
fun checkIfUserAlreadyExist(
activity: SigninWithPhoneActivity, userId: String, userDetails: User
) {
mFireStore.collection("users")
.whereEqualTo(Constants.USER_ID, userId)
.get()
.addOnSuccessListener { document ->
if (document.documents.size > 0) {
activity.userSignInSuccess()
} else {
FirestoreClass().registerUser(activity, userDetails)
}
}
.addOnFailureListener { e ->
}
}
private fun registerUser(activity: SigninWithPhoneActivity, userInfo: User) {
mFireStore.collection(Constants.USERS)
.document(userInfo.user_id)
.set(userInfo, SetOptions.merge())
.addOnSuccessListener {
activity.userRegistrationSuccess()
}
.addOnFailureListener { e ->
activity.hideProgressDialog()
}
}

Return a boolean function only when api call is complete in android [duplicate]

This question already has answers here:
How to return a list from Firestore database as a result of a function in Kotlin?
(3 answers)
Closed 2 years ago.
I have a function which makes a call to Firebase Firestore db and returns the value of the same.
Here, the function returns the boolean value before the api fetching is complete. I guess the addOnCompleteListener is a sync function; so how do I make the checkProfileAvailable async.
private fun checkProfileAvailable(): Boolean {
val userMail = FirebaseAuth.getInstance().currentUser!!.email!!
var cgpa = ""
var name = ""
var end = ""
var subjects = ""
var board = ""
db.collection("users")
.document(userMail)
.collection("dsfdsafs")
.document("fgdsgfds")
.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
if (task.result?.data?.isNotEmpty() == true) {
Log.d(TAG, task.result!!.data.toString())
cgpa = task.result!!.data!!["cgpa"].toString()
name = task.result!!.data!!["schoolName"].toString()
end = task.result!!.data!!["endYear"].toString()
subjects = task.result!!.data!!["subjects"].toString()
board = task.result!!.data!!["board"].toString()
}
} else {
Log.w(TAG, "Error getting documents.", task.exception)
}
}
.addOnFailureListener {
Log.d(TAG, it.message.toString())
}
return !(cgpa == "" || name == "" || end == "" || subjects == "" || board == "")
}
You can use a callback since you have to wait before sending a result back. Using your code
private fun checkProfileAvailable(callback:(Boolean)-> Unit) {
val userMail = FirebaseAuth.getInstance().currentUser!!.email!!
var cgpa = ""
var name = ""
var end = ""
var subjects = ""
var board = ""
db.collection("users")
.document(userMail)
.collection("dsfdsafs")
.document("fgdsgfds")
.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
if (task.result?.data?.isNotEmpty() == true) {
Log.d(TAG, task.result!!.data.toString())
cgpa = task.result!!.data!!["cgpa"].toString()
name = task.result!!.data!!["schoolName"].toString()
end = task.result!!.data!!["endYear"].toString()
subjects = task.result!!.data!!["subjects"].toString()
board = task.result!!.data!!["board"].toString()
//call the callback here
callback(//pass here the boolean condition you were returning)
}
} else {
Log.w(TAG, "Error getting documents.", task.exception)
//you should handle this case
}
}
.addOnFailureListener {
Log.d(TAG, it.message.toString())
//you should handle this case
}
}

how can i paginate data in kotlin using firestore?

I have created adapter which is fetching data from firestore.
But I need to paginate it in kotlin, can you help me?
private fun fetch(){
try {
mShared = getSharedPreferences("mShared", 0)
val path = mShared!!.getString("governorate", "Suez").toString()
dp!!.collection("Fraise")
.whereEqualTo("governorate", "${path}")
.orderBy("time")
.limit(5)
.get()
.addOnCompleteListener {
data.addAll(it.result.toObjects(Data::class.java))
adapter = Fraise_adapter(this, data)
adapter.notifyDataSetChanged()
recyclerView.adapter = adapter
}
} catch (e: Exception) {
Toast.makeText(this, "Please choose a governorate from the main activity", Toast.LENGTH_LONG).show()
}
}
This works for me. For Firestore pagination.
private fun first(){
val first = collectionRef
.orderBy("priority")
.limit(3)
first.get()
.addOnSuccessListener {
var lastVisible = it.documents[it.size()-1]
var text = ""
for (document in it) {
val note = document.toObject(Note::class.java)
note.noteId = document.id
text+= note.title+"\n"
}
binding.tvShow.append(text)
binding.btnShow.setOnClickListener {
val next = collectionRef
.orderBy("priority")
.startAfter(lastVisible)
.limit(3)
next.get()
.addOnSuccessListener {
var text = ""
for (document in it) {
val note = document.toObject(Note::class.java)
note.noteId = document.id
text+= note.title+"\n"
}
if(it.size()>0) {
text += "--------------------------\n\n"
binding.tvShow.append(text)
lastVisible = it.documents[it.size()-1]
}
}
}
}
.addOnFailureListener {
Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show()
Log.d(TAG, it.message)
}
}

Facebook info not showing

I'm trying to get the user info with this code but is not showing on the activity
The profile picture and the name are not creating a new user on the base
What am I missing?
Does anyone had coded this using Kotlin?
private fun handleFacebookAccessToken(token: AccessToken) {
Log.d(TAG, "handleFacebookAccessToken:" + token)
val credential = FacebookAuthProvider.getCredential(token.token)
App.currentAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { Log.d(TAG, "signInWithCredential:success") }
.addOnSuccessListener(this) { authResult ->
if (authResult != null) {
val firebaseUser = authResult.user
if (App.database_table_users.child(firebaseUser.uid) == null) {
var facebookId = ""
firebaseUser.providerData
.filter { it.providerId == FacebookAuthProvider.PROVIDER_ID }
.forEach { facebookId = it.uid }
val photoUrl = "https://graph.facebook.com/$facebookId/picture?width=1024&height=1024"
App.database_table_users.child(firebaseUser.uid).setValue(
User(firebaseUser.uid,
firebaseUser.email.orEmpty(),
firebaseUser.displayName.orEmpty(),
photoUrl,
false
)
)
}
}
}
.addOnFailureListener(this) { ex ->
if (ex is FirebaseAuthUserCollisionException) {
LoginManager.getInstance().logOut()
val ad = AlertDialog.Builder(this#LoginActivity)
ad.setMessage(getString(R.string.auth_user_collision))
ad.setPositiveButton(getString(R.string.ok), null)
ad.show()
} else {
ex.printStackTrace()
}
}
}
You must use FirebaseAuth.getInstance() instead of App.currentAuth.
For example;
val mAuth = FirebaseAuth.getInstance()
val credential = FacebookAuthProvider.getCredential(token)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = mAuth.currentUser
} else {
task.exception?.printStackTrace()
}
}
Try This it's work for me
private fun loginWithFaceBook()
{
LoginManager.getInstance().registerCallback(callbackManager, facebookCallBack)
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile","email"))
}
private val facebookCallBack = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult?) {
val graphRequest = GraphRequest.newMeRequest(result?.accessToken) { _, response ->
val graphObject = response.jsonObject
val id = if(graphObject.has("id")) graphObject.getString("id") else null
val email = if(graphObject.has("email")) graphObject.getString("email") else null
val firstName = if(graphObject.has("first_name")) graphObject.getString("first_name") else null
val lastName = if(graphObject.has("last_name")) graphObject.getString("last_name") else null
val photoUrl = if(graphObject.has("picture")) {
val picture : JSONObject = graphObject.getJSONObject("picture")
if(picture.has("data") && picture.has("url") && picture.getString("url").isNotBlank()) {
picture.getString("url")
}
else
null
}
else
val bundle = Bundle()
bundle.putString("fields", "id,first_name,last_name,name,picture,email,gender,birthday,link")
graphRequest.parameters = bundle
graphRequest.executeAsync()
}
override fun onError(error: FacebookException) {
when{
error.message != null -> showSnackbar(error.message.toString())
}
}
override fun onCancel() {
}
}

Categories

Resources