I am making an app using Firebase Firestore and Authentication. It is logging the user properly but as soon as the user gets authenticated, the app crashes. It gives a runtime exception.
Could not deserialize object. Class com.swetajain.mapchat.model.User does not define a no-argument constructor.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.swetajain.mapchat, PID: 4005
java.lang.RuntimeException: Could not deserialize object. Class com.swetajain.mapchat.model.User does not define a no-argument constructor. If you are using ProGuard, make sure these constructors are not stripped
at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(com.google.firebase:firebase-firestore@@21.4.1:563)
at com.google.firebase.firestore.util.CustomClassMapper.access$200(com.google.firebase:firebase-firestore@@21.4.1:54)
at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@21.4.1:749)
at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@21.4.1:741)
at com.google.firebase.firestore.util.CustomClassMapper.convertBean(com.google.firebase:firebase-firestore@@21.4.1:542)
at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-firestore@@21.4.1:253)
at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-firestore@@21.4.1:100)
at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@21.4.1:187)
at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@21.4.1:165)
at com.swetajain.mapchat.ui.LoginActivity$setUpFirebaseAuth$1$1.onComplete(LoginActivity.kt:86)
at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7136)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:536)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
My model class is here: User.kt
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
class User(
var email: String,
var user_id: String,
var username: String,
var avatar: String?
) : Parcelable
And my Login class is here: LoginActivity.kt
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils.isEmpty
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseAuth.AuthStateListener
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.FirebaseFirestoreSettings
import com.swetajain.mapchat.MainActivity
import com.swetajain.mapchat.R
import com.swetajain.mapchat.UserClient
import com.swetajain.mapchat.model.User
import kotlinx.android.synthetic.main.activity_login.*
class LoginActivity : AppCompatActivity(), View.OnClickListener {
private val TAG = "LoginActivity"
private val mProgressBar: ProgressBar? = null
private val mEmail: EditText? = null
private val mPassword: EditText? = null
private var mAuthListener: AuthStateListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
setUpFirebaseAuth()
email_sign_in_button.setOnClickListener(this)
link_register.setOnClickListener(this)
hideSoftKeyboard()
}
private fun hideSoftKeyboard() {
this.window
.setSoftInputMode(
WindowManager
.LayoutParams
.SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
}
private fun setUpFirebaseAuth() {
Log.d(TAG, "setUpFirebaseAuth: started..")
mAuthListener = AuthStateListener { firebaseAuth ->
var firebaseUser = firebaseAuth.currentUser
if (firebaseUser != null) {
Log.d(TAG, "onAuthStateChanged:signed_in:" + firebaseUser.uid)
Toast.makeText(
this@LoginActivity,
"Authenticated with: " + firebaseUser.email,
Toast.LENGTH_SHORT
).show()
val db = FirebaseFirestore.getInstance()
val settings = FirebaseFirestoreSettings.Builder()
.setTimestampsInSnapshotsEnabled(true)
.build()
db.firestoreSettings = settings
val userRef =
db.collection(getString(R.string.collection_users))
.document(firebaseUser.uid)
userRef.get()
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(
TAG,
"onComplete: successfully set the user client."
)
var user:User =
task.result
?.toObject(
User::class.java
)!!
(applicationContext as UserClient).setUser(user = user)
//this line is showing error
}
}
val intent = Intent(this@LoginActivity, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
} else { // User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out")
}
// ...
}
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.link_register -> {
startActivity(
Intent(
this@LoginActivity,
RegisterActivity::class.java
)
)
}
R.id.email_sign_in_button -> {
signIn()
}
}
}
private fun signIn() {
if (!isEmpty(mEmail!!.text.toString())
&& !isEmpty(mPassword!!.text.toString())
) {
Log.d(TAG, "onClick: attempting to authenticate.")
showDialog()
FirebaseAuth.getInstance().signInWithEmailAndPassword(
mEmail.text.toString(),
mPassword.text.toString()
)
.addOnCompleteListener { hideDialog() }.addOnFailureListener {
Toast.makeText(
this@LoginActivity,
"Authentication Failed",
Toast.LENGTH_SHORT
).show()
hideDialog()
}
} else {
Toast.makeText(
this@LoginActivity,
"You didn't fill in all the fields.",
Toast.LENGTH_SHORT
).show()
}
}
override fun onStart() {
super.onStart()
mAuthListener?.let { FirebaseAuth.getInstance().addAuthStateListener(it) }
}
override fun onStop() {
super.onStop()
if (mAuthListener != null) {
FirebaseAuth.getInstance().removeAuthStateListener(mAuthListener!!)
}
}
private fun showDialog() {
mProgressBar?.visibility = View.VISIBLE
}
private fun hideDialog() {
when (mProgressBar?.visibility) {
View.VISIBLE -> mProgressBar.visibility = View.INVISIBLE
}
}
}