For AI agents: see the complete documentation index at /llms.txt.
SDK quickstart
Updated
A highly reliable global communication platform where users can chat one-to-one, in groups or in chat rooms.
Instant messaging enhances user engagement by enabling users to connect and form a community within the app. Increased engagement can lead to increased user satisfaction and loyalty to your app. An instant messaging feature can also provide real-time support to users, allowing them to get help and answers to their questions quickly. The Chat SDK enables you to embed real-time messaging in any app, on any device, anywhere.
This page guides you through implementing peer-to-peer messaging into your app using the Chat SDK.
Understand the tech
The following figure shows the workflow of sending and receiving peer-to-peer messages using Chat SDK.
Chat SDK workflow
- Clients retrieve an authentication token from your app server.
- Users log in to Chat using the App ID, their user ID, and token.
- Clients send and receive messages through Chat as follows:
- Client A sends a message to Client B. The message is sent to the Agora Chat server.
- The server delivers the message to Client B. When Client B receives a message, the SDK triggers an event.
- Client B listens for the event to read and display the message.
Prerequisites
In order to follow the procedure on this page, you must have:
-
A valid Agora account.
-
An Agora project for which you have enabled Chat.
-
The App ID for the project.
-
Internet access.
Ensure that no firewall is blocking your network communication.
- An Android emulator or a physical Android device.
- Android Studio 3.6 or higher.
- Java Development Kit (JDK). You can refer to the Android User Guide for applicable versions.
- Xcode. This page uses Xcode 13.0 as an example.
- A device running iOS 10 or later.
- A Windows or macOS computer that meets the following requirements:
- A browser supported by the Agora Chat SDK:
- Internet Explorer 9 or later
- FireFox 10 or later
- Chrome 54 or later
- Safari 6 or later
- Access to the Internet. If your network has a firewall, follow the instructions in Firewall Requirements to access Agora services.
- A browser supported by the Agora Chat SDK:
- Node.js and npm
-
Flutter 2.10 or higher.
-
Dart 2.16 or higher.
-
If your target platform is iOS:
- macOS
- Xcode 12.4 or higher with Xcode Command Line Tools
- CocoaPods
- An iOS emulator or a physical iOS device running iOS 10.0 or higher
-
If your target platform is Android:
- macOS or Windows
- Android Studio 4.0 or higher with JDK 1.8 or higher
- An Android emulator or a physical Android device running Android SDK API 21 or higher
If your target platform is iOS:
- macOS 10.15.7 or later
- Xcode 12.4 or later, including command line tools
- React Native 0.66.5 or later
- NodeJs 16 or later, including npm package management tool
- CocoaPods package management tool
- Yarn compile and run tool
- Watchman debugging tool
- A physical or virtual mobile device running iOS 10.0 or later
If your target platform is Android:
- macOS 10.15.7 or later, or Windows 10 or later
- Android Studio 4.0 or later, including JDK 1.8 or later
- React Native 0.66.5 or later
- CocoaPods package management tool if your operating system is macOS.
- Powershell 5.1 or later if your operating system is Windows.
- NodeJs 16 or later, including npm package management tool
- Yarn compile and run tool
- Watchman debugging tool
- A physical or virtual mobile device running Android 6.0 or later
For more information, see Setting up the environment.
- A device running Windows 7 or higher.
- Visual Studio IDE 2019 or later
- .NET Framework 4.5.2 or later
Project setup
To integrate Chat into your app, do the following:
-
Method 1: Use
mavenCentralto automatically integrate:-
In Android Studio, create a new Phone and Tablet Android project with an Empty Activity. Choose Java as the project language, and ensure that the Minimum SDK version is set to
21or higher.Android Studio automatically starts gradle sync. Wait for the sync to succeed before you continue.
-
Add Chat SDK to your project dependencies.
To add the SDK to your project:
-
In
/Gradle Scripts/build.gradle (Module: <projectname>.app), add the following line underdependencies:dependencies { ... implementation 'io.agora.rtc:chat-sdk:<version>' }Replace
<version>with the version number for the latest Chat SDK release, for example1.3.1. You can obtain the latest version information using Maven Central Repository Search. -
To download the SDK from Maven Central, press Sync Now.
-
-
Add permissions for network and device access.
To add the necessary permissions, in
/app/Manifests/AndroidManifest.xml, add the following permissions after</application>:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> -
Prevent code obfuscation.
In
/Gradle Scripts/proguard-rules.pro, add the following line:-keep class io.agora.** {*;} -dontwarn io.agora.** -
-
Method 2: Dynamically load .so library files
In order to reduce the size of the application installation package, the SDK provides
ChatOptions#setNativeLibBasePathmethod to support dynamic loading of the.sofiles required by the SDK. Taking SDK 1.3.0 as an example, the.sofile includes two files:libcipherdb.soand.libhyphenate.so. The steps to implement this function are as follows:-
Download the latest version of the SDK and unzip it.
-
Integrate the
agorachat_1.3.0.jarfile into your project. -
Upload
.sofiles for all schemas to your server and ensure that the application can download.sofiles for the target schemas over the network. -
When the application runs, it checks whether the
.sofile exists. If not found, the app downloads the.sofile and saves it to your custom app's private directory. -
When calling
ChatClient#init, set the app private directory where the.sofile is located as a parameter into theChatOptions#setNativeLibBasePathmethod. -
The SDK will automatically load
.sofiles from the specified path upon initialization.// Assume that you have put two .so libraries, `libcipherdb.so` and `libagora-chat-sdk.so` in the /data/data/packagename/files directory of the app. String filesPath = mContext.getFilesDir().getAbsolutePath(); ChatOptions options = new ChatOptions(); options.setNativeLibBasePath(filesPath); ChatClient.getInstance().init(mContext, options);
This method is applicable when you integrate the SDK manually but not when you integrate the SDK with Maven Central.
You can specify the path of
.sofiles with the path parameter in theChatOptions#setNativeLibBasePathmethod. The path must be a valid and private directory of the app.If you set this parameter, the SDK will use
System.loadto load the.solibrary from the directory you specify, so that the app dynamically loads the required.sofiles when it runs, thereby reducing the package size.If you do not set this parameter or set it to
null, the SDK will useSystem.loadto load the.solibrary from the default path when compiling the app, thus increasing the package size compared to the previous method.Since March 6, 2024, using this method to reduce the app size no longer meets the requirements of Google Play. For details, refer to the Developer Program Policies issued by Google. If your app needs to be listed on Google Play, please try other ways to reduce the app size. For details, see App size optimization.
-
To integrate Chat into your app, do the following:
-
Create a new project for this device app using the App template. Select the Storyboard Interface and Swift Language.
If you have not already added team information, click Add account…, input your Apple ID, then click Next.
-
Enable automatic signing for your project. Set the target devices to deploy your iOS app to an iPhone or iPad.
-
Add project permissions for microphone and camera usage:
-
Open Info in the project navigation panel, then add the following properties to the Information Property List:
Key Type Value NSMicrophoneUsageDescription String Access the microphone. NSCameraUsageDescription String Access the camera.
-
-
Integrate Agora Chat SDK into your project:
-
In Xcode, click File > Add Packages..., then paste the following link in the search:
https://github.com/AgoraIO/AgoraChat_iOS.gitYou see the available Agora packages. In AgoraChat_iOS, specify the latest Chat SDK version, for example
1.0.9. You can obtain the latest version information in the release notes. -
Click Add Package. In the new window, click Add Package.
You see AgoraChat in Package Dependencies for your project.
-
The privacy updates for App Store submissions released by Apple, require developers to declare approved reasons for using a set of APIs in their app’s privacy manifest. Agora provides a PrivacyInfo.xcprivacy file that you can include in your project. If you are using Chat SDK 1.2 or earlier, refer to Add a privacy manifest file for details.
To create the environment necessary to add peer-to-peer messaging into your app, do the following:
- Use VITE to create a new project. If VITE is not installed, run
npm i vite -gto install it. Then, runnpm create vite@latest agora_quickstart. In this example, we choose "React + JavaScript" to create the project.
The project directory now has the following structure:
agora_quickstart
├─ index.html
├─ main.js
└─ package.json-
Integrate the Agora Chat SDK into your project through npm. Add 'agora-chat' and 'vite' to the 'package.json' file.
{ "name": "agora_quickstart", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies":{ "agora-chat": "latest" }, "devDependencies": { "vite": "^3.0.7" } }
To integrate Chat into your app, do the following:
-
Set up a Flutter environment for a Chat project
In the terminal, run the following command:
flutter doctorFlutter checks your development device and helps you set up your local development environment. Make sure that your system passes all the checks.
-
Create a new Flutter app
In the IDE of your choice, create a new Flutter Application project.
You can also create a new project from the terminal using the following command:
flutter create <--insert project name--> -
Add Chat SDK to your project
Add the following line to the
<project_folder>/pubspec.yamlfile underdependencies:dependencies: ... # For x.y.z, fill in a specific SDK version number. For example, 1.0.9 agora_chat_sdk: ^x.y.z ...To get the latest device Chat SDK version number, visit pub.dev.
You can also add the Chat SDK dependency to your project by running the following command in the project folder:
flutter pub add agora_chat_sdk -
Use the Flutter framework to download dependencies to your app
Open a terminal window and execute the following command in the project folder:
flutter pub get -
Add platform specific requirements
Update the minimum version requirements for your target platforms as follows:
-
Android
-
In the
<project_folder>/android/app/build.gradlefile, set the AndroidminSdkVersionto21underdefaultConfig {.android { defaultConfig { minSdkVersion 21 } } -
In the
<project_folder>/android/app/proguard-rules.profile, add the following lines to prevent code obfuscation:-keep class com.hyphenate.** {*;} -dontwarn com.hyphenate.**
-
-
iOS
Open the
<project_folder>/ios/Runner.xcodeprojfile in Xcode, and select TARGETS > Runner in the left sidebar. In the General > Deployment Info section, set the minimum iOS version toiOS 10.0.
-
Follow these steps to create a React Native project and add Agora Chat into your app.
-
Prepare the development environment according to your development system and target platform.
-
In your terminal, navigate to the directory where you want to create the project, and run the following command to create a React Native project:
npx @react-native-community/cli@latest init --version 0.76 simple_demoThe created project name is
simple_demo.Initialize the project:
cd simple_demo yarn set version 1.22.19 yarn
You can use npm or other tools.
-
In the terminal, run the following command to add dependencies:
yarn add react-native-agora-chat -
Initialize the native part.
For iOS platform, use
cocoapodsto initialize:cd ios && pod install && cd ..
-
Create a Unity project:
-
In Unity Hub, select Projects, then click New Project.
-
In All templates, select 3D. Set the Project name and Location, then click Create Project.
Your project opens in Unity Editor.
-
-
Integrate Chat SDK into your project:
-
Unzip Chat SDK for Unity to a local folder:
-
In Unity, click Assets > Import Package > Custom Package.
-
Navigate to the Chat SDK package and click Open.
-
In Import Unity Package, click Import.
-
This section shows how to integrate Chat SDK into your project.
-
Create a Windows project
- Open Visual Studio and Create a C# WPF app named
AgoraWindowsChat. - Set the Active solution configuration as Debug and Active solution platform as x64.
- Open Visual Studio and Create a C# WPF app named
-
Integrate the Chat SDK
-
Download the Chat SDK NuGet package.
-
In Solution Explorer, right-click
<project-name>and select Manage NuGet Packages.... -
On the
NuGet: <project-name>page, select the Gear icon at the top right. -
In Options,
- Click + at the top right, then select the new package source.
- Set Name, then set Source to the parent directory of the Nuget package resides.
- Click OK.
-
Go back to the
NuGet: <project-name>page, open the Package source drop-down list at the top right, then select the package you just added. -
In Browse on the
NuGet: <project-name>page, select agora_chat_sdk, then click Install.If you don't see agora_chat_sdk, refresh the page.
-
In Preview Changes, click OK
-
You have installed Chat SDK.
Implement peer-to-peer messaging
This section shows how to use the Chat SDK to implement peer-to-peer messaging in your app, step by step.
Create the UI
In the quickstart app, you create a simple UI that consists of the following elements:
- A
Buttonto log in or out of Agora Chat. - An
EditTextbox to specify the recipient user ID. - An
EditTextbox to enter a text message. - A
Buttonto send the text message. - A scrollable layout to display sent and received messages.
To add the UI framework to your device project, open app/res/layout/activity_main.xml and replace the content with the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ECE5DD">
<Button
android:id="@+id/btnJoinLeave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_margin="5dp"
android:onClick="joinLeave"
android:text="Join" />
<EditText
android:id="@+id/etRecipient"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/btnJoinLeave"
android:layout_alignTop="@id/btnJoinLeave"
android:layout_toStartOf="@id/btnJoinLeave"
android:layout_margin="5dp"
android:padding="5dp"
android:background="#FFFFFF"
android:hint="Enter recipient user ID" />
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/btnSendMessage"
android:layout_below="@id/etRecipient"
android:background="#ECE5DD">
<LinearLayout
android:id="@+id/messageList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<EditText
android:id="@+id/etMessageText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/btnSendMessage"
android:layout_alignBottom="@id/btnSendMessage"
android:layout_margin="5dp"
android:padding="5dp"
android:background="#FFFFFF"
android:hint="Message" />
<Button
android:id="@+id/btnSendMessage"
android:layout_width="50dp"
android:layout_margin="5dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:onClick="sendMessage"
android:text=">>" />
</RelativeLayout>You see Cannot resolve symbol errors in your IDE. This is because this layout refers to methods that you create later.
Handle the system logic
Import the necessary classes, and add a method to show status updates to the user.
-
Import the relevant Agora and Android classes
In
/app/java/com.example.<projectname>/MainActivity, add the following lines afterpackage com.example.<project name>:import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.view.View; import android.widget.Toast; import android.graphics.Color; import android.view.Gravity; import android.view.inputmethod.InputMethodManager; import android.util.Log; import java.util.List; import io.agora.CallBack; import io.agora.ConnectionListener; import io.agora.MessageListener; import io.agora.chat.ChatClient; import io.agora.chat.ChatMessage; import io.agora.chat.ChatOptions; import io.agora.chat.TextMessageBody; -
Log events and show status updates to your users
In the
MainActivityclass, add the following method beforeonCreate.private void showLog(String text) { // Show a toast message runOnUiThread(() -> Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show()); // Write log Log.d("AgoraChatQuickStart", text); }
Send and receive messages
When a user opens the app, you instantiate and initialize a ChatClient. When the user taps the Join button, the app logs in to Agora Chat. When a user types a message in the text box and then presses Send, the typed message is sent to Agora Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.
The following figure shows the API call sequence for implementing this workflow.
API call sequence
To implement this workflow in your app, take the following steps:
-
Declare variables
In the
MainActivityclass, add the following declarations:private String userId = "<User ID of the local user>"; private String token = "<Your authentication token>"; private String appId = "<App ID from Agora console>"; private ChatClient agoraChatClient; private boolean isJoined = false; EditText editMessage; -
Set up Chat when the app starts
When the app starts, you create an instance of the
ChatClientand set up callbacks to handle Chat events. To do this, replace theonCreatemethod in theMainActivityclass with the following:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setupChatClient(); // Initialize the ChatClient setupListeners(); // Add event listeners // Set up UI elements for code access editMessage = findViewById(R.id.etMessageText); } -
Instantiate the
ChatClientTo implement peer-to-peer messaging, you use Chat SDK to initialize a
ChatClientinstance. In theMainActivityclass, add the following method beforeonCreate.private void setupChatClient() { ChatOptions options = new ChatOptions(); if (appId.isEmpty()) { showLog("You need to set your App ID"); return; } options.setAppId(appId); // Set your app ID in options agoraChatClient = ChatClient.getInstance(); agoraChatClient.init(this, options); // Initialize the ChatClient agoraChatClient.setDebugMode(true); // Enable debug info output } -
Handle and respond to Chat events
To receive notification of Chat events such as connection, disconnection, and token expiration, you add a
ConnectionListener. To handle message delivery and new message notifications, you add aMessageListener. When you receive theonMessageReceivednotification, you display the message to the user.In
/app/java/com.example.<projectname>/MainActivity, add the following method aftersetupChatClient:private void setupListeners() { // Add message event callbacks agoraChatClient.chatManager().addMessageListener(new MessageListener() { @Override public void onMessageReceived(List<ChatMessage> messages) { for (ChatMessage message : messages) { runOnUiThread(() -> displayMessage(((TextMessageBody) message.getBody()).getMessage(), false) ); showLog("Received a " + message.getType().name() + " message from " + message.getFrom()); } } }); // Add connection event callbacks agoraChatClient.addConnectionListener(new ConnectionListener() { @Override public void onConnected() { showLog("Connected"); } @Override public void onDisconnected(int error) { if (isJoined) { showLog("Disconnected: " + error); isJoined = false; } } @Override public void onLogout(int errorCode) { showLog("User logging out: " + errorCode); } @Override public void onTokenExpired() { // The token has expired } @Override public void onTokenWillExpire() { // The token is about to expire. Get a new token // from the token server and renew the token. } }); } -
Log in to Agora Chat
When a user clicks Join, your app logs in to Agora Chat. When a user clicks Leave, the app logs out of Agora Chat.
To implement this logic, in the
MainActivityclass, add the following method beforeonCreate:public void joinLeave(View view) { Button button = findViewById(R.id.btnJoinLeave); if (isJoined) { agoraChatClient.logout(true, new CallBack() { @Override public void onSuccess() { showLog("Sign out success!"); runOnUiThread(() -> button.setText("Join")); isJoined = false; } @Override public void onError(int code, String error) { showLog(error); } }); } else { agoraChatClient.loginWithToken(userId, token, new CallBack() { @Override public void onSuccess() { showLog("Signed in"); isJoined = true; runOnUiThread(() -> button.setText("Leave")); } @Override public void onError(int code, String error) { if (code == 200) { // Already joined isJoined = true; runOnUiThread(() -> button.setText("Leave")); } else { showLog(error); } } }); } } -
Send a message
To send a message to Agora Chat when a user presses the Send button, add the following method to the
MainActivityclass, beforeonCreate:public void sendMessage(View view) { // Read the recipient name from the EditText box String toSendName = ((EditText) findViewById(R.id.etRecipient)).getText().toString().trim(); String content = editMessage.getText().toString().trim(); if (toSendName.isEmpty() || content.isEmpty()) { showLog("Enter a recipient name and a message"); return; } // Create a ChatMessage ChatMessage message = ChatMessage.createTextSendMessage(content, toSendName); // Set the message callback before sending the message message.setMessageStatusCallback(new CallBack() { @Override public void onSuccess() { showLog("Message sent"); runOnUiThread(() -> { displayMessage(content, true); // Clear the box and hide the keyboard after sending the message editMessage.setText(""); InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(editMessage.getApplicationWindowToken(),0); }); } @Override public void onError(int code, String error) { showLog(error); } }); // Send the message agoraChatClient.chatManager().sendMessage(message); } -
Display chat messages
To display the messages the current user has sent and received in your app, add the following method to the
MainActivityclass:void displayMessage(String messageText, boolean isSentMessage) { // Create a new TextView final TextView messageTextView = new TextView(this); messageTextView.setText(messageText); messageTextView.setPadding(10,10,10,10); // Set formatting LinearLayout messageList = findViewById(R.id.messageList); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT); if (isSentMessage) { params.gravity = Gravity.END; messageTextView.setBackgroundColor(Color.parseColor("#DCF8C6")); params.setMargins(100,25,15,5); } else { messageTextView.setBackgroundColor(Color.parseColor("white")); params.setMargins(15,25,100,5); } // Add the message TextView to the LinearLayout messageList.addView(messageTextView, params); }
Create the UI
In the quickstart app, you create a simple UI that consists of the following elements:
- A
UIButtonto log in or out of the Chat. - A
UITextFieldbox to specify the recipient user ID. - A
UITextFieldbox to enter a text message. - A
UIButtonto send the text message. - A
UITextViewto display sent and received messages.
To create this user interface, in the ViewController class:
-
Add the UI elements you need
Add the following declarations at the top of the class.
var btnJoinLeave: UIButton! var etRecipient: UITextField! var scrollView: UITextView! var etMessageText: UITextField! var btnSendMessage: UIButton! -
Configure the UI elements in your interface
Add the following below
super.viewDidLoad()inside theviewDidLoadmethod:btnJoinLeave = UIButton(type: .system) btnJoinLeave.frame = CGRect(x: 60, y: 100, width: 250, height: 30) btnJoinLeave.setTitle("Join", for: .normal) btnJoinLeave.addTarget(self, action: #selector(joinLeave), for: .touchUpInside) self.view.addSubview(btnJoinLeave) etRecipient = UITextField(frame: CGRect(x: 100, y: 150, width: 300, height: 30)) etRecipient.placeholder = "Enter recipient user ID" self.view.addSubview(etRecipient) scrollView = UITextView(frame: CGRect(x: 130, y: 200, width: 300, height: 100)) scrollView.isEditable = false self.view.addSubview(scrollView) etMessageText = UITextField(frame: CGRect(x: 80, y: 320, width: 200, height: 30)) etMessageText.placeholder = "Message" self.view.addSubview(etMessageText) btnSendMessage = UIButton(type: .system) btnSendMessage.frame = CGRect(x: 270, y: 320, width: 80, height: 30) btnSendMessage.setTitle(">>", for: .normal) btnSendMessage.addTarget(self, action: #selector(sendMessage), for: .touchUpInside) self.view.addSubview(btnSendMessage)
Handle the system logic
Import the necessary classes, and add a method to show status updates to the user.
-
Import the Chat SDK class
In
ViewController, add the provided code sample afterimport UIKit:import AgoraChat
If Xcode does not recognize this import, click File > Packages > Reset Package Caches.
-
Log events and show status updates to your users
In
ViewController, add the following method after theviewDidLoadfunction:func showLog(_ text: String) -> Void { DispatchQueue.main.async { let alert = UIAlertController(title: "", message: text, preferredStyle: .alert) self.present(alert, animated: true) alert.dismiss(animated: true, completion: nil) } }
Send and receive messages
When a user opens the app, you instantiate and initialize a ChatClient. When the user taps the Join button, the app logs in to the Chat. When a user types a message in the text box and then presses Send, the typed message is sent to the Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.
To implement this workflow in your app, take the following steps:
-
Declare variables
In the
ViewControllerclass, add the following declarations at the top:var userId = "<User ID of the local user>" var token = "<Your authentication token>" var appId = "<App ID from Agora console>" var agoraChatClient: AgoraChatClient! var isJoined: Bool = false -
Set up Chat when the app starts
When the app starts, you create an instance of the
AgoraChatClient. To do this, add the following toviewDidLoad:setupChatClient() // Initialize the ChatClient -
Instantiate the
AgoraChatClientTo implement peer-to-peer messaging, you use Chat SDK to initialize an
AgoraChatClientinstance. In theViewControllerclass, add the following method after theviewDidLoadfunction:func setupChatClient() { if (appId.isEmpty) { showLog("You need to set your App ID") return } let options = AgoraChatOptions(appId: appId) // Create AgoraChatOptions with your App ID agoraChatClient = AgoraChatClient.shared() options.enableConsoleLog = true // Enable printing logs on console agoraChatClient.initializeSDK(with: options) // Initialize the AgoraChatClient agoraChatClient.chatManager?.add(self, delegateQueue: nil) // Adds the chat delegate to receive messages } -
Handle and respond to Chat events
The
AgoraChatClientDelegateimplements callbacks to receive notification of Chat events such as a connection state change, and a token expiration. TheAgoraChatManagerDelegateimplements a callback to handle the receival of messages. When you receive themessagesDidReceivenotification, you display the message to the user.To handle these events, add the following extensions to the
ViewController:// Add message event callbacks extension ViewController: AgoraChatManagerDelegate { func messagesDidReceive(_ aMessages: [AgoraChatMessage]) { for message in aMessages { let msgBody = message.body as! AgoraChatTextMessageBody DispatchQueue.main.async { self.displayMessage(messageText: msgBody.text, isSentMessage: false) } showLog("Received a message from \(message.from)") } } } // Add connection event callbacks extension ViewController: AgoraChatClientDelegate { func connectionStateDidChange(_ aConnectionState: AgoraChatConnectionState) { if aConnectionState == .connected { showLog("Connected to the chat server.") } else { if isJoined { showLog("Disconnected from the chat server.") isJoined = false } } } func tokenWillExpire(_ aErrorCode: AgoraChatErrorCode) { showLog("Token will expire (log in using new token)") } func tokenDidExpire(_ aErrorCode: AgoraChatErrorCode) { showLog("Token expired (log in using new token)") } } -
Log in to the Chat
When a user presses Join, your app logs in to the Chat. When a user presses Leave, the app logs out of the Chat.
To implement this logic, put the following method to the
ViewController:@objc func joinLeave() { if (isJoined) { let result: AgoraChatError? = agoraChatClient.logout(true) guard result == nil else { showLog(result!.errorDescription) return } showLog("Signed out") DispatchQueue.main.async { self.btnJoinLeave.setTitle("Join", for: .normal) self.isJoined = false } } else { let result: AgoraChatError? = agoraChatClient.login(withUsername: userId, token: token) guard result == nil else { if (result!.code.rawValue == 200) { // Already joined isJoined = true showLog("Already signed in") DispatchQueue.main.async { self.btnJoinLeave.setTitle("Leave", for: .normal) } } else { showLog(result!.errorDescription) } return } showLog("Signed in") isJoined = true DispatchQueue.main.async { self.btnJoinLeave.setTitle("Leave", for: .normal) } } } -
Send a message
To send a message to the Chat when a user presses the Send button, perform the following steps:
-
Add the following method to the
ViewControllerclass before theviewDidLoadfunction:@objc func sendMessage() { // Read the recipient name from the EditText box let toSendName = etRecipient.text!.trimmingCharacters(in: .whitespaces) let content = etMessageText.text!.trimmingCharacters(in: .whitespaces) if (toSendName.isEmpty || content.isEmpty) { showLog("Enter a recipient name and a message.") return } // Create a ChatMessage let message = AgoraChatMessage( conversationID: toSendName, from: agoraChatClient.currentUsername!, to: toSendName, body: AgoraChatTextMessageBody(text: content), ext: nil ) // Send the message agoraChatClient.chatManager?.send(message, progress: nil) { _, err in if let err = err { self.showLog("Error occurred when sending the message. \(err.errorDescription)") } else { self.showLog("Message sent successfully.") DispatchQueue.main.async { self.displayMessage(messageText: content, isSentMessage: true) self.etMessageText.text = "" } } } }
-
-
Display chat messages
To display the messages the current user has sent and received in your app, add the following method to the
ViewControllerclass:func displayMessage(messageText: String, isSentMessage: Bool) { DispatchQueue.main.async { self.scrollView.text.append( DateFormatter.localizedString(from: Date.now, dateStyle: .none, timeStyle: .medium) + ": " + String(reflecting: messageText) + "\r\n" ) self.scrollView.scrollRangeToVisible(NSRange(location: self.scrollView.text.count, length: 1)) } }
Copy the following code to the App.jsx file to implement the UI:
import { useEffect, useState, useRef } from "react";
import "./App.css";
import AgoraChat from "agora-chat";
function App() {
// Replaces <Your App ID> with your App ID.
const appId = "<Your App ID>";
const [userId, setUserId] = useState("");
const [token, setToken] = useState("");
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [peerId, setPeerId] = useState("");
const [message, setMessage] = useState("");
const [logs, setLogs] = useState([]);
const chatClient = useRef(null);
// Logs into Agora Chat.
const handleLogin = () => {
if (userId && token) {
chatClient.current.open({
user: userId,
// Use agoraToken for v1.2.1 and earlier, but accessToken for 1.2.2 and later.
accessToken: token,
});
} else {
addLog("Please enter userId and token");
}
};
// Logs out.
const handleLogout = () => {
chatClient.current.close();
setIsLoggedIn(false);
setUserId("");
setToken("");
setPeerId("");
};
// Sends a peer-to-peer message.
const handleSendMessage = async () => {
if (message.trim()) {
try {
const options = {
chatType: "singleChat", // Sets the chat type as a one-to-one chat.
type: "txt", // Sets the message type.
to: peerId, // Sets the recipient of the message with user ID.
msg: message, // Sets the message content.
};
let msg = AgoraChat.message.create(options);
await chatClient.current.send(msg);
addLog(`Message send to ${peerId}: ${message}`);
setMessage("");
} catch (error) {
addLog(`Message send failed: ${error.message}`);
}
} else {
addLog("Please enter message content");
}
};
// Add log.
const addLog = (log) => {
setLogs((prevLogs) => [...prevLogs, log]);
};
useEffect(() => {
// Initializes the Web client.
chatClient.current = new AgoraChat.connection({
appId: appId,
});
// Adds the event handler.
chatClient.current.addEventHandler("connection&message", {
// Occurs when the app is connected to Agora Chat.
onConnected: () => {
setIsLoggedIn(true);
addLog(`User ${userId} Connect success !`);
},
// Occurs when the app is disconnected from Agora Chat.
onDisconnected: () => {
setIsLoggedIn(false);
addLog(`User Logout!`);
},
// Occurs when a text message is received.
onTextMessage: (message) => {
addLog(`${message.from}: ${message.msg}`);
},
// Occurs when the token is about to expire.
onTokenWillExpire: () => {
addLog("Token is about to expire");
},
// Occurs when the token has expired.
onTokenExpired: () => {
addLog("Token has expired");
},
onError: (error) => {
addLog(`on error: ${error.message}`);
},
});
}, []);
return (
<>
<div
style={{
width: "500px",
display: "flex",
gap: "10px",
flexDirection: "column",
}}
>
<h2>Agora Chat Examples</h2>
{!isLoggedIn ? (
<>
<div>
<label>UserID: </label>
<input
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)}
placeholder="Enter the user ID"
/>
</div>
<div>
<label>Token: </label>
<input
type="text"
value={token}
onChange={(e) => setToken(e.target.value)}
placeholder="Enter the token"
/>
</div>
<button onClick={handleLogin}>Login</button>
</>
) : (
<>
<h3>Welcome, {userId}</h3>
<button onClick={handleLogout}>Logout</button>
<div>
<label>Peer userID: </label>
<input
type="text"
value={peerId}
onChange={(e) => setPeerId(e.target.value)}
placeholder="Enter the peer user ID"
/>
</div>
<div>
<label>Peer message: </label>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Input message"
/>
<button onClick={handleSendMessage}>Send</button>
</div>
</>
)}
<h3>Operation log</h3>
<div
style={{
height: "300px",
overflowY: "auto",
border: "1px solid #ccc",
padding: "10px",
textAlign: "left",
}}
>
{logs.map((log, index) => (
<div key={index}>{log}</div>
))}
</div>
</div>
</>
);
}
export default App;Handle the system logic
Import the Chat SDK package and set up the app framework.
-
Add the Chat SDK package
Open the file
/lib/main.dartand add the followingimportstatement at the top of the file:import 'package:agora_chat_sdk/agora_chat_sdk.dart'; -
Declare global variables
In
/lib/main.dartadd the following declaration after theimportstatements:// Global key to access the scaffold messenger final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>(); -
Enable SnackBar messages
Update the root widget to add the
scaffoldMessengerKeyfor showing SnackBar messages, and set the background color. In/lib/main.dart, replace theMyAppclass with the following:class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', scaffoldMessengerKey: scaffoldMessengerKey, theme: ThemeData( scaffoldBackgroundColor: const Color(0xFFECE5DD), ), home: const MyHomePage(title: 'Agora Chat Quickstart'), ); } } -
Set up the app framework
To set up a Flutter app framework for Chat, you do the following:
- Create a stateful widget
- Declare variables to manage the connection and access UI elements
- Add a method to display information to the user
To do this, replace the
_MyHomePageStateclass with the following:class _MyHomePageState extends State<MyHomePage> { static const String appId = "<App ID from Agora console>"; static const String userId = "<User ID of the local user>"; String token = "<Your authentication token>"; late ChatClient agoraChatClient; bool isJoined = false; ScrollController scrollController = ScrollController(); TextEditingController messageBoxController = TextEditingController(); String messageContent = "", recipientId = ""; final List<Widget> messageList = []; showLog(String message) { scaffoldMessengerKey.currentState?.showSnackBar(SnackBar( content: Text(message), )); } }
Build the UI
In the quickstart app, you create a simple UI that consists of the following elements:
- An
ElevatedButtonto log in or out of Agora Chat - A
TextFieldto specify the recipient user ID - A
TextFieldto enter a text message - An
ElevatedButtonto send the text message - A
ListView.builderto display sent and received messages
To create this UI, add the following build method to the _MyHomePageState class:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
children: [
Expanded(
child: SizedBox(
height: 40,
child: TextField(
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Enter recipient's userId",
),
onChanged: (chatUserId) => recipientId = chatUserId,
),
),
),
const SizedBox(width: 10),
SizedBox(
width: 80,
height: 40,
child: ElevatedButton(
onPressed: joinLeave,
child: Text(isJoined ? "Leave" : "Join"),
),
),
],
),
const SizedBox(height: 10),
Expanded(
child: ListView.builder(
controller: scrollController,
itemBuilder: (_, index) {
return messageList[index];
},
itemCount: messageList.length,
),
),
Row(children: [
Expanded(
child: SizedBox(
height: 40,
child: TextField(
controller: messageBoxController,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Message",
),
onChanged: (msg) => messageContent = msg,
),
),
),
const SizedBox(width: 10),
SizedBox(
width: 50,
height: 40,
child: ElevatedButton(
onPressed: sendMessage,
child: const Text(">>"),
),
),
]),
],
),
),
);
}Send and receive messages
When a user opens the app, you instantiate and initialize a ChatClient. When the user taps the Join button, the app logs in to Agora Chat. When a user types a message in the text box and then presses Send, the typed message is sent to Agora Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.
The following figure shows the API call sequence for implementing this workflow.
API call sequence
To implement this workflow in your app, take the following steps:
-
Set up Chat when the app starts
When the app starts, you create an instance of the
ChatClientand set up callbacks to handle Chat events. To do this, add the followinginitStatemethod to the_MyHomePageStateclass:@override void initState() { super.initState(); setupChatClient(); setupListeners(); } -
Instantiate the
ChatClientTo implement peer-to-peer messaging, you use Chat SDK to initialize a
ChatClientinstance. In the_MyHomePageStateclass, add the following method afterinitState.void setupChatClient() async { ChatOptions options = ChatOptions.withAppId( appId, autoLogin: false, ); agoraChatClient = ChatClient.getInstance; await agoraChatClient.init(options); // Notify the SDK that the Ul is ready. After the following method is executed, callbacks within ChatRoomEventHandler and ChatGroupEventHandler can be triggered. await ChatClient.getlnstance.startCallback(); } -
Handle and respond to Chat events
To receive notification of Chat events such as connection, disconnection, and token expiration, you add a
ConnectionEventHandler. To handle message delivery and new message notifications, you add aChatEventHandler. When you receive theonMessageReceivednotification, you display the message to the user.In the
_MyHomePageStateclass, add the following methods aftersetupChatClient:void setupListeners() { agoraChatClient.addConnectionEventHandler( "CONNECTION_HANDLER", ConnectionEventHandler( onConnected: onConnected, onDisconnected: onDisconnected, onTokenWillExpire: onTokenWillExpire, onTokenDidExpire: onTokenDidExpire ), ); agoraChatClient.chatManager.addEventHandler( "MESSAGE_HANDLER", ChatEventHandler(onMessagesReceived: onMessagesReceived), ); } void onMessagesReceived(List<ChatMessage> messages) { for (var msg in messages) { if (msg.body.type == MessageType.TXT) { ChatTextMessageBody body = msg.body as ChatTextMessageBody; displayMessage(body.content, false); showLog("Message from ${msg.from}"); } else { String msgType = msg.body.type.name; showLog("Received $msgType message, from ${msg.from}"); } } } void onTokenWillExpire() { // The token is about to expire. Get a new token // from the token server and renew the token. } void onTokenDidExpire() { // The token has expired } void onDisconnected () { // Disconnected from the Chat server } void onConnected() { showLog("Connected"); } -
Log in to Agora Chat
When a user presses Join, your app logs in to Agora Chat. When a user presses Leave, the app logs out of Agora Chat.
To implement this logic, in the
_MyHomePageStateclass, add the following method beforeshowLog:void joinLeave() async { if (!isJoined) { // Log in try { await agoraChatClient.loginWithToken(userId, token); showLog("Logged in successfully as $userId"); setState(() { isJoined = true; }); } on ChatError catch (e) { if (e.code == 200) { // Already logged in setState(() { isJoined = true; }); } else { showLog("Login failed, code: ${e.code}, desc: ${e.description}"); } } } else { // Log out try { await agoraChatClient.logout(true); showLog("Logged out successfully"); setState(() { isJoined = false; }); } on ChatError catch (e) { showLog("Logout failed, code: ${e.code}, desc: ${e.description}"); } } } -
Send a message
To send a message to Agora Chat when a user presses the Send button, add the following method to the
_MyHomePageStateclass, afterjoinLeave:void sendMessage() async { if (recipientId.isEmpty || messageContent.isEmpty) { showLog("Enter recipient user ID and type a message"); return; } var msg = ChatMessage.createTxtSendMessage( targetId: recipientId, content: messageContent, ); ChatClient.getInstance.chatManager.addMessageEvent( "UNIQUE_HANDLER_ID", ChatMessageEvent( onSuccess: (msgId, msg) { _addLogToConsole("on message succeed"); }, onProgress: (msgId, progress) { _addLogToConsole("on message progress"); }, onError: (msgId, msg, error) { _addLogToConsole( "on message failed, code: ${error.code}, desc: ${error.description}", ); }, ), ); ChatClient.getInstance.chatManager.removeMessageEvent("UNIQUE_HANDLER_ID"); agoraChatClient.chatManager.sendMessage(msg); } -
Display chat messages
To display the messages the current user has sent and received in your app, add the following method to the
_MyHomePageStateclass:void displayMessage(String text, bool isSentMessage) { messageList.add(Row(children: [ Expanded( child: Align( alignment: isSentMessage ? Alignment.centerRight : Alignment.centerLeft, child: Container( padding: const EdgeInsets.all(10), margin: EdgeInsets.fromLTRB( (isSentMessage ? 50 : 0), 5, (isSentMessage ? 0 : 50), 5), decoration: BoxDecoration( color: isSentMessage ? const Color(0xFFDCF8C6) : const Color(0xFFFFFFFF), ), child: Text(text), ), ), ), ])); setState(() { scrollController.jumpTo(scrollController.position.maxScrollExtent + 50); }); } -
Remove event handlers on exit
When a user closes the app, you remove the message and connection event handlers. To do this, add the following
disposemethod to the_MyHomePageStateclass:@override void dispose() { agoraChatClient.chatManager.removeEventHandler("MESSAGE_HANDLER"); agoraChatClient.removeConnectionEventHandler("CONNECTION_HANDLER"); super.dispose(); }
Implementation
This section introduces the codes you need to add to your project to start one-to-one messaging.
Implement one-to-one messaging
To send a one-to-one message, users must register a Chat account, log in to Agora Chat, and send a text message.
Open simple_demo/App.js, and replace the code with the following:
// Imports dependencies.
import React, {useEffect} from 'react';
import {
SafeAreaView,
ScrollView,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import {
ChatClient,
ChatOptions,
ChatMessageChatType,
ChatMessage,
} from 'react-native-agora-chat';
// Defines the App object.
const App = () => {
// Defines the variable.
const title = 'AgoraChatQuickstart';
// Replaces <your App ID> with your App ID.
const appId = '<your App ID>';
// Replaces <your userId> with your user ID.
const [username, setUsername] = React.useState('<your userId>');
// Replaces <your agoraToken> with your Agora token.
const [chatToken, setChatToken] = React.useState('<your token>');
const [targetId, setTargetId] = React.useState('');
const [content, setContent] = React.useState('');
const [logText, setWarnText] = React.useState('Show log area');
const chatClient = ChatClient.getInstance();
const chatManager = chatClient.chatManager;
// Outputs console logs.
useEffect(() => {
logText.split('\n').forEach((value, index, array) => {
if (index === 0) {
console.log(value);
}
});
}, [logText]);
// Outputs UI logs.
const rollLog = text => {
setWarnText(preLogText => {
let newLogText = text;
preLogText
.split('\n')
.filter((value, index, array) => {
if (index > 8) {
return false;
}
return true;
})
.forEach((value, index, array) => {
newLogText += '\n' + value;
});
return newLogText;
});
};
useEffect(() => {
// Registers listeners for messaging.
const setMessageListener = () => {
let msgListener = {
onMessagesReceived(messages) {
for (let index = 0; index < messages.length; index++) {
rollLog('received msgId: ' + messages[index].msgId);
}
},
onCmdMessagesReceived: messages => {},
onMessagesRead: messages => {},
onGroupMessageRead: groupMessageAcks => {},
onMessagesDelivered: messages => {},
onMessagesRecalled: messages => {},
onConversationsUpdate: () => {},
onConversationRead: (from, to) => {},
};
chatManager.removeAllMessageListener();
chatManager.addMessageListener(msgListener);
};
// Initializes the SDK.
// Initializes any interface before calling it.
const init = () => {
let o = ChatOptions.withAppId({
autoLogin: false,
appId: appId,
});
chatClient.removeAllConnectionListener();
chatClient
.init(o)
.then(() => {
rollLog('init success');
let listener = {
onTokenWillExpire() {
rollLog('token expire.');
},
onTokenDidExpire() {
rollLog('token did expire');
},
onConnected() {
rollLog('onConnected');
setMessageListener();
},
onDisconnected(errorCode) {
rollLog('onDisconnected:' + errorCode);
},
};
chatClient.addConnectionListener(listener);
})
.catch(error => {
rollLog(
'init fail: ' +
(error instanceof Object ? JSON.stringify(error) : error),
);
});
};
init();
}, [chatClient, chatManager, appId]);
// Logs in with an account ID and a token.
const login = () => {
rollLog('start login ...');
chatClient
.loginWithToken(username, chatToken)
.then(() => {
rollLog('login operation success.');
})
.catch(reason => {
rollLog('login fail: ' + JSON.stringify(reason));
});
};
// Logs out from server.
const logout = () => {
rollLog('start logout ...');
chatClient
.logout()
.then(() => {
rollLog('logout success.');
})
.catch(reason => {
rollLog('logout fail:' + JSON.stringify(reason));
});
};
// Sends a text message to somebody.
const sendmsg = () => {
let msg = ChatMessage.createTextMessage(
targetId,
content,
ChatMessageChatType.PeerChat,
);
const callback = new (class {
onProgress(locaMsgId, progress) {
rollLog(`send message process: ${locaMsgId}, ${progress}`);
}
onError(locaMsgId, error) {
rollLog(`send message fail: ${locaMsgId}, ${JSON.stringify(error)}`);
}
onSuccess(message) {
rollLog('send message success: ' + message.localMsgId);
}
})();
rollLog('start send message ...');
chatClient.chatManager
.sendMessage(msg, callback)
.then(() => {
rollLog('send message: ' + msg.localMsgId);
})
.catch(reason => {
rollLog('send fail: ' + JSON.stringify(reason));
});
};
// Renders the UI.
return (
<SafeAreaView>
<View style={styles.titleContainer}>
<Text style={styles.title}>{title}</Text>
</View>
<ScrollView>
<View style={styles.inputCon}>
<TextInput
multiline
style={styles.inputBox}
placeholder="Enter username"
onChangeText={text => setUsername(text)}
value={username}
autoCapitalize={'none'}
/>
</View>
<View style={styles.inputCon}>
<TextInput
multiline
style={styles.inputBox}
placeholder="Enter chatToken"
onChangeText={text => setChatToken(text)}
value={chatToken}
autoCapitalize={'none'}
/>
</View>
<View style={styles.buttonCon}>
<Text style={styles.eachBtn} onPress={login}>
SIGN IN
</Text>
<Text style={styles.eachBtn} onPress={logout}>
SIGN OUT
</Text>
</View>
<View style={styles.inputCon}>
<TextInput
multiline
style={styles.inputBox}
placeholder="Enter the username you want to send"
onChangeText={text => setTargetId(text)}
value={targetId}
autoCapitalize={'none'}
/>
</View>
<View style={styles.inputCon}>
<TextInput
multiline
style={styles.inputBox}
placeholder="Enter content"
onChangeText={text => setContent(text)}
value={content}
autoCapitalize={'none'}
/>
</View>
<View style={styles.buttonCon}>
<Text style={styles.btn2} onPress={sendmsg}>
SEND TEXT
</Text>
</View>
<View>
<Text style={styles.logText}>{logText}</Text>
</View>
<View>
<Text style={styles.logText}>{}</Text>
</View>
<View>
<Text style={styles.logText}>{}</Text>
</View>
</ScrollView>
</SafeAreaView>
);
};
// Sets UI styles.
const styles = StyleSheet.create({
titleContainer: {
height: 60,
backgroundColor: '#6200ED',
},
title: {
lineHeight: 60,
paddingLeft: 15,
color: '#fff',
fontSize: 20,
fontWeight: '700',
},
inputCon: {
marginLeft: '5%',
width: '90%',
height: 60,
paddingBottom: 6,
borderBottomWidth: 1,
borderBottomColor: '#ccc',
},
inputBox: {
marginTop: 15,
width: '100%',
fontSize: 14,
fontWeight: 'bold',
},
buttonCon: {
marginLeft: '2%',
width: '96%',
flexDirection: 'row',
marginTop: 20,
height: 26,
justifyContent: 'space-around',
alignItems: 'center',
},
eachBtn: {
height: 40,
width: '28%',
lineHeight: 40,
textAlign: 'center',
color: '#fff',
fontSize: 16,
backgroundColor: '#6200ED',
borderRadius: 5,
},
btn2: {
height: 40,
width: '45%',
lineHeight: 40,
textAlign: 'center',
color: '#fff',
fontSize: 16,
backgroundColor: '#6200ED',
borderRadius: 5,
},
logText: {
padding: 10,
marginTop: 10,
color: '#ccc',
fontSize: 14,
lineHeight: 20,
},
});
export default App;Build and run your project
To build and run the app on iOS platform:
yarn run iosTo build and run the app on Android platform:
yarn run androidTo start the debug service:
yarn run startIf the project runs properly, the following user interface appears:
- Android platform
- iOS platform
Create the UI
In the quick start app, you create a simple UI that consists of the following elements:
- A
Button - TextMeshProto log in or out of Agora Chat. - An
Input Field - TextMeshProto specify the recipient user ID. - An
Input Field - TextMeshProto enter a text message. - A
Button - TextMeshProto send the text message. - A
Scroll Viewto display all sent and received messages.
To implement this user interface, in your Unity project:
-
Set up the Scroll View
-
In Unity Editor, right-click Sample Scene, then click Game Object > UI > Scroll View. A scroll view appears in the Scene Canvas. In Inspector, rename the Scroll View to
scrollView.If you can't see the view clearly in Unity, zoom out and rotate the scene
-
To adjust the
scrollViewsize, change the following coordinates in Inspector:- Pos X -
0 - Pos Y -
0 - Width -
250 - Height -
300
- Pos X -
-
In Hierarchy select scrollView > Viewport > Content. In Inspector click Add Component and choose Layout > Vertical Layout Group.
-
In Inspector click Add Component again, and select Layout > Content Size Fitter. Set the Vertical fit property of the component to
Preferred Size. -
In Inspector click Add Component again, and select UI > TextMeshPro - Text (UI). In the TMP Importer pop-up, click Import TMP Essentials. Your project imports the required components to your project. Expand the TextMeshPro - Text component properties and under Extra Settings set the Left, Top, Right and Bottom margins to
10.
-
-
Add a login button
-
In Hierarchy, right-click Sample Scene, then click UI > Button - TextMeshPro. A button appears in the Scene Canvas. In Inspector, rename Button to
joinBtn, then change the following properties:- Pos X -
89 - Pos Y -
160 - Width -
70 - Height -
30
- Pos X -
-
Select the Text (TMP) sub-item of
joinBtnand in Inspector, change Text toJoin.
-
-
Add a send button
-
Right-click Sample Scene, then click UI > Button - TextMeshPro. A button appears in the Scene Canvas. In Inspector, rename Button to
sendBtn, then change the following properties:- Pos X -
97 - Pos Y -
-162 - Width -
57 - Height -
30
- Pos X -
-
Select the Text (TMP) sub-item of
sendBtnand in Inspector, change Text to>>.
-
-
Add input fields to enter a message and a recipient user ID
-
Right-click Sample Scene, then click UI > Input Field - TextMeshPro. An input field appears in the Scene Canvas. In Inspector, rename InputField (TMP) to
message, and change the following coordinates:- Pos X -
-27 - Pos Y -
-162 - Width -
195 - Height -
30
- Pos X -
-
Repeat the procedure in the previous step to add another input field named
userName. In Inspector set the following coordinates:- Pos X -
-35 - Pos Y -
160 - Width -
180 - Height -
30
- Pos X -
-
Handle the system logic
In this section, you create a script file, add the necessary namespaces, and bind your script to the canvas.
-
Create a new script
-
In Project, open Assets > AgoraChat > Scripts. Right-click Scripts, then click Create > C# Script. In Assets, you see the
NewBehaviourScriptfile that you use to implement Chat SDK in your app. -
In Inspector, click Open.
NewBehaviourScript.csopens in your default text editor.
-
-
Import the relevant Agora and Unity classes
In
NewBehaviourScript.cs, add the following lines afterusing UnityEngine;:using UnityEngine.UI; using TMPro; using AgoraChat; using AgoraChat.MessageBody; -
Bind your script to the canvas
-
Drag
NewBehaviourScript.csfromAssets/AgoraChat/Scripts, and drop it on to Canvas in the Hierarchy. -
Click Canvas, you see that your script is added to Canvas in Inspector.
-
Send and receive messages
When a user opens the app, you instantiate and initialize a SDKClient. When the user taps the Join button, the app logs in to Agora Chat. When a user types a message in the text box and then presses >>, the typed message is sent to Agora Chat. When the app receives a message from the server, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.
The following figure shows the API call sequence for implementing this workflow.
API call sequence
To implement this workflow in your app, take the following steps:
-
Declare variables
In the
NewBehaviourScriptclass, add the following declarations:private TMP_Text messageList; private string userId = ""; private string token = ""; private string appId = ""; private bool isJoined = false; SDKClient agoraChatClient; -
Set up Chat when the app starts
When the app starts, you set up a
SDKClientand callbacks to handle Chat events. To do this, replace theStartmethod in theNewBehaviourScriptclass with the following:void Start() { GameObject.Find("userName/Text Area/Placeholder").GetComponent<TMP_Text>().text = "Enter recipient name"; GameObject.Find("message/Text Area/Placeholder").GetComponent<TMP_Text>().text = "Message"; messageList = GameObject.Find("scrollView/Viewport/Content").GetComponent<TextMeshProUGUI>(); messageList.fontSize = 14; messageList.text = ""; GameObject button = GameObject.Find("joinBtn"); button.GetComponent<Button>().onClick.AddListener(joinLeave); button = GameObject.Find("sendBtn"); button.GetComponent<Button>().onClick.AddListener(sendMessage); setupChatSDK(); } -
Instantiate the
SDKClientTo implement peer-to-peer messaging, you use Chat SDK to initialize a
SDKClientinstance. In theNewBehaviourScriptclass, add the following method beforeStart.void setupChatSDK() { if (appId == "") { Debug.Log("You should set your App ID first!"); return; } // Initialize the Agora Chat SDK Options options = Options.InitOptionsWithAppId(appId); options.UsingHttpsOnly = true; options.DebugMode = true; agoraChatClient = SDKClient.Instance; agoraChatClient.InitWithOptions(options); } -
Handle and respond to Chat events
To receive notification of Chat events such as connection, disconnection, and token expiration, you use
IChatManagerDelegateandIConnectionDelegate. When you receive theonMessageReceivednotification, you display the message to the user. To implement these notifications in your app, do the following:-
In the
NewBehaviourScriptclass, add the following at the end ofsetupChatSDK:agoraChatClient.ChatManager.AddChatManagerDelegate(this); -
Implement the
IChatManagerDelegateandIConnectionDelegateinterfaces in theNewBehaviourScriptclass. InNewBehaviourScript.cs, add the following afterpublic class NewBehaviourScript : MonoBehaviour:, IChatManagerDelegate, IConnectionDelegate -
In the
NewBehaviourScriptclass, add the following callbacks beforesetupChatSDK:public void OnMessagesReceived(List<Message> messages) { foreach (Message msg in messages) { if (msg.Body.Type == MessageBodyType.TXT) { TextBody txtBody = msg.Body as TextBody; string Msg = msg.From + ":" + txtBody.Text; displayMessage(Msg, false); } } } public void OnCmdMessagesReceived(List<Message> messages) { // This callback is triggered only by the reception of a command message that is usually invisible to users. } public void OnMessagesRead(List<Message> messages) { // Occurs when a read receipt is received for a message. } public void OnMessagesDelivered(List<Message> messages) { // Occurs when a delivery receipt is received. } public void OnMessagesRecalled(List<Message> messages) { // Occurs when a received message is recalled. } public void OnReadAckForGroupMessageUpdated() { // Occurs when the read status updates of a group message is received. } public void OnGroupMessageRead(List<GroupReadAck> list) { // Occurs when a read receipt is received for a group message. } public void OnConversationsUpdate() { // Occurs when the number of conversations changes. } public void OnConversationRead(string from, string to) { // Occurs when the read receipt is received for a conversation. } public void MessageReactionDidChange(List<MessageReactionChange> list) { // Occurs when the reactions change. } public void OnConnected() { Debug.Log("Connected"); } public void OnTokenExpired() { // Occurs when the token has expired. } public void OnTokenWillExpire() { // Occurs when the token is about to expire } public void OnAuthFailed() { // Occurs when the user is forced to log out of the current account due to an authentication failure. } public void OnKickedByOtherDevice() { // Occurs when the user is forced to log out of the current account on the current device due to login to another device. } public void OnLoginTooManyDevice() { // Occurs when the user is forced to log out of the current account because he or she reached the maximum number of devices that the user can log in to with the current account. } public void OnChangedIMPwd() { // Occurs when the user is forced to log out of the current account because the login password has changed. } public void OnForbidByServer() { // Occurs when the current user account is banned. } public void OnRemovedFromServer() { // Occurs when the current user account is removed from the server. } public void OnLoggedOtherDevice(string deviceName, string info) { // Occurs when the user logs in to another device with the current account. } public void OnDisconnected() { Debug.Log("Disconnected"); } public void OnMessageContentChanged(Message msg, string operatorId, long operationTime) { } public void OnMessagePinChanged(string messageId, string conversationId, bool isPinned, string operatorId, long operationTime) { } public void OnLoggedOtherDevice(string str) { } public void OnAppActiveNumberReachLimitation() { } public void OnMessageContentChanged(Message msg, string operatorId, long operationTime) { } public void OnMessagePinChanged(string messageId, string conversationId, bool isPinned, string operatorId, long operationTime) { } public void OnOfflineMessageSyncStart() { } public void OnOfflineMessageSyncFinish() { }
-
-
Log in to Agora Chat
When a user presses Join, your app logs in to Agora Chat. When a user presses Leave, the app logs out of Agora Chat. To implement this logic, in the
NewBehaviourScriptclass, add the following method beforeStart:public void joinLeave() { if (isJoined) { agoraChatClient.Logout(true, callback: new CallBack( onSuccess: () => { Debug.Log("Logout succeed"); isJoined = false; GameObject.Find("joinBtn").GetComponentInChildren<TextMeshProUGUI>().text = "Join"; }, onError: (code, desc) => { Debug.Log($"Logout failed, code: {code}, desc: {desc}"); })); } else { // Use LoginWithToken to replace LoginWithAgoraToken for the SDK of v1.3.0 or later agoraChatClient.LoginWithAgoraToken(userId, token, callback: new CallBack( onSuccess: () => { Debug.Log("Login succeed"); isJoined = true; GameObject.Find("joinBtn").GetComponentInChildren<TextMeshProUGUI>().text = "Leave"; }, onError: (code, desc) => { Debug.Log($"Login failed, code: {code}, desc: {desc}"); })); } } -
Send a message
To send a message to Agora Chat when a user presses the >> button, add the following method to the
NewBehaviourScriptclass, beforeStart:public void sendMessage() { string recipient = GameObject.Find("userName").GetComponent<TMP_InputField>().text; string Msg = GameObject.Find("message").GetComponent<TMP_InputField>().text; if (Msg == "" || recipient == "") { Debug.Log("You did not type your message"); return; } Message msg = Message.CreateTextSendMessage(recipient, Msg); displayMessage(Msg, true); agoraChatClient.ChatManager.SendMessage(ref msg, new CallBack( onSuccess: () => { Debug.Log($"Send message succeed"); GameObject.Find("message").GetComponent<TMP_InputField>().text = ""; }, onError: (code, desc) => { Debug.Log($"Send message failed, code: {code}, desc: {desc}"); })); } -
Display chat messages
To display sent and received messages in your app, add the following method to the
NewBehaviourScriptclass:public void displayMessage(string messageText, bool isSentMessage) { if (isSentMessage) { messageList.text += "<align=\"right\"><color=black><mark=#dcf8c655 padding=\"10, 10, 0, 0\">" + messageText + "</color></mark>\n"; } else { messageList.text += "<align=\"left\"><color=black><mark=#ffffff55 padding=\"10, 10, 0, 0\">" + messageText + "</color></mark>\n"; } } -
Clean up the resources
When you quit the app, it calls
OnApplicationQuit. You use this method for clean up. To Implement the clean up logic, in theNewBehaviourScriptclass, add the following afterStart:void OnApplicationQuit() { agoraChatClient.ChatManager.RemoveChatManagerDelegate(this); agoraChatClient.Logout(true, callback: new CallBack( onSuccess: () => { Debug.Log("Logout succeed"); }, onError: (code, desc) => { Debug.Log($"Logout failed, code: {code}, desc: {desc}"); })); }
Create the UI
In your project, create a simple UI that consists of the following elements:
- A
Buttonto Join or Leave Agora Chat. - A
TextBoxbox to specify the recipient user ID. - A
TextBoxbox to enter a text message. - A
Buttonto send the text message. - A scrollable layout to display sent and received messages.
To add the UI framework to your device project, In Solution Explorer, open <project-name> > MainWindow.xaml, then replace the file contents with the following:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AgoraWindowsChat"
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" x:Class="AgoraWindowsChat.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="457" Width="804">
<Grid x:Name="mainGrid">
<Button x:Name="btnJoinLeave" Content="Join" HorizontalAlignment="Left" Margin="662,53,0,0" VerticalAlignment="Top" Height="36" Width="107" Click="JoinLeave_Click" Background="#FF4B5ADE" FontSize="18">
<Button.Foreground>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/>
</Button.Foreground>
</Button>
<TextBox x:Name="eReciepientUserId" HorizontalAlignment="Left" Height="39" Margin="10,50,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="20" Width="642" Foreground="Gray" Opacity="1.0" Text="">
<TextBox.Resources>
<VisualBrush x:Key="HelpBrush" TileMode="None" Opacity="0.3" Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock FontStyle="Normal" Text="Recipient User Id"/>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Resources>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource HelpBrush}"/>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="{StaticResource HelpBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Button x:Name="btnMessageSend" Content=">>" HorizontalAlignment="Left" Margin="662,334,0,0" VerticalAlignment="Top" Height="36" Width="107" Click="MessageSend_Click" Background="#FF4B5ADE" FontSize="18">
<Button.Foreground>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/>
</Button.Foreground>
</Button>
<TextBox x:Name="eMessage" HorizontalAlignment="Left" Height="39" Margin="5,331,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="652" FontSize="20" Foreground="Gray" Opacity="1.0" Text="" >
<TextBox.Resources>
<VisualBrush x:Key="HelpBrush" TileMode="None" Opacity="0.3" Stretch="None" AlignmentX="Left">
<VisualBrush.Visual>
<TextBlock FontStyle="Normal" Text="Message"/>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Resources>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource HelpBrush}"/>
</Trigger>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="{StaticResource HelpBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Label x:Name="appNameLabel" Content=" agoraChatQuickStart" HorizontalAlignment="Left" Height="45" Margin="10,0,0,0" VerticalAlignment="Top" Width="759" Background="#FF4655D6" FontSize="22" FontWeight="Bold" Foreground="White"/>
<ScrollViewer x:Name="scrollMessagesView" HorizontalAlignment="Left" Height="198" Margin="10,94,0,0" VerticalAlignment="Top" Width="763" Foreground="#FF000000" Background="Linen" RenderTransformOrigin="0.5,0.5" VerticalScrollBarVisibility="Auto">
<StackPanel></StackPanel>
</ScrollViewer>
</Grid>
</Window>Handle the system logic
This section shows you how to add Chat SDK headers and setup logging. To do this:
-
Import the Agora namespaces
In the Solution Explorer, select
<project-name>>MainWindow.xaml, and double-click it to open theMainWindow.xaml.csfile. Add the following lines to the namespaces list in the file:using AgoraChat; using AgoraChat.MessageBody; -
Log events and show status updates to your users
In the
MainWindowclass, add the following helper method:private void showLog(string log) { // Show a message box Dip?.Invoke(() => { MessageBox.Show(log); }); // Write log Console.WriteLine(log); }
Send and receive messages
When a user opens the app, you instantiate and initialize a SDKClient. When the user clicks the Join button, the app logs in to Agora Chat. When a user types a message in the text box and then presses Send, the typed message is sent to another registered user. When the app receives a message from Agora Chat, the message is displayed in the message list. This simple workflow enables you to rapidly build a Chat client with basic functionality.
The following figure shows the API call sequence for implementing this workflow.
API call sequence
To implement this workflow in your app, take the following steps:
-
Declare connection variables
In the
MainWindowclass, add the following declarations:private readonly string userId = "<User ID of the local user>"; private string token = "<Your authentication token>"; private readonly string app_id = "<App ID from Agora console>"; private bool isJoined = false; // Update the UI from callbacks on a separate thread private readonly System.Windows.Threading.Dispatcher? Dip = null; -
Set up Chat when the app starts
When the app starts, you create an instance of
SDKClientand set up delegates to handle connection and Chat events. To do this, replace theMainWindow()constructor in theMainWindowclass with the following:public MainWindow() { // Initialize the thread dispatcher Dip = System.Windows.Threading.Dispatcher.CurrentDispatcher; // Initialize Chat SDK client setupChatClient(); // Add connection and chat delegates to handle callbacks SDKClient.Instance.AddConnectionDelegate(this); SDKClient.Instance.ChatManager.AddChatManagerDelegate(this); // Execute the CloseWindow method when the app closes Closed += CloseWindow; } -
Initialize the
SDKClientTo implement peer-to-peer messaging, you use Chat SDK to initialize a
SDKClientinstance. In theMainWindowclass, add the following method:private void setupChatClient() { var options = Options.InitOptionsWithAppId(app_id); options.UsingHttpsOnly = true; // Initialize the chat SDKClient SDKClient.Instance.InitWithOptions(options); } -
Log in to Agora Chat
When a user clicks Join, your app logs in to Agora Chat. When they click Leave, the app logs out. To implement this logic, add the following method after
showLog()in theMainWindowclass:private void JoinLeave_Click(object sender, RoutedEventArgs e) { Button button = (Button)this.FindName("btnJoinLeave"); if (isJoined) { SDKClient.Instance.Logout(true, callback: new CallBack( onSuccess: () => { showLog("Sign out from Agora Chat succeed"); Dip?.Invoke(() => { button.Content = "Join"; }); isJoined = false; }, onError: (code, desc) => { showLog(desc); } )); } else { // Log in to the Chat service with userId and Agora token. SDKClient.Instance.LoginWithToken(userId, token, callback: new CallBack( onSuccess: () => { showLog("Sign in to Agora Chat succeed"); isJoined = false; Dip?.Invoke(() => { button.Content = "Leave"; }); }, onError: (code, desc) => { if (code == 200) { // Already joined isJoined = true; Dip?.Invoke(() => { button.Content = "Leave"; }); } else { showLog(desc); } } )); } } -
Send a message
When a user types a message and presses the Send button, the app sends the message to the recipient. To do this, add the following method to the
MainWindowclass, afterJoinLeave_Click():private void MessageSend_Click(object sender, RoutedEventArgs e) { if (eReciepientUserId.Text.Equals("") || eMessage.Text.Equals("")) { showLog("Enter a recipient name and a message"); return; } //Send Message Message msg = Message.CreateTextSendMessage(eReciepientUserId.Text, eMessage.Text); SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( onSuccess: () => { // The success callback uses the System.Windows.Threading.Dispatcher to update UI elements Dip?.Invoke(() => { TextBody? txtBody = msg.Body as TextBody; if (txtBody != null) { displayMessage(txtBody.Text, true); } eMessage.Text = ""; }); }, onError: (code, desc) => { showLog(desc); } )); } -
Set up callbacks for handling Chat events
To set up callbacks for handling connection and Chat events, you implement the
IConnectionDelegateandIChatManagerDelegateinterfaces in theMainWindowclass. Update theMainWindowclass definition as follows:public partial class MainWindow : Window, IConnectionDelegate, IChatManagerDelegate -
Handle connection events
To implement all
IConnectionDelegatecallbacks, add the following code to theMainWindowclass:public void OnConnected() { showLog("SDK connected successfully."); } public void OnDisconnected() { showLog("SDK disconnected."); } public void OnLoggedOtherDevice(string deviceName, string info) { } public void OnRemovedFromServer() { } public void OnForbidByServer() { } public void OnChangedIMPwd() { } public void OnLoginTooManyDevice() { } public void OnKickedByOtherDevice() { } public void OnAuthFailed() { showLog("User authentication failed."); } public void OnTokenExpired() { showLog("The token has expired."); } public void OnTokenWillExpire() { showLog("The token is about to expire. Get a new token from the token server and renew the token."); } public void OnAppActiveNumberReachLimitation() { } public void OnOfflineMessageSyncStart() { } public void OnOfflineMessageSyncFinish() { } -
Handle Chat events
To read and display received chat messages, you add code to the
OnMessagesReceivedcallback of theIChatManagerDelegate. To implement allIChatManagerDelegatecallbacks, add the following code to theMainWindowclass:public void OnMessagesReceived(List<Message> messages) { foreach (Message msg in messages) { Dip?.Invoke(() => { TextBody? txtBody = msg.Body as TextBody; if (txtBody != null) { displayMessage(txtBody.Text, false); } }); } } public void OnCmdMessagesReceived(List<Message> messages) { } public void OnMessagesRead(List<Message> messages) { } public void OnMessagesDelivered(List<Message> messages) { } public void OnMessagesRecalled(List<Message> messages) { } public void OnReadAckForGroupMessageUpdated() { } public void OnGroupMessageRead(List<GroupReadAck> list) { } public void OnConversationsUpdate() { } public void OnConversationRead(string from, string to) { } public void MessageReactionDidChange(List<MessageReactionChange> list) { } public void OnMessageContentChanged(Message msg, string operatorId, long operationTime) { } public void OnMessagePinChanged(string messageId, string conversationId, bool isPinned, string operatorId, long operationTime) { } -
Display chat messages
To display sent and received messages, add the following method to the
MainWindowclass:private void displayMessage(string messageText, bool isSentMessage) { // Create a new TextBlock TextBlock messageTextBlock = new TextBlock(); messageTextBlock.Text = messageText; messageTextBlock.Padding = new Thickness(10); // Set formatting ScrollViewer? messageList = FindName("scrollMessagesView") as ScrollViewer; if (messageList != null) { if (isSentMessage) { messageTextBlock.Background = new SolidColorBrush(Color.FromRgb(220, 248, 198)); messageTextBlock.HorizontalAlignment = HorizontalAlignment.Right; messageTextBlock.Margin = new Thickness(100, 25, 15, 5); } else { messageTextBlock.Background = Brushes.White; messageTextBlock.HorizontalAlignment = HorizontalAlignment.Left; messageTextBlock.Margin = new Thickness(15, 25, 100, 5); } // Add the message TextBlock to the StackPanel inside the ScrollViewer StackPanel? messageStackPanel = messageList.Content as StackPanel; if (messageStackPanel != null) { messageStackPanel.Children.Add(messageTextBlock); messageList.ScrollToEnd(); // Scroll to the bottom of the messages } } } -
Clean up when the window is closed
Add the following method to the
MainWindowclass:private void CloseWindow(object sender, EventArgs e) { SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(this); SDKClient.Instance.DeleteConnectionDelegate(this); }
Test your implementation
To ensure that you have implemented Peer-to-Peer Messaging in your app:
-
Create an app instance for the first user:
-
In the
MainActivityclass, updateuserId,token, andappIdwith values from Agora Console. To get your App ID, see Get Chat project information. -
Connect a physical Android device to your development device.
-
In Android Studio, click Run app. A moment later you see the project installed on your device.
-
Create an app instance for the second user:
-
Register a second user in Agora Console and generate a user token.
-
In the
MainActivityclass, updateuserIdandtokenwith values for the second user. Make sure you use the sameappIdas for the first user. -
Run the modified app on a device emulator or a second physical Android device.
-
-
On each device, click Join to log in to Agora Chat.
-
Edit the recipient name on each device to show the user ID of the user logged in to the other device.
-
Type a message in the Message box of either device and press
>>.The message is sent and appears on the other device.
-
Press Leave to log out of Agora Chat.
-
Create an app instance for the first user:
-
In the
ViewControllerclass, updateuserId,token, andappIdwith values from Agora Console. To get your App ID, see Get Chat project information. -
Connect a physical device to your development device.
-
In Xcode, click Run app. A moment later you see the project installed on your device.
-
Create an app instance for the second user:
-
Register a second user in Agora Console and generate a user token.
-
In the
ViewControllerclass, updateuserIdandtokenwith values for the second user. Make sure you use the sameappIdas for the first user. -
Run the modified app on a device emulator or a second physical device.
-
-
On each device, click Join to log in to the Chat.
-
Edit the recipient name on each device to show the user ID of the user logged in to the other device.
-
Type a message in the Message box of either device and press
>>.The message is sent and appears on the other device.
-
Press Leave to log out of the Chat.
Use vite to build the project. You can run below commands to run the project.
$ npm install$ npm run devThe following page opens in your browser:
To validate the peer-to-peer messaging you have just integrated into your Web app using Agora Chat:
-
Log in
Fill in the user ID of the sender (
Leo) in the user id box and agora token in the token box, and click Login to log in to the app. -
Send a message
Fill in the user ID of the receiver (
Roy) in the single chat id box and type in the message ("Hi, how are you doing?") to send in the message content box, and click Send to send the message. -
Log out
Click Logout to log out of the app.
-
Receive the message
Open the same page in a new window, log in as the receiver (
Roy) and receive the message ("Hi, how are you doing?") sent from Leo.
-
Create an app instance for the first user:
-
In the
_MyHomePageStateclass, updateappId,token, anduserIdwith values from Agora Console. To get your App ID, see Get Chat project information. -
Connect a physical test device to your development device.
-
In your IDE, click Run app or launch your app from the terminal using
flutter run lib/main.dart. A moment later you see the project installed on your device.
-
Create an app instance for the second user:
-
Register a second user in Agora Console and generate a user token.
-
In the
_MyHomePageStateclass, updateuserIdandtokenwith values for the second user. Make sure you use the sameappIdas for the first user. -
Run the modified app on a device emulator or a second physical test device.
-
-
On each device, click Join to log in to Agora Chat.
-
Edit the recipient name on each device to show the user ID of the user logged in to the other device.
-
Type a message in the Message box of either device and press
>>.The message is sent and appears on the other device.
-
Press Leave to log out of Agora Chat.
You can log in to the app by either modifying the fields in the App.js file as stated below, or entering the required fields in the user interface.
To validate the peer-to-peer messaging you have just integrated into your app using Agora Chat, perform the following operations:
-
Log in a. In the
App.jsfile, replace the placeholders ofappId,username, andchatTokenwith the App ID, user ID, and Agora token of the sender. b. Run and build your app. c. On your simulator or physical device, click SIGN IN to log in with the sender account. -
Send a message Fill in the user ID of the receiver in the Enter the username you want to send box, type in te message to send in the Enter content box, and click SEND TEXT to send the message.
-
Log out Click SIGN OUT to log out of the sender account.
-
Receive the message a. After signing out, change the values of
appId,username, andchatTokento the user ID, Agora token, and App ID of the receiver in theApp.jsfile. b. Run the app on another device or simulator with the receiver account and receive the message sent in step 2.
You can also read from the logs on the UI to see whether you have successfully signed in, signed out, and sent and received a text message.
-
In the
NewBehaviourScriptclass, updateuserId,token, andappIdwith values from Agora Console. To get your App ID, see Get Chat project information. -
In Unity Editor, click Play. A moment later you see the project installed on your development device.
-
Click Join to log in to Agora Chat.
-
Type the recipient user name in the Recepient Name field.
-
Type a message in the Message field and press
>>.The message is sent and a confirmation message is displayed in the debug console.
-
Register the recipient user in Agora Console and Generate a user token.
-
In the
NewBehaviourScriptclass, updateuserIdandtokenwith values you generated for recipient. Make sure you use the sameappIdas for both users. -
Save your changes and click Play to run the app.
-
Click Join to log in to the Chat.
You see a message in the scroll view that you sent earlier.
-
Create an app instance for the first user:
-
In the
MainWindowclass, updateuserId,token, andappIdwith values from Agora Console. To get your App ID, see Get Chat project information. -
Click the Start button. You see the following interface:
-
Create an app instance for the second user:
-
Register a second user in Agora Console and generate a user token.
-
Build a second instance of your app after updating
userIdandtokenwith values for the second user. Make sure you use the sameappIdas for the first user. -
Click the Start button to launch the second instance.
-
-
On each instance, click Join to log in to Agora Chat.
-
Edit the recipient name in each app instance to show the user ID of the user logged in to the other instance.
-
Type a message in the Message box of either instance and press
>>. The message is sent and appears on the other app. -
Press Leave to log out from Agora Chat.
Reference
This section contains content that completes the information in this page, or points you to documentation that explains other aspects to this product.
- For more code samples, see Samples and demos.
- Manual install shows you how to integrate Chat SDK into your project manually.
Integration issues
If your project integrates Agora Chat SDK 1.3.2 or later and either Signaling SDK 2.2.0 or later or Video SDK 4.3.0 or later, you may encounter a compilation error because the libaosl.so library is included in both SDKs.
com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'lib/x86/libaosl.so'To resolve this issue, add packaging options under the Android node in the build.gradle file of your app. This ensures that the build process prioritizes the first matching file:
-
Android Gradle Plugin < 7.x
android { packagingOptions { pickFirst 'lib/**/libaosl.so' } } dependencies { implementation 'io.agora.infra:aosl:x.y.z' // implementation RTM sdk // implementation RTC sdk } -
Android Gradle Plugin 7.x or later
android { packaging { jniLibs { pickFirsts += ["lib/**/libaosl.so"] } } } dependencies { implementation 'io.agora.infra:aosl:x.y.z' // implementation RTM sdk // implementation RTC sdk }
-
Android Gradle Plugin < 7.x
android { packagingOptions { pickFirst("lib/**/libaosl.so") } } dependencies { implementation("io.agora.infra:aosl:x.y.z") // implementation RTM sdk // implementation RTC sdk } -
Android Gradle Plugin 7.x or later
android { packaging { jniLibs { pickFirsts += setOf("lib/**/libaosl.so") } } } dependencies { implementation("io.agora.infra:aosl:x.y.z") // implementation RTM sdk // implementation RTC sdk }
API reference
Integrate the SDK through CocoaPods
-
Install CocoaPods. For details, see Getting Started with CocoaPods.
-
In the Terminal, navigate to the project root directory and run the
pod initcommand to create a text filePodfilein the project folder. -
Open the
Podfilefile and add the Agora Chat SDK. Remember to replaceYour project targetwith the target name of your project.platform :ios, '11.0' target 'Your project target' do pod 'Agora_Chat_iOS' end -
In the project root directory, run the following command to integrate the SDK:
pod installWhen the SDK is installed successfully, you can see
Pod installation complete!in the Terminal and anxcworkspacefile in the project folder. -
Open the
xcworkspacefile in Xcode.
Add a privacy manifest file
The Agora Chat SDK for device provides the PrivacyInfo.xcprivacy file that contains the required reasons for the APIs used by the SDK. To add the privacy manifest to your app in Xcode, follow these steps:
-
Create a privacy manifest in your app project:
-
Choose File > New File.
-
Scroll down to the Resource section and select App Privacy File type.
-
Click Next.
-
Check your app in the Targets list.
-
Click Create.
The default file name is
PrivacyInfo.xcprivacywhich is also the required file name for bundled privacy manifests. -
-
Add the items in
PrivacyInfo.xcprivacyfile of the Agora Chat SDK toPrivacyInfo.xcprivacyof the app in either of the following ways:-
Add the following source code:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSPrivacyAccessedAPITypes</key> <array> <dict> <key>NSPrivacyAccessedAPITypeReasons</key> <array> <string>CA92.1</string> </array> <key>NSPrivacyAccessedAPIType</key> <string>NSPrivacyAccessedAPICategoryUserDefaults</string> </dict> <dict> <key>NSPrivacyAccessedAPITypeReasons</key> <array> <string>C617.1</string> </array> <key>NSPrivacyAccessedAPIType</key> <string>NSPrivacyAccessedAPICategoryFileTimestamp</string> </dict> </array> <key>NSPrivacyCollectedDataTypes</key> <array/> <key>NSPrivacyTrackingDomains</key> <array/> <key>NSPrivacyTracking</key> <false/> </dict> </plist> -
Add the list of items as shown in the following figure:
-
Frequently asked questions
API reference
For details:
-
Manual install shows you how to integrate Chat SDK into your project manually.
-
Sample code for getting started with Chat.
-
Install the demo app.
API reference
For details, see the sample code for getting started with Chat.
API reference
- Avoid blocked callbacks Each callback of a Chat client instance is triggered from internal threads. To avoid blocking internal threads, Agora recommends that you execute your operations in other threads when callbacks are triggered.
API reference
Next steps
In a production environment, best practice is to deploy your own token server. Users retrieve a token from the token server to log in to Chat. To see how to implement a server that generates and serves tokens on request, see Secure authentication with tokens.
