> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-release-flutter-v5-stable.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Recommended patterns and practices for building with the CometChat Android SDK.

Follow these best practices to build reliable, performant, and secure applications with the CometChat Android SDK. Organized by topic — jump to what's relevant for your current work.

## Initialization & Authentication

| Practice                                | Description                                                                                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Initialize once at app startup          | Call `CometChat.init()` in your `Application` class `onCreate()`. It only needs to be called once per session.                                                                 |
| Store credentials in `local.properties` | Keep App ID, Region, and Auth Key out of source control. Read them via `BuildConfig` fields set in `build.gradle`.                                                             |
| Check for existing sessions             | Before calling `login()`, use `CometChat.getLoggedInUser()` to check if a session already exists.                                                                              |
| Use Auth Tokens in production           | Auth Keys are for development only. Generate Auth Tokens server-side using the [REST API](https://api-explorer.cometchat.com/reference/create-authtoken).                      |
| Handle token expiry                     | Implement a mechanism to detect login failures due to expired tokens. Use the [Login Listener](/sdk/android/authentication-overview#login-listener) to detect session changes. |
| Logout on sign-out                      | Always call `CometChat.logout()` when your user signs out to clear the SDK session and stop real-time events.                                                                  |

## Activity & Fragment Lifecycle

| Practice                                        | Description                                                                                                         |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Register listeners in `onResume()`              | Re-register message and call listeners when the Activity or Fragment becomes visible.                               |
| Remove listeners in `onPause()`                 | Remove listeners in `onPause()` to avoid processing events while the screen is not visible.                         |
| Clean up in `onDestroy()`                       | Remove all remaining listeners and cancel pending requests in `onDestroy()` to prevent memory leaks.                |
| Use `ViewModel` for SDK state                   | Hold SDK data (messages, users, groups) in a `ViewModel` so it survives configuration changes like screen rotation. |
| Avoid SDK calls in `onCreate()` before `init()` | Ensure `CometChat.init()` has completed (in your `Application` class) before making any SDK calls in an Activity.   |

## Listeners

| Practice                                | Description                                                                                                       |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Use unique listener IDs                 | Use descriptive IDs like `"MESSAGE_LISTENER_CHAT_SCREEN"` to avoid accidental overwrites.                         |
| Register after login, remove on cleanup | Register listeners after `login()` succeeds. Remove them in `onPause()` or `onDestroy()` to prevent memory leaks. |
| Keep callbacks lightweight              | Avoid heavy processing inside listener callbacks. Post updates to your `ViewModel` or `LiveData`.                 |
| Use specific listeners                  | Only register the listener types you need. Don't register a `GroupListener` if your screen only handles messages. |

## Pagination & Caching

| Practice                       | Description                                                                                                 |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| Use reasonable limits          | Set `setLimit()` to 30–50 for users, messages, and group members.                                           |
| Reuse request objects          | Call `fetchNext()`/`fetchPrevious()` on the same request instance. Creating a new object resets the cursor. |
| Cache frequently accessed data | Store user and group objects in your `ViewModel` or a local Room database to reduce API calls.              |

## Rate Limits

| Practice                    | Description                                                                                                                                    |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Batch operations            | Space out bulk operations using a queue or throttle mechanism.                                                                                 |
| Monitor rate limit headers  | Check `X-Rate-Limit-Remaining` in REST API responses to slow down before hitting limits.                                                       |
| Distinguish operation types | Core operations (login, create/delete user) share a 10,000/min limit. Standard operations have 20,000/min. Avoid frequent login/logout cycles. |

## Messaging

| Practice                      | Description                                                                                 |
| ----------------------------- | ------------------------------------------------------------------------------------------- |
| Use appropriate message types | Choose text, media, or custom messages based on your content.                               |
| Add metadata for context      | Use `setMetadata()` to attach location, device info, or other contextual data.              |
| Handle errors gracefully      | Always implement `onError()` callbacks to handle network issues or invalid parameters.      |
| Validate file types           | Before sending media messages, verify the file type matches the message type.               |
| Hide deleted/blocked content  | Use `hideDeletedMessages(true)` and `hideMessagesFromBlockedUsers(true)` for cleaner lists. |

## Threaded Messages

| Practice                | Description                                                                   |
| ----------------------- | ----------------------------------------------------------------------------- |
| Track active thread ID  | Store the current thread's `parentMessageId` to filter incoming messages.     |
| Use `hideReplies(true)` | Exclude thread replies from the main conversation to avoid clutter.           |
| Show reply count        | Display the number of replies on parent messages to indicate thread activity. |

## Reactions & Mentions

| Practice                   | Description                                                                |
| -------------------------- | -------------------------------------------------------------------------- |
| Update UI optimistically   | Show reactions immediately, then sync with the server response.            |
| Use correct mention format | Always use `<@uid:UID>` format for mentions in message text.               |
| Highlight mentions in UI   | Parse message text and style mentions differently using `SpannableString`. |

## Typing Indicators

| Practice               | Description                                                                                                             |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Debounce typing events | Don't call `startTyping()` on every keystroke — debounce to \~300ms intervals using a `Handler` or `debounce` operator. |
| Auto-stop typing       | Call `endTyping()` after 3–5 seconds of inactivity or when the user sends a message.                                    |

## Delivery & Read Receipts

| Practice                   | Description                                                                        |
| -------------------------- | ---------------------------------------------------------------------------------- |
| Mark as delivered on fetch | Call `markAsDelivered()` when messages are fetched and displayed.                  |
| Mark as read on view       | Call `markAsRead()` when the user actually views or scrolls to a message.          |
| Batch receipts             | Mark the last message in a batch — all previous messages are automatically marked. |

## Groups

| Practice                          | Description                                                                                      |
| --------------------------------- | ------------------------------------------------------------------------------------------------ |
| Use meaningful GUIDs              | Choose descriptive, unique GUIDs (e.g., `"project-alpha-team"`).                                 |
| Set group type carefully          | Group type cannot be changed after creation. Choose between `PUBLIC`, `PASSWORD`, and `PRIVATE`. |
| Add members at creation           | Use `createGroupWithMembers()` to add initial members in a single API call.                      |
| Check `hasJoined` before joining  | Avoid unnecessary API calls by checking the group's `hasJoined` property first.                  |
| Transfer ownership before leaving | Owners must transfer ownership to another member before they can leave.                          |
| Use `joinedOnly(true)`            | Filter to joined groups when building sidebars or group lists.                                   |

## Group Members

| Practice                | Description                                                                      |
| ----------------------- | -------------------------------------------------------------------------------- |
| Batch member additions  | Add multiple members in a single `addMembersToGroup()` call.                     |
| Set appropriate scopes  | Assign `PARTICIPANT` by default. Only use `ADMIN` or `MODERATOR` when needed.    |
| Handle partial failures | Check each entry in the response for `"success"` or an error message.            |
| Use scope constants     | Use `CometChatConstants.SCOPE_ADMIN` instead of raw strings.                     |
| Kick vs. Ban            | Use kick when the user can rejoin. Use ban for permanent removal until unbanned. |

## Calling

| Practice                            | Description                                                                                             |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Initialize Calls SDK after Chat SDK | Always initialize Chat SDK (`CometChat.init()`) before Calls SDK (`CometChatCalls.init()`).             |
| Store session ID immediately        | Save the session ID from `initiateCall()` response — you'll need it for accept, reject, and cancel.     |
| Handle all call states              | Implement handlers for all listener events (accepted, rejected, cancelled, busy, ended).                |
| Generate tokens just-in-time        | Generate call tokens immediately before starting a session rather than caching them.                    |
| Clean up on session end             | Always call `CometChatCalls.endSession()` in both `onCallEnded` and `onCallEndButtonPressed` callbacks. |
| Request permissions before calling  | Check and request `CAMERA` and `RECORD_AUDIO` permissions at runtime before initiating a call.          |
| Inform users about recording        | Always notify participants when recording starts — this is often a legal requirement.                   |
| Limit presenters to 5               | Additional users should join as viewers.                                                                |

## Permissions

| Practice                              | Description                                                                                                     |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Request permissions at the right time | Request `CAMERA`, `RECORD_AUDIO`, and `READ_EXTERNAL_STORAGE` permissions contextually, not at app launch.      |
| Handle permission denial gracefully   | Show a rationale dialog if the user denies a permission, and disable the relevant feature rather than crashing. |
| Use `ActivityResultContracts`         | Use the modern `registerForActivityResult` API instead of the deprecated `onRequestPermissionsResult`.          |

## Connection & WebSocket

| Practice                           | Description                                                                     |
| ---------------------------------- | ------------------------------------------------------------------------------- |
| Register connection listener early | Add the listener right after `CometChat.init()` succeeds.                       |
| Show connection status in UI       | Display a banner when disconnected so users know messages may be delayed.       |
| Queue actions during disconnection | Queue user actions and retry once `onConnected` fires.                          |
| Don't poll `getConnectionStatus()` | Use the listener-based approach instead.                                        |
| Reconnect on app foreground        | Call `CometChat.connect()` in `onResume()` if you disconnect in the background. |

## AI Features

| Practice                               | Description                                                                                  |
| -------------------------------------- | -------------------------------------------------------------------------------------------- |
| Register both listeners for AI Agents  | Use `AIAssistantListener` for streaming events and `MessageListener` for persisted messages. |
| Handle streaming progressively         | Render the assistant's reply token-by-token using `Text Message Content` events.             |
| Show pending state for moderation      | Display a visual indicator when `getModerationStatus()` returns `PENDING`.                   |
| Handle disapproved messages gracefully | Show a placeholder or notification so the sender understands what happened.                  |
| Track pending messages                 | Maintain a local map of pending message IDs to update UI when moderation results arrive.     |

## Upgrading from V3

| Practice                     | Description                                                                                 |
| ---------------------------- | ------------------------------------------------------------------------------------------- |
| Follow the setup guide first | Complete the v4 [setup instructions](/sdk/android/setup) before changing dependencies.      |
| Update Gradle dependency     | Replace the v3 artifact with `com.cometchat:chat-sdk-android:4.x.x` in your `build.gradle`. |
| Test incrementally           | Test each feature area (messaging, calling, groups) individually after updating.            |
| Remove old packages          | Remove the v3 dependency from `build.gradle` and sync to avoid conflicts.                   |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="wrench" href="/sdk/android/troubleshooting">
    Common issues and solutions
  </Card>

  <Card title="Setup SDK" icon="gear" href="/sdk/android/setup">
    Installation and initialization guide
  </Card>
</CardGroup>
