This guide covers the breaking changes in CometChat Android SDK v5 and what you need to update in your app.
Dependency Update
Update your build.gradle dependency:
dependencies {
implementation "com.cometchat:chat-sdk-android:5.0.0"
}
Breaking Changes Overview
SDK v5 removes the Gson dependency from all SDK model classes and changes equals() / hashCode() to structural (deep) equality. All SDK model classes now implement Parcelable.
Must Do (will crash without these)
Replace Gson deserialization of SDK classes
Gson().fromJson(json, BaseMessage::class.java) no longer works because SDK classes no longer have Gson annotations.
Before (v4):
val message = Gson().fromJson(jsonString, BaseMessage::class.java)
After (v5):
val message = BaseMessage.processMessage(jsonObject)
For Conversation:
Before (v4):
val conversation = Gson().fromJson(jsonString, Conversation::class.java)
After (v5):
Use Parcelable to pass between components, or reconstruct from the SDK’s fetch methods.
Replace Gson-based Intent/Bundle passing
All SDK model classes (User, Group, BaseMessage, Conversation, etc.) now implement Parcelable. Use putExtra() / IntentCompat.getParcelableExtra() instead of Gson serialization.
User
Before (v4):
// Sending
intent.putExtra("user", Gson().toJson(user))
// Receiving
val user = Gson().fromJson(intent.getStringExtra("user"), User::class.java)
After (v5):
// Sending
intent.putExtra(getString(R.string.app_user), user)
// Receiving
val user = IntentCompat.getParcelableExtra(intent, getString(R.string.app_user), User::class.java)
BaseMessage
Before (v4):
// Sending
intent.putExtra("message", Gson().toJson(baseMessage))
// Receiving
val message = Gson().fromJson(intent.getStringExtra("message"), BaseMessage::class.java)
After (v5):
// Sending
intent.putExtra(getString(R.string.app_message), baseMessage)
// Receiving
val message = IntentCompat.getParcelableExtra(intent, getString(R.string.app_message), BaseMessage::class.java)
Group
Before (v4):
// Sending
intent.putExtra("group", Gson().toJson(group))
// Receiving
val group = Gson().fromJson(intent.getStringExtra("group"), Group::class.java)
After (v5):
// Sending
intent.putExtra(getString(R.string.app_group), group)
// Receiving
val group = IntentCompat.getParcelableExtra(intent, getString(R.string.app_group), Group::class.java)
Conversation
Before (v4):
// Sending
intent.putExtra("conversation", Gson().toJson(conversation))
// Receiving
val conversation = Gson().fromJson(intent.getStringExtra("conversation"), Conversation::class.java)
After (v5):
// Sending
intent.putExtra(getString(R.string.app_conversation), conversation)
// Receiving
val conversation = IntentCompat.getParcelableExtra(intent, getString(R.string.app_conversation), Conversation::class.java)
This pattern applies to all SDK model classes — Call, Action, MediaMessage, TextMessage, CustomMessage, etc. They all implement Parcelable in v5.
Replace Gson clone hacks
Before (v4):
val clone = Gson().fromJson(Gson().toJson(original), User::class.java)
After (v5):
val clone = original.clone()
Must Do (will cause silent bugs without these)
Update DiffUtil comparisons
equals() now does deep structural comparison. Using it in areItemsTheSame() will cause incorrect diff results.
Before (v4):
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem // worked because equals() compared by UID
}
After (v5):
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.uid == newItem.uid // explicit ID comparison
}
Replace list contains/remove with ID-based operations
Before (v4):
if (userList.contains(user)) { ... }
userList.remove(user)
After (v5):
if (userList.any { it.uid == user.uid }) { ... }
userList.removeAll { it.uid == user.uid }
Stop using SDK objects as HashMap/HashSet keys
Before (v4):
val map = HashMap<User, SomeData>()
map[user] = data
After (v5):
val map = HashMap<String, SomeData>() // use UID as key
map[user.uid] = data
Add ProGuard keep rules
Add the following to your proguard-rules.pro:
-keep class com.cometchat.** { *; }
-keepclassmembers class com.cometchat.** {
public boolean contentEquals(**);
}
Should Review
These won’t crash but may cause unexpected behavior if your code relied on the old identity-based equality:
- Any code that relied on
user1.equals(user2) meaning “same user” — it now means “identical in every field”
- Any code that relied on
message1.equals(message2) meaning “same message” — it now means “identical in every field including read receipts, reactions, etc.”
- Any code comparing Conversations via
equals() — now does recursive deep comparison of lastMessage and conversationWith
Safe — No Changes Needed
These patterns continue to work without modification:
- Gson usage for your own custom DTOs (not SDK classes)
User.fromJson(), Group.fromJson(), BaseMessage.processMessage() — these SDK methods still work
user.toJson(), group.toMap() — these SDK serialization methods still work