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