I am trying to add a document to Firestore but only if it doesn't exist before. I tried finding some existing answers on SO but they talk about having security rules for Firebase. But I want to do it programmatically.
What I have done so far :
I have a simple layout which have one edit text called as etDeviceCode. I am asking user to enter a code(let's say any string) and if it already exists I just want a toast to show that it exists otherwise perform the task to add it. User authentication is already done.
Here is code:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Initialising firestore and auth
firestore = FirebaseFirestore.getInstance()
auth = FirebaseAuth.getInstance()
binding.btnAddDevice.setOnClickListener {
val device = binding.etAddDevice.text.toString()
saveInFirestore(device)
}
}
private fun saveInFirestore(device: String) {
//Firestore document reference
val docsRef = firestore.collection("Devices Registered").document(device)
val addDevice: MutableMap<String, String> = HashMap()
addDevice["UID"] = auth.uid!!
addDevice["Device Name"] = device
if (!verifyFirebase()) {
Timber.d("It already exists!!!!")
} else {
docsRef.set(addDevice)
.addOnSuccessListener {
Timber.d("New device saved with name : $device")
Toast.makeText(requireContext(), "New Device Saved", Toast.LENGTH_SHORT).show()
}
.addOnFailureListener {
Toast.makeText(requireContext(), "Not able to save Device", Toast.LENGTH_SHORT)
.show()
Timber.d("Unable to add device")
}
}
}
private fun verifyFirebase(): Boolean {
var valid = true
val device = binding.etAddDevice.text.toString()
val docRef = firestore.collection("Devices Registered").document(device)
docRef.get()
.addOnSuccessListener { document ->
if (document != null) {
Timber.d("Document data is : ${document.data}")
val response = document.getString("Device Name")
Timber.d(response)
if (response == device) {
Timber.d("Device already exists by name : $response")
valid = false
}
} else {
Timber.d("No such doc exists")
}
}
.addOnFailureListener {
Timber.d("Failed with exception : $it")
}
Timber.d("valid : $valid")
return valid
}
I have applied a logic in verifyFirebase to check if it already exists using Boolean.
Now the main issue I am facing: The value of valid which is converted to false when the document is already there at line
Timber.d("Device already exists by name : $response")
valid = false
}
but at the end when I am returning the value it is still true. I checked the logs and found that it returns before even entering addOnSuccessListener so obviously it is returning true. But why? I don't get it, why is it returning true and why is it getting executed before the addOnSuccessListener.
If you have any understanding about this let me know in comments. It would be highly appreciated.
Edit 1: Complete Code