diff --git a/assets/images/signaling/authentication-workflow.puml b/assets/images/signaling/authentication-workflow.puml new file mode 100644 index 000000000..890eb03fd --- /dev/null +++ b/assets/images/signaling/authentication-workflow.puml @@ -0,0 +1,47 @@ +@startuml + +!include ../video-sdk/agora_skin.iuml + + +box "Implemented by you" + +participant "Token server" as TS + +participant "Your app" as APP + +end box + + +box "Agora" +participant "Signaling" as API +end box + +group Log in to Signaling using authentication +TS -> TS: Configure your token server using\n your App Id and App Certificate +APP -> TS: Request an RTM token using a user Id +TS -> TS: Validate request against internal security\n and generate a token +TS -> APP: Return RTM token to App +APP -> APP: Initiate the Signaling Engine using\n the App Id +APP -> API: Log in to Signaling using\n the user Id and the RTM token +API -> API: Validate the token +API -> APP: Log in user, then trigger callback +end + +group Join a stream channel +APP -> TS: Request an RTC token using\n a user Id, and a stream channel name +TS -> TS: Validate request against internal security\n and generate token +TS -> APP: Return RTC token to App +APP -> API: Join a stream channel using\n channel name, user Id, and the RTC token +end + +group Renew token +API -> APP: Trigger event:\n token privilege will expire +APP -> TS: Request an RTM token using\n the user ID +TS -> TS: Validate request against internal security\n and generate a token +TS -> APP: Return RTM token to App +API <- APP: Send RTM token to Signaling with a \ncall to renew token +API -> API: Validate the token +API -> APP: Trigger callback +end + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/authentication-workflow.svg b/assets/images/signaling/authentication-workflow.svg new file mode 100644 index 000000000..efa0ea6f0 --- /dev/null +++ b/assets/images/signaling/authentication-workflow.svg @@ -0,0 +1 @@ +Implemented by youAgoraToken serverToken serverYour appYour appSignalingSignalingLog in to Signaling using authenticationConfigure your token server usingyour App Id and App CertificateRequest an RTM token using a user IdValidate request against internal securityand generate a tokenReturn RTM token to AppInitiate the Signaling Engine usingthe App IdLog in to Signaling usingthe user Id and the RTM tokenValidate the tokenLog in user, then trigger callbackJoin a stream channelRequest an RTC token usinga user Id, and a stream channel nameValidate request against internal securityand generate tokenReturn RTC token to AppJoin a stream channel usingchannel name, user Id, and the RTC tokenRenew tokenTrigger event:token privilege will expireRequest an RTM token usingthe user IDValidate request against internal securityand generate a tokenReturn RTM token to AppSend RTM token to Signaling with acall to renew tokenValidate the tokenTrigger callback \ No newline at end of file diff --git a/assets/images/signaling/cloud-proxy.puml b/assets/images/signaling/cloud-proxy.puml new file mode 100644 index 000000000..745b1a505 --- /dev/null +++ b/assets/images/signaling/cloud-proxy.puml @@ -0,0 +1,45 @@ +@startuml cloud-proxy +!include ../others/agora_skin.iuml + +actor "User" as USR + +box "Implemented by you" +actor "Admin" as ADMIN +participant "App" as APP +participant "Enterprise Firewall" as FIREWALL +end box + +box "Provided by Agora" +participant "Cloud Proxy" as PROXY +participant "SD-RTN" as API +end box + +ADMIN -> FIREWALL: Whitelist IP addresses and ports\n for Cloud Proxy in the firewall. + +USR -> APP: Open the app +APP -> APP: Initialize the Signaling Engine + +group Enable cloud proxy +APP -> APP: Call the method to enable\na Cloud Proxy connection +APP -> FIREWALL: Request access to \n Cloud Proxy +FIREWALL-> FIREWALL : Check whitelist to grant\n access +FIREWALL -> PROXY: Request access to \n Cloud Proxy +PROXY -> APP: Proxy information +end + +USR -> APP: Join a channel + +APP -> PROXY: Join a channel +PROXY -> API: Ask to join a channel +API -> PROXY: Join success +PROXY -> APP: Join success +APP -> PROXY: Send data stream +PROXY <-> API: Send and receive data stream +PROXY -> APP: Receive data stream + +USR -> APP: Leave a channel +APP -> PROXY: Leave the channel +PROXY -> API: Channel leave + + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/cloud-proxy.svg b/assets/images/signaling/cloud-proxy.svg new file mode 100644 index 000000000..df6ffca59 --- /dev/null +++ b/assets/images/signaling/cloud-proxy.svg @@ -0,0 +1 @@ +Implemented by youProvided by AgoraUserUserAdminAdminAppAppEnterprise FirewallEnterprise FirewallCloud ProxyCloud ProxySD-RTNSD-RTNWhitelist IP addresses and portsfor Cloud Proxy in the firewall.Open the appInitialize the Signaling EngineEnable cloud proxyCall the method to enablea Cloud Proxy connectionRequest access toCloud ProxyCheck whitelist to grantaccessRequest access toCloud ProxyProxy informationJoin a channelJoin a channelAsk to join a channelJoin successJoin successSend data streamSend and receive data streamReceive data streamLeave a channelLeave the channelChannel leave \ No newline at end of file diff --git a/assets/images/signaling/data-encryption.puml b/assets/images/signaling/data-encryption.puml new file mode 100644 index 000000000..e590cbe34 --- /dev/null +++ b/assets/images/signaling/data-encryption.puml @@ -0,0 +1,33 @@ +@startuml media-stream-encryption +!include ../others/agora_skin.iuml + +actor "User" as USR + +box "Implemented by you" +participant "Authentication system" as SVR +participant "App" as APP +end box + +box "Provided by Agora" +participant "SD-RTN" as API +end box + + +USR -> APP: Start the app + +group Setup media stream encryption +APP -> SVR: Login to the \nauthentication system +APP <-> SVR: Retrieve a 32-byte key +APP <-> SVR: Retrieve a 32-byte salt in \nBase64 format +APP -> APP: Create a encryption configuration using \nthe key and salt +APP -> API: Set the encryption configuration +end +APP -> APP: Initiate the Signaling Engine + +USR -> APP: Select a channel to join +APP <-> SVR: Retrieve an access token. +APP <-> API: Join a channel +APP <-> API: Communicate over an\n encrypted data stream + + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/data-encryption.svg b/assets/images/signaling/data-encryption.svg new file mode 100644 index 000000000..5d2deb717 --- /dev/null +++ b/assets/images/signaling/data-encryption.svg @@ -0,0 +1 @@ +Implemented by youProvided by AgoraUserUserAuthentication systemAuthentication systemAppAppSD-RTNSD-RTNStart the appSetup media stream encryptionLogin to theauthentication systemRetrieve a 32-byte keyRetrieve a 32-byte salt inBase64 formatCreate a encryption configuration usingthe key and saltSet the encryption configurationInitiate the Signaling EngineSelect a channel to joinRetrieve an access token.Join a channelCommunicate over anencrypted data stream \ No newline at end of file diff --git a/assets/images/signaling/get-started-workflow.puml b/assets/images/signaling/get-started-workflow.puml new file mode 100644 index 000000000..7fa3d1154 --- /dev/null +++ b/assets/images/signaling/get-started-workflow.puml @@ -0,0 +1,38 @@ +@startuml + +!include ../video-sdk/agora_skin.iuml + +actor "User" as USR + +box "Your app" +participant "Signaling SDK" as APP +end box + +box "Agora" +participant "Signaling" as API +end box + +group Initialize +USR -> APP: Open app +APP -> APP: Create a signalingEngine instance +APP -> APP: Add event listeners +APP -> APP: Set the authentication token +APP -> API: Log in to Signaling +end + +group Messages +USR -> APP: Subscribe to a channel +APP -> API: signalingEngine.subscribe +USR -> APP: Publish message +APP -> API: signalingEngine.publish +APP -> APP: Listen for message events +API -> APP: message +APP -> USR: Receive message +end + +group Close +USR -> APP: Log out +APP -> API: Log out of Signaling +end + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/get-started-workflow.svg b/assets/images/signaling/get-started-workflow.svg new file mode 100644 index 000000000..67c35e610 --- /dev/null +++ b/assets/images/signaling/get-started-workflow.svg @@ -0,0 +1 @@ +Your appAgoraUserUserSignaling SDKSignaling SDKSignalingSignalingInitializeOpen appCreate a signalingEngine instanceAdd event listenersSet the authentication tokenLog in to SignalingMessagesSubscribe to a channelsignalingEngine.subscribePublish messagesignalingEngine.publishListen for message eventsmessageReceive messageCloseLog outLog out of Signaling \ No newline at end of file diff --git a/assets/images/signaling/presence-workflow.puml b/assets/images/signaling/presence-workflow.puml new file mode 100644 index 000000000..826225bc9 --- /dev/null +++ b/assets/images/signaling/presence-workflow.puml @@ -0,0 +1,50 @@ +@startuml + +!include ../video-sdk/agora_skin.iuml + +actor "User" as USR + +box "Your app" +participant "Signaling SDK" as APP +end box + +box "Agora" +participant "Signaling" as API +end box + +group Initialize +USR -> APP: Open app +APP -> APP: Create a signalingEngine instance +APP -> APP: Add the presence event listener +APP -> APP: Set the authentication token +APP -> API: Log in to Signaling +end + +group Presence notifications +USR -> APP: Join a channel +APP -> API: Subscribe to a channel \nand enable presence events for the channel +API -> APP: Presence event:\n A remote user joins, leaves \nor changes status in the channel +APP -> APP: Read the event arguments +APP -> USR: Inform users +end + +group Presence queries +USR -> APP: Load the list of users in the channel +APP <-> API: Call getOnlineUsers +USR -> APP: Load the channel list for a user +APP <-> API: Call getUserChannels +end + +group User status +USR -> APP: Set own status +APP -> API: Call setState +USR -> APP: Query the status of a remote user +APP <-> API: Call getState +end + +group Close +USR -> APP: Log out +APP -> API: Log out of Signaling +end + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/presence-workflow.svg b/assets/images/signaling/presence-workflow.svg new file mode 100644 index 000000000..18d5029f2 --- /dev/null +++ b/assets/images/signaling/presence-workflow.svg @@ -0,0 +1 @@ +Your appAgoraUserUserSignaling SDKSignaling SDKSignalingSignalingInitializeOpen appCreate a signalingEngine instanceAdd the presence event listenerSet the authentication tokenLog in to SignalingPresence notificationsJoin a channelSubscribe to a channeland enable presence events for the channelPresence event:A remote user joins, leavesor changes status in the channelRead the event argumentsInform usersPresence queriesLoad the list of users in the channelCall getOnlineUsersLoad the channel list for a userCall getUserChannelsUser statusSet own statusCall setStateQuery the status of a remote userCall getStateCloseLog outLog out of Signaling \ No newline at end of file diff --git a/assets/images/signaling/signaling-metadata-workflow.puml b/assets/images/signaling/signaling-metadata-workflow.puml new file mode 100644 index 000000000..7dac57b47 --- /dev/null +++ b/assets/images/signaling/signaling-metadata-workflow.puml @@ -0,0 +1,56 @@ +@startuml + +!include ../video-sdk/agora_skin.iuml + +actor "User" as USR + +box "Your app" +participant "Signaling SDK" as APP +end box + +box "Agora" +participant "Signaling" as API +end box + +group Initialize +USR -> APP: Open app +APP -> APP: Create a Signaling client +APP -> APP: Add client event callbacks +APP -> APP: Create a Signaling channel +APP -> APP: Add channel event callbacks +APP -> API: Log in to Signaling +APP -> API: Join a channel +end + +group Read and write user metadata +APP -> API: Set local user metadata +USR -> APP: Change user information +APP -> API: Add, update, or delete local user metadata +APP -> API: Subscribe to metadata of remote users +APP <- API: On user metadata updated callback +APP <- API: Retrieve metadata of a remote user +end + +group Read and write channel metadata +APP -> API: Set channel metadata +USR -> APP: Update channel information +APP -> API: Add, update, or delete channel metadata +APP <- API: On channel metadata updated callback +APP <- API: Retrieve channel metadata +end + +group Use locks +APP -> API: Set a lock +USR -> APP: Update channel metadata with locking +APP -> API: Acquire the lock +APP -> API: Specify the lock name when updating metadata +end + +group Close +USR -> APP: Leave the channel +APP -> API: Release locks +APP -> API: Unsubscribe from user metadata update notifications +APP -> API: Log out of Signaling +end + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/signaling-metadata-workflow.svg b/assets/images/signaling/signaling-metadata-workflow.svg new file mode 100644 index 000000000..ff5f3c62d --- /dev/null +++ b/assets/images/signaling/signaling-metadata-workflow.svg @@ -0,0 +1 @@ +Your appAgoraUserUserSignaling SDKSignaling SDKSignalingSignalingInitializeOpen appCreate a Signaling clientAdd client event callbacksCreate a Signaling channelAdd channel event callbacksLog in to SignalingJoin a channelRead and write user metadataSet local user metadataChange user informationAdd, update, or delete local user metadataSubscribe to metadata of remote usersOn user metadata updated callbackRetrieve metadata of a remote userRead and write channel metadataSet channel metadataUpdate channel informationAdd, update, or delete channel metadataOn channel metadata updated callbackRetrieve channel metadataUse locksSet a lockUpdate channel metadata with lockingAcquire the lockSpecify the lock name when updating metadataCloseLeave the channelRelease locksUnsubscribe from user metadata update notificationsLog out of Signaling \ No newline at end of file diff --git a/assets/images/signaling/signaling-pricing-plans.png b/assets/images/signaling/signaling-pricing-plans.png new file mode 100644 index 000000000..fc398b5f9 Binary files /dev/null and b/assets/images/signaling/signaling-pricing-plans.png differ diff --git a/assets/images/signaling/signaling-quickstart-android.png b/assets/images/signaling/signaling-quickstart-android.png new file mode 100644 index 000000000..470563c02 Binary files /dev/null and b/assets/images/signaling/signaling-quickstart-android.png differ diff --git a/assets/images/signaling/stream-channel-workflow.puml b/assets/images/signaling/stream-channel-workflow.puml new file mode 100644 index 000000000..b24108c38 --- /dev/null +++ b/assets/images/signaling/stream-channel-workflow.puml @@ -0,0 +1,65 @@ +@startuml + +!include ../video-sdk/agora_skin.iuml + +actor "User" as USR + +box "Your app" +participant "Signaling SDK" as APP +end box + +box "Agora" +participant "Signaling" as API +end box + +group Initialize +USR -> APP: Open app +APP -> APP: Create a signalingEngine instance +APP -> APP: Add user event callbacks +APP -> APP: Set the authentication token +APP -> API: Log in to Signaling +end + +group Channel + +USR -> APP: Create stream channel +APP <-> API: Create channel or add user to channel +USR -> APP: Subscribe to a channel +API <-> APP: Channel events + +group Topic +USR -> APP: Join topic +APP <-> API: Create topic or add user to topic +USR -> APP: Subscribe to topic +API <-> APP: Topic events +group Messages + +USR -> APP: Send message +APP -> API: Publish message to topic + +API -> APP: Message from topic +APP -> APP: Listen for message events +APP -> USR: Receive message +end +USR -> APP: Leave topic +APP <-> API: Leave topic + +end +USR -> APP: Leave channel +APP <-> API: Leave channel +end + +group Presence + +USR -> APP: Change status +APP -> APP: listen for user events +API -> APP: ConnectionStateChanged +APP -> USR: Inform users + +end +group Close +USR -> APP: Log out +APP -> API: Log out of Signaling +end + +@enduml \ No newline at end of file diff --git a/assets/images/signaling/stream-channel-workflow.svg b/assets/images/signaling/stream-channel-workflow.svg new file mode 100644 index 000000000..f157a924b --- /dev/null +++ b/assets/images/signaling/stream-channel-workflow.svg @@ -0,0 +1 @@ +Your appAgoraUserUserSignaling SDKSignaling SDKSignalingSignalingInitializeOpen appCreate a signalingEngine instanceAdd user event callbacksSet the authentication tokenLog in to SignalingChannelCreate stream channelCreate channel or add user to channelSubscribe to a channelChannel eventsTopicJoin topicCreate topic or add user to topicSubscribe to topicTopic eventsMessagesSend messagePublish message to topicMessage from topicListen for message eventsReceive messageLeave topicLeave topicLeave channelLeave channelPresenceChange statuslisten for user eventsConnectionStateChangedInform usersCloseLog outLog out of Signaling \ No newline at end of file diff --git a/broadcast-streaming/reference/cloud-proxy-allowed-ips.mdx b/broadcast-streaming/reference/cloud-proxy-allowed-ips.mdx index 8e1ed1a0e..2929b5b64 100644 --- a/broadcast-streaming/reference/cloud-proxy-allowed-ips.mdx +++ b/broadcast-streaming/reference/cloud-proxy-allowed-ips.mdx @@ -7,7 +7,7 @@ description: > --- -import Proxy from '../../shared/video-sdk/_cloud-proxy-allowed-iplist.mdx'; +import Proxy from '../../shared/common/_cloud-proxy-allowed-iplist.mdx'; export const toc = [{}]; diff --git a/flexible-classroom/reference/ui-scene.mdx b/flexible-classroom/reference/ui-scene.mdx index 43fc00ff6..fe5696ac3 100644 --- a/flexible-classroom/reference/ui-scene.mdx +++ b/flexible-classroom/reference/ui-scene.mdx @@ -1,5 +1,5 @@ --- -title: 'UI Scene SDK' +title: 'FcrUIScene SDK' sidebar_position: 5 type: docs description: > diff --git a/interactive-live-streaming/reference/cloud-proxy-allowed-ips.mdx b/interactive-live-streaming/reference/cloud-proxy-allowed-ips.mdx index 8e1ed1a0e..2929b5b64 100644 --- a/interactive-live-streaming/reference/cloud-proxy-allowed-ips.mdx +++ b/interactive-live-streaming/reference/cloud-proxy-allowed-ips.mdx @@ -7,7 +7,7 @@ description: > --- -import Proxy from '../../shared/video-sdk/_cloud-proxy-allowed-iplist.mdx'; +import Proxy from '../../shared/common/_cloud-proxy-allowed-iplist.mdx'; export const toc = [{}]; diff --git a/iot/reference/cloud-proxy-allowed-ips.mdx b/iot/reference/cloud-proxy-allowed-ips.mdx index 5fde83e45..2ce375a2f 100644 --- a/iot/reference/cloud-proxy-allowed-ips.mdx +++ b/iot/reference/cloud-proxy-allowed-ips.mdx @@ -7,7 +7,7 @@ description: > --- -import Proxy from '../../shared/video-sdk/_cloud-proxy-allowed-iplist.mdx'; +import Proxy from '../../shared/common/_cloud-proxy-allowed-iplist.mdx'; export const toc = [{}]; diff --git a/shared/video-sdk/_cloud-proxy-allowed-iplist.mdx b/shared/common/_cloud-proxy-allowed-iplist.mdx similarity index 98% rename from shared/video-sdk/_cloud-proxy-allowed-iplist.mdx rename to shared/common/_cloud-proxy-allowed-iplist.mdx index 1795bf757..f25204eee 100644 --- a/shared/video-sdk/_cloud-proxy-allowed-iplist.mdx +++ b/shared/common/_cloud-proxy-allowed-iplist.mdx @@ -1,5 +1,5 @@ -Agora deploys dedicated servers to run the cloud proxy service. Agora owns the IP addresses and fully controls the traffic on these addresses. To use Agora Cloud Proxy Force UDP or Force TCP modes, your end users must first configure their firewalls to trust the following IP address and port ranges. +Agora deploys dedicated servers to run the cloud proxy service. Agora owns the IP addresses and fully controls the traffic on these addresses. To use Agora Cloud Proxy, your end users must first configure their firewalls to trust the following IP address and port ranges. When adding IP addresses: diff --git a/shared/common/_core-concepts.mdx b/shared/common/_core-concepts.mdx index 4c752276c..8944a76b9 100644 --- a/shared/common/_core-concepts.mdx +++ b/shared/common/_core-concepts.mdx @@ -1,16 +1,6 @@ Before you start writing your code, familiarize yourself with the core concepts that SDKs are built on. - -## - -Agora's core engagement services are powered by its Software-Defined Real-time Network (SD-RTN™) that is accessible and available anytime, anywhere around the world. The software-defined network isn’t confined by device, phone numbers, or a telecommunication provider’s coverage area like traditional networks. has data centers globally that cover over 200+ countries and regions. The network delivers sub-second latency and high availability of real-time video and audio anywhere on the globe. With , Agora can deliver live user engagement experiences in the form of real-time communication (RTC) with the following advantages: - -* Unmatched quality of service -* High availability and accessibility -* True scalability -* Low Cost - ## is the main dashboard where you manage your projects and services. provides an intuitive interface for developers to query and manage their account. After registering an Agora Account, you use the console to perform the following tasks: @@ -25,31 +15,38 @@ Agora's core engagement services are powered by its Software-Defined Real-time N also provides RESTful APIs that you use to implement features such as creating a project and fetching usage numbers programmatically. + +## + +Agora's core engagement services are powered by its Software-Defined Real-time Network (SD-RTN™) that is accessible and available anytime, anywhere around the world. The software-defined network isn’t confined by device, phone numbers, or a telecommunication provider’s coverage area like traditional networks. has data centers globally that cover over 200+ countries and regions. The network delivers sub-second latency and high availability of real-time video and audio anywhere on the globe. With , Agora can deliver live user engagement experiences in the form of real-time communication (RTC) with the following advantages: + +* Unmatched quality of service +* High availability and accessibility +* True scalability +* Low Cost + +## App + +The software you create that integrates functionality. One instance only of your +may be installed on a device at a time. + ## App ID The App ID is a random string generated within when you create a new project. You can create multiple projects in your account; each project has a different App ID. This App ID enables your app users to communicate securely with each other. When you initialize in your app, you pass the App ID as an argument. The App ID is also used to create the authentication tokens that ensure secure communication in a channel. You retrieve your App ID using . uses this App ID to identify each app, provide billing and other statistical data services. - - - - - - + + For applications requiring high security in a production environment, you must choose a App ID + Token mechanism for [user authentication](../develop/authentication-workflow) when creating a new project. Without an authentication token, your environment is open to anyone with access to your App ID. - - - - - For applications requiring high security in a production environment, you must choose a App ID + Token mechanism for user authentication when creating a new project. Without an authentication token, your environment is open to anyone with access to your App ID. - + For applications requiring high security in a production environment, you must choose a App ID + Token mechanism for [user authentication](../get-started/authentication-workflow) when creating a new project. Without an authentication token, your environment is open to anyone with access to your App ID. @@ -57,47 +54,18 @@ For applications requiring high security in a production environment, you must c An App certificate is a string generated by to enable token authentication. It is required for generating an or authentication token. To get your app certificate from , see [Manage app certificates](../reference/manage-agora-account#get-the-app-certificate). - - - - - - + To use your App certificate for setting up a token server, see [Create and run a token server.](../develop/authentication-workflow#create-and-run-a-token-server) - - - - - - + To use your App certificate for setting up a token server, see [Create and run a token server.](../get-started/authentication-workflow#create-and-run-a-token-server) -## Token - -A token is a dynamic key that is used by the authentication server to check user permissions. You use to generate a temporary token for testing purposes during the development process. In a production environment, you implement a token server in your security infrastructure to control access to your channels. - - - - - - -For more information, see [Secure authentication with tokens](../develop/authentication-workflow). - - - - - - - - -For more information, see [Secure authentication with tokens](../get-started/authentication-workflow). - - ## Channel + uses the *channel name* to identify a channel. Users who specify the same *channel name* join a common channel and interact with each other. A channel is created when the first user joins. It ceases to exist when the last user leaves. You create a channel by calling the methods for transmitting real-time data. uses different channels to transmit different types of data. The channel transmits audio or video data, while the channel transmits messaging or signaling data. The and channels are independent of each other. @@ -113,10 +81,27 @@ The SDK applies different optimization methods according to the selected channel | COMMUNICATION | This profile is suitable for one-on-one or group calls, where all users in the channel talk freely. | | LIVE\_BROADCASTING | In a live streaming channel, users have two client roles: *host* and *audience*. The *host* sends and receives audio or video, while the *audience* only receives audio or video with the sending function disabled. | -## User ID + + + -A user ID (UID) identifies a user in a channel. Each user in a channel should have a unique user ID. If you do not specify a user ID when the user joins a channel, a UID is automatically generated and assigned to the user. +A data transfer management mechanism for passing data from one device to another. Any user who subscribes to or joins a channel can receive messages or events transmitted in that channel. Clients can subscribe to or join multiple channels at the same time. + includes the following types of channels: + +| Channel type | Main features | Applicable scenario| +|---------------|---------------|--------------------| +| Message | Follows the industry-standard pub/sub model. Channels do not need to be created in advance, and there is no upper limit on the number of publishers and subscribers in a channel.|Multi-device management and command exchange in the IoT industry, location tracking in smart devices, etc.| +| Stream |Follows the chat room model. Users need to join the channel to send and receive event notifications. Messages are managed and delivered through topics, and a single channel allows up to 1000 users to join at the same time. Supports channel sharing and synchronous transmission of audio and video data.|High-frequency and large concurrent data transmission or co-channel and synchronous transmission with audio and video data, such as metaverse, cloud games, etc.| + + + +## Device + +A physical or virtual device that connects to . For example, a mobile device, computer, +smart watch, or IoT device. + + ## Stream A stream is a sequence of digitally-encoded coherent signals that contains audio or video data. Users in a channel [publish](#publish) local streams and [subscribe](#subscribe) to remote streams from other users. @@ -131,6 +116,41 @@ After successfully publishing a stream, the SDK continues sending media data to Subscribing is the act of receiving media streams published by remote users to the channel. A user receives audio and video data from other users by subscribing to one or more of their streams. You either directly play the subscribed streams or process incoming data for other purposes such as recording or capturing screenshots. For further details, on how to create, manage and update your account, see [Manage your account](../reference/manage-agora-account). + + +## Token + +A token is a dynamic key that is used by the authentication server to check user permissions. You use to generate a temporary token for testing purposes during the development process. In a production environment, you implement a token server in your security infrastructure to control access to your channels. + + + +For more information, see [Secure authentication with tokens](../get-started/authentication-workflow). + + + +For more information, see [Secure authentication with tokens](../get-started/authentication-workflow). + + + +## User ID + + +A User ID (UID) identifies a user in a channel. Each user in a channel should have a unique user ID. If you do not + specify a user ID when the user joins a channel, a UID is automatically generated and assigned to the user. + + + +A user ID (UID) identifies a user in a channel. A user is a person or entity that logs into your . +Each user in a [project](#app-id) must have a globally unique UID. + +The same UID cannot log in to from multiple devices at the same time. If s with the same UID logs in to , the that logged in first +is disconnected and sent an event notification. + +The UID is used for billing and online status notifications. + + diff --git a/shared/common/_create-run-token-server.mdx b/shared/common/_create-run-token-server.mdx new file mode 100644 index 000000000..22b8faff9 --- /dev/null +++ b/shared/common/_create-run-token-server.mdx @@ -0,0 +1,65 @@ +This section shows you how to deploy a token server on a cloud platform. + +1. Start deploying the token server to your cloud platform: + The cloud platform retrieves the project code and necessary files from Github, then takes you to the + **Deployment** page. + - [Render](https://render.com/deploy?repo=https://github.com/AgoraIO-Community/agora-token-service) + - [Railway](https://railway.app/new/template/NKYzQA?referralCode=waRWUT) + - [Heroku](https://www.heroku.com/deploy/?template=https://github.com/AgoraIO-Community/agora-token-service) + +1. Fill in the information needed by your cloud platform: + + 1. `Blueprint name`: A unique name for your deployment. + + 1. `Branch name`: The branch of the repo or fork you want to deploy, default is main. + + 1. `APP_CERTIFICATE`: The App Certificate obtained from . + + 1. `APP_ID`: The [App ID](../reference/manage-agora-account#get-the-app-id) obtained from . + + 1. `Github account`: The GitHub account where the cloud platform should clone the token server repository. + + 1. `Repository name`: The name of the cloned repository, the default is `agora-token-service`. + + 1. `Private repository`: Select this option to hide this repository. + +2. Click **Deploy**. The platform configures and builds the token server. + +3. Click the **URL**. + + You are notified of a URL where your server is deployed. Click the link and open the token server in your + browser. Don’t worry if you see `404 page not found` in your browser. Follow the next steps and test your server. + +4. Test your server + + To retrieve a token, send a request to the token server using a URL based on the [Token server GET request structure](#token-server-get-request-structure): + + + ```text + /rtc/:channelName/:role/:tokentype/:uid/?expiry=expireTime + ``` + + For example: `https://agora-token-service-production-1234.up.railway.app/rtc/MyChannel/1/uid/1/?expiry=300` + + + + ```text + /rtm/:uid/?expiry=expireTime + ``` + + For example: `https://agora-token-service-production-1234.up.railway.app/rtm/bob/?expiry=600` + + + Your token server returns a JSON object containing an encrypted token: + + + ```json + {"rtcToken":"ThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleToken"} + ``` + + + ```json + {"rtmToken":"ThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleToken"} + ``` + + diff --git a/shared/common/_manage-agora-account.mdx b/shared/common/_manage-agora-account.mdx index 3aa4cab28..601a3a70c 100644 --- a/shared/common/_manage-agora-account.mdx +++ b/shared/common/_manage-agora-account.mdx @@ -10,7 +10,7 @@ import OnlinePayment from '@docs/shared/common/manage-agora-account/_online-paym import Ticket from '@docs/shared/common/manage-agora-account/_ticket.mdx'; import DeleteAccount from '@docs/shared/common/manage-agora-account/_delete-account.mdx'; - +This page shows you how to use to manage all aspects of your account. diff --git a/shared/common/_supported-platforms.mdx b/shared/common/_supported-platforms.mdx index 364d401ea..630866ef4 100644 --- a/shared/common/_supported-platforms.mdx +++ b/shared/common/_supported-platforms.mdx @@ -1,7 +1,8 @@ -import * as data from '@site/data/variables'; import {ProductWrapper} from "../../../src/mdx-components/ProductWrapper"; +import * as data from '@site/data/variables'; This section lists the platforms and products you use to develop apps that interact with . + - *Android*: @@ -10,7 +11,7 @@ This section lists the platforms and products you use to develop apps that inter | The latest version of Chrome | Supported | Supported | | The latest version of WeChat | Supported | Supported | - *iOS*: - |Operating system |Features |VP9 | H.264| + |Operating system |Features |VP8 | H.264| |---|---|---|---| |Applications with built-in WebView|Receiving streams|iOS 12.2 and later |iOS 12.1.4 and later| |Applications with built-in WebView| Sending streams|iOS 14.3 and later |iOS 14.3 and later| @@ -22,6 +23,7 @@ This section lists the platforms and products you use to develop apps that inter |Windows|
  • Chrome
  • Firefox
  • Edge
|Supported |Supported| |ChromeOS |Chrome |Supported |Supported| + To ensure the best user experience, best practice is to use the latest version each browser on the latest version of the operating system. Download the latest version of: - [Chrome](https://www.google.com/intl/en/chrome/) @@ -29,7 +31,6 @@ To ensure the best user experience, best practice is to use the latest version e - [Edge](https://microsoft.com/edge) - [Safari](https://support.apple.com/en-hk/HT201541) -
@@ -148,6 +149,7 @@ To ensure the best user experience, best practice is to use the latest version e | Flutter | Flutter 1.0.0 or later | +
@@ -162,6 +164,7 @@ To ensure the best user experience, best practice is to use the latest version e + - *Android* | Browser or application | Receiving streams | Sending streams | |-----------------|--------------------------|---------------------------------------| @@ -187,3 +190,74 @@ To ensure the best user experience, best practice is to use the latest version e - [Edge](https://microsoft.com/edge) - [Safari](https://support.apple.com/en-hk/HT201541) + + + +### Supported browsers + + + supports the following browsers: + +- *Android* + | Browser or application | Minimum supported version | + |----------------------------------|---------------------------| + | Chrome | 86.0.4240 | + | Firefox (x64, ARM64, IA-32, ARMv7| 83.0 | + +- *iOS*: + | Browser or application | Minimum supported version | + |------------------------|---------------------------| + | Chrome | 86.0.4240 | + | Firefox | 29.0 | + +- *Desktop*: + |Operating system |Browser |Minimum supported version | + |-----------------|--------------|--------------------------| + |Windows |Firefox |83.0 | + |Windows |Chrome |86.0.4240 | + |Windows |Microsoft Edge|87.0.664.60 | + |macOS |Chrome |86.0.4240 | + |macOS |Firefox |83.0 | + |macOS |Safari |13.0 | + |Linux |Firefox |83.0 | + |Linux |Chrome |86.0.4240 | + |OpenBSD |Firefox |83.0 | + +### Dependencies + +When you integrate features into your , has the following + dependencies: + +| Name | Minimum version | License | Dependency | +|---|---|---|---| +| @thi.ng/cache | 1.0.70 | Apache 2.0 | Transitive | +| @types/format-util | 1.0.1 | MIT | Transitive | +| @types/google-closure-compiler | 0.0.18 | MIT | Transitive | +| @types/node-forge | 1.3.1 | BSD 2-Clause | Transitive | +| abortcontroller-polyfill | 1.7.1 | MIT | Transitive | +| console-polyfill | 0.3.0 | MIT | Transitive | +| core-js | 3.9.0 | MIT | Transitive | +| debug | 4.3.4 | MIT | Transitive | +| dotenv | 8.2.0 | BSD 2-Clause | Transitive | +| events | 3.2.0 | MIT | Transitive | +| format-util | 1.0.5 | MIT | Transitive | +| gud | 1.0.0 | MIT | Transitive | +| is-mobile | 3.1.1 | MIT | Transitive | +| is-what | 3.14.1 | MIT | Transitive | +| lodash | 4.17.21 | MIT | Transitive | +| long | 4.0.0 | Apache 2.0 | Transitive | +| lru-cache | 6.0.0 | ISC | Transitive | +| never throw | 5.0.1 | MIT | Transitive | +| node-forge | 1.3.1 | BSD 3-Clause or GPL 2 | Transitive | +| promise-polyfill | 8.2.0 | MIT | Transitive | +| protobufjs | 6.10.2 | MIT | Transitive | +| regenerator-runtime | 0.13.9 | MIT | Transitive | +| rxjs | 6.6.3 | Apache 2.0 | Transitive | +| rxjs-etc | 10.6.0 | MIT | Transitive | +| rxjs-websockets | 8.0.1 | ISC | Transitive | +| safe-json-stringify | 1.2.0 | MIT | Transitive | +| tslib | 2.1.0 | BSD Zero Clause | Transitive | +| uuid | 3.4.0 | MIT | Transitive | +| webcrypto-shim | 0.1.6 | MIT | Transitive | + + \ No newline at end of file diff --git a/shared/common/_token-server-source-request-structure.mdx b/shared/common/_token-server-source-request-structure.mdx new file mode 100644 index 000000000..75221d38c --- /dev/null +++ b/shared/common/_token-server-source-request-structure.mdx @@ -0,0 +1,34 @@ + +#### Source code for a token server + +The token server RESTful web service used in this page is written in Golang using the Gin framework. Want to use the code in your authentication service? [Download](https://github.com/AgoraIO-Community/agora-token-service/releases/tag/v1.1.1) the token server source code and binaries for various platforms from Github. + +To see how to create a token generator inside your IAM system, see [Integrate a token generator](../develop/integrate-token-generation). + +#### Token server GET request structure + +A token server GET request has the following structure: + + ``` html + /rtc/:channelName/:role/:tokentype/:uid/?expiry=expireTime + ``` + +- `:channelName` is the name of the Channel you wish to join + + A channel name may contain numbers with both upper and lower case letters. The name length must be less than 64 characters. + +- `:role` is the user role + + Use `publisher` for publisher, `subscriber` for subscriber. + +- `:tokentype` is the type of token + + supports both integer user IDs and string user accounts for token generation. To ensure smooth communication, all the users in a channel must use the same type of ID, that is, either the integer `uid`, or a string `userAccount`. Best practice is to use the `uid`. + +- `:uid` is the user ID + + User Id can be any 32-bit unsigned integer. It can be set to 0, if you do not need to authenticate the user based on the user ID. + +- `expireTime` (optional) is the number of seconds after which the token will expire + + By default, a token expires after 24 hours unless a shorter life span is explicitly specified in the token request. diff --git a/shared/common/prerequities.mdx b/shared/common/prerequities.mdx index cdbe5d10c..b12c6a24f 100644 --- a/shared/common/prerequities.mdx +++ b/shared/common/prerequities.mdx @@ -1,4 +1,5 @@ To test the code used in this page you need to have: + * Implemented either of the following: - [ quickstart](../get-started/get-started-uikit) @@ -26,9 +27,12 @@ To test the code used in this page you need to have: | [Windows](https://docs.unrealengine.com/4.27/en-US/Basics/InstallingUnrealEngine/RecommendedSpecifications/) | 32-bit Windows only supports Unreal Engine 4 and below. You need to uncomment the Windows 32-bit related code in the file `AgoraPluginLibrary.Build.cs`. | + - A [supported browser](../reference/supported-platforms#browsers). + - Physical media input devices, such as a camera and a microphone. + - A JavaScript package manager such as [npm](https://www.npmjs.com/package/npm). diff --git a/shared/common/project-setup/web.mdx b/shared/common/project-setup/web.mdx index 2a69bf074..8b6968fec 100644 --- a/shared/common/project-setup/web.mdx +++ b/shared/common/project-setup/web.mdx @@ -1,19 +1,24 @@ + 1. **Clone the [ reference app](https://github.com/AgoraIO/video-sdk-samples-js) repository**. Navigate to your `` folder and run the following command: - + ```bash git clone https://github.com/AgoraIO/video-sdk-samples-js.git ``` - - + + +1. **Clone the [ reference app](https://github.com/AgoraIO/signaling-sdk-samples-web) repository**. + + Navigate to your `` folder and run the following command: + ```bash git clone https://github.com/AgoraIO/signaling-sdk-samples-web ``` - + 1. **Install dependencies**: diff --git a/shared/common/project-test/index.mdx b/shared/common/project-test/index.mdx index 70939fe59..b03b6664a 100644 --- a/shared/common/project-test/index.mdx +++ b/shared/common/project-test/index.mdx @@ -11,7 +11,9 @@ import Windows from './windows.mdx'; import CloneProj from './clone-project.mdx' + + diff --git a/shared/common/project-test/web.mdx b/shared/common/project-test/web.mdx index f665e77b0..a021e3e4c 100644 --- a/shared/common/project-test/web.mdx +++ b/shared/common/project-test/web.mdx @@ -1,8 +1,14 @@ - -3. **Set the AppID** - - In `src/agora_manager/config.json`, set `appId` to the [AppID](../reference/manage-agora-account?platform=android#get-the-app-id) of your project. + + +1. **Set the AppID** + + In `src/agora_manager/config.json`, set `appId` to the [AppID](../reference/manage-agora-account#get-the-app-id) of your project. + + + In `/src/signaling_manager/config.json`, set `appId` to the [AppID](../reference/manage-agora-account#get-the-app-id) of your project. + + 1. **Set the authentication method** Choose one of the following authentication methods: @@ -19,13 +25,13 @@ 1. **Run the reference app** - In Terminal, navigate to \, then run the following command: + In Terminal, navigate to ``, then run the following command: ```bash pnpm dev ``` Use the URL displayed in the terminal to open the in your browser. - + diff --git a/shared/flexible-classroom/customize-ui-scene-sdk/android.mdx b/shared/flexible-classroom/customize-ui-scene-sdk/android.mdx new file mode 100644 index 000000000..df69ecd25 --- /dev/null +++ b/shared/flexible-classroom/customize-ui-scene-sdk/android.mdx @@ -0,0 +1,5 @@ + + +Currently not supported for this platform. + + \ No newline at end of file diff --git a/shared/flexible-classroom/customize-ui-scene-sdk/index.mdx b/shared/flexible-classroom/customize-ui-scene-sdk/index.mdx index a99bdd2c9..196e24ea1 100644 --- a/shared/flexible-classroom/customize-ui-scene-sdk/index.mdx +++ b/shared/flexible-classroom/customize-ui-scene-sdk/index.mdx @@ -1,6 +1,10 @@ import Electron from './electron.mdx' import Web from './web.mdx'; +import Android from './android.mdx'; +import Ios from './ios.mdx'; + + diff --git a/shared/flexible-classroom/customize-ui-scene-sdk/ios.mdx b/shared/flexible-classroom/customize-ui-scene-sdk/ios.mdx new file mode 100644 index 000000000..66b6cfb38 --- /dev/null +++ b/shared/flexible-classroom/customize-ui-scene-sdk/ios.mdx @@ -0,0 +1,5 @@ + + +Currently not supported for this platform. + + \ No newline at end of file diff --git a/shared/flexible-classroom/release-notes/js.mdx b/shared/flexible-classroom/release-notes/js.mdx index e47acc337..0100c3e4a 100644 --- a/shared/flexible-classroom/release-notes/js.mdx +++ b/shared/flexible-classroom/release-notes/js.mdx @@ -7,12 +7,12 @@ v2.9.0 was released on November 22, 2023. #### New features -This version adds the following new features: +This version adds the following new scenarios: - Online classroom scenarios and the introduction of a new UI style and interactive experience that are closer to the usage habits of educational users. See the following documentation: - - [Scene SDK](../develop/customize-ui/customize-ui-scene-sdk) - - [API Reference](ui-scene) + - [FcrUIScene SDK](../develop/customize-ui/customize-ui-scene-sdk) + - [API Reference](../reference/ui-scene) One-to-one private chat function. This function does not currently support retrieving historical messages from servers on demand. diff --git a/shared/signaling/authentication-workflow/implementation/android.mdx b/shared/signaling/authentication-workflow/implementation/android.mdx new file mode 100644 index 000000000..70f3149de --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/android.mdx @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/implementation/index.mdx b/shared/signaling/authentication-workflow/implementation/index.mdx new file mode 100644 index 000000000..f25927243 --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/index.mdx @@ -0,0 +1,15 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import ReactNative from './react-native.mdx'; +import Unity from './unity.mdx'; +import Web from './web.mdx'; +import Windows from './windows.mdx'; + +In , each authentication token you create is specific for a user ID in your . You create a token for each user who logs in to . When you initiate the , ensure that the UID is the same one you used to create the token. + + + + + + + diff --git a/shared/signaling/authentication-workflow/implementation/ios.mdx b/shared/signaling/authentication-workflow/implementation/ios.mdx new file mode 100644 index 000000000..b2418ba5a --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/ios.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/release-notes/react-native.mdx b/shared/signaling/authentication-workflow/implementation/react-native.mdx similarity index 60% rename from shared/signaling/release-notes/react-native.mdx rename to shared/signaling/authentication-workflow/implementation/react-native.mdx index dc59b730e..25a8fca94 100644 --- a/shared/signaling/release-notes/react-native.mdx +++ b/shared/signaling/authentication-workflow/implementation/react-native.mdx @@ -1,4 +1,3 @@ - - + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/implementation/unity.mdx b/shared/signaling/authentication-workflow/implementation/unity.mdx new file mode 100644 index 000000000..7a090839d --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/unity.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/implementation/web.mdx b/shared/signaling/authentication-workflow/implementation/web.mdx new file mode 100644 index 000000000..3d70cc0bc --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/web.mdx @@ -0,0 +1,161 @@ + + +In order to make HTTPS calls to a token server and interpret the JSON return parameters, the axios HTTP client is integrated into the reference . + +To retrieve tokens from the token server and use them to authenticate your with using : + +1. **Retrieve an RTM token from the server** + + Use a GET request to retrieve an RTM authentication token for initializing the engine. + + ``` javascript + // Get the config + const config = signalingManager.config; + + // Fetches the Signaling token + async function fetchToken(uid) { + if (config.serverUrl !== "") { + try { + const res = await fetch( + config.proxyUrl + + config.serverUrl + + "/rtm/" + + uid + + "/?expiry=" + + config.tokenExpiryTime, + { + headers: { + "X-Requested-With": "XMLHttpRequest", + }, + } + ); + const data = await res.text(); + const json = await JSON.parse(data); + console.log("RTM token fetched from server: ", json.rtmToken); + return json.rtmToken; + } catch (err) { + console.log(err); + } + } else { + return config.token; // Fallback + } + } + ``` + +1. **Use the token to login into the ** + + Call `fetchToken` to get a fresh RTM token. Use the token in the `RTMConfig` to initiate the . + + ``` javascript + const fetchTokenAndLogin = async (uid) => { + const token = await fetchToken(uid); + signalingManager.login(uid, token); + }; + ``` +1. **Retrieve an RTC token** + + To join a stream channel you retrieve an RTC token from the token server by specifying the `uid` and `channelName`. + + ```javascript + // Fetches an RTC token for stream channels + async function fetchRTCToken(uid, channelName) { + if (config.serverUrl !== "") { + try { + const res = await fetch( + config.proxyUrl + + config.serverUrl + + "/rtc/" + + channelName + + "/" + + role + + "/uid/" + + uid + + "/?expiry=" + + config.tokenExpiryTime, + { + headers: { + "X-Requested-With": "XMLHttpRequest", + }, + } + ); + const data = await res.text(); + const json = await JSON.parse(data); + console.log("RTC token fetched from server: ", json.rtcToken); + return json.rtcToken; + } catch (err) { + console.log(err); + } + } else { + return config.rtcToken; + } + } + ``` + +1. **Use the RTC token to join a stream channel** + + Create a stream channel using the channel name and call `join` with the RTC token. + + ```javascript + const streamChannelJoinAndLeave = async function ( + isStreamChannelJoined, + uid, + streamChannelName + ) { + const token = await fetchRTCToken(uid, streamChannelName); + if (getSignalingStreamChannel() === null) { + streamChannel = await signalingManager + .getSignalingEngine() + .createStreamChannel(streamChannelName); // creates a stream channel + } + + if (isStreamChannelJoined === false) { + await streamChannel + .join({ + token: token, + withPresence: true, + }) + .then((response) => { + console.log(response); + }); + } else { + streamChannel.leave().then((response) => { + console.log(response); + messageCallback("Left the channel: " + streamChannelName); + streamChannel = null; + }); + } + }; + ``` + +1. **Handle the event triggered by when the token is about to expire** + + A token expires after the `tokenExpiryTime` specified in the call to the token server. If the expiry time + is not specified the default timeout is 24 hours. The `TokenPrivilegeWillExpire` event receives a callback when + the current token is about to expire so that a fresh token may be retrieved and used. + + ``` javascript + // When token-privilege-will-expire occurs, fetch a new token from the server and call renewToken to renew the token. + const handleSignalingEvents = (event, eventArgs) => { + switch (event) { + case "TokenPrivilegeWillExpire": + renewToken(uid); + break; + } + } + ``` + +1. **Renew the token** + + You persist the existing session by retrieving a fresh token and calling `renewToken`. + + ``` javascript + const renewToken = async (uid) => { + const token = await fetchToken(uid); + const result = await signalingManager + .getSignalingEngine() + .renewToken(token); + messageCallback("Token was about to expire so it was renewed..."); + }; + ``` + + diff --git a/shared/signaling/authentication-workflow/implementation/windows.mdx b/shared/signaling/authentication-workflow/implementation/windows.mdx new file mode 100644 index 000000000..d936cf6f0 --- /dev/null +++ b/shared/signaling/authentication-workflow/implementation/windows.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/index.mdx b/shared/signaling/authentication-workflow/index.mdx new file mode 100644 index 000000000..b7c219da9 --- /dev/null +++ b/shared/signaling/authentication-workflow/index.mdx @@ -0,0 +1,84 @@ +import Setup from '@docs/shared/common/project-setup/index.mdx'; +import Prerequisites from '@docs/shared/common/prerequities.mdx'; +import CreateRunTokenServer from '@docs/shared/common/_create-run-token-server.mdx'; +import Implement from '@docs/shared/signaling/authentication-workflow/implementation/index.mdx'; +import Test from '@docs/shared/signaling/authentication-workflow/test/index.mdx'; +import Reference from '@docs/shared/signaling/get-started-sdk/reference/index.mdx'; + +Authentication is the act of validating the identity of each user before they access a system. +uses digital tokens to authenticate users and their privileges before they access . Each token is valid +for a limited period and works for a specific UID only. For example, you cannot use a token generated for UID +`john` for UID `doe`. + +This page shows you how to quickly set up an authentication token server, retrieve a token from the server, and use +it to connect securely to as a specific user. You use this server for development +purposes. To see how to develop your own token generator and integrate it into your production IAM system, read +[Token generators](/signaling/develop/integrate-token-generation). + +## Understand the tech + +An authentication token is a dynamic key that is valid for a maximum of 24 hours. On request, a token server returns an authentication token that is valid for a specific user. A token server generates two types of tokens: + +* To initialize the , you use an RTM token. An RTM token is valid only for the user Id that you use to generate it. +* To join a stream channel, you use an RTC token. An RTC token is valid only for the channel name and the user Id that you use to generate it. + +The following figure shows the call flow you need to implement to create step-up-authentication with : + +![token authentication flow](/images/signaling/authentication-workflow.svg) + +To initiate the engine, your retrieves an RTM token from the token server in your security infrastructure. Your then sends this token to for authentication. validates the token and reads the user and project information stored in the token. + +To join a stream channel you request an RTC token from the server by supplying a user Id and a channel name. You do not need an authentication token to subscribe to a message channel. + +A token contains the following information: + +- The [App ID](../reference/manage-agora-account#get-the-app-id) of your project + +- The [App certificate](../reference/manage-agora-account#get-the-app-certificate) of your project + +- The User Id of the user to be authenticated + +- The Unix timestamp showing when the token will expire + +- The channel name (only for RTC tokens) + +When the token is about to expire, sends an event to your and you renew the session with a new token. + +## Prerequisites + +To follow this page, you must have: + +- Implemented the [](../get-started/get-started-sdk) +- Created a cloud platform account that is verified through your GitHub account. The following platforms are +currently supported: + - [Render](https://render.com/) + - [Railway](https://railway.app/) + - [Heroku](https://www.heroku.com/) + +To integrate a token generator directly into your security infrastructure, see [Token generators](/signaling/develop/integrate-token-generation). + +## Implement the authentication workflow + +In the , the uses an authentication token obtained manually to join a channel. In a production environment, your retrieves this token from a token server. This section shows you how to: + +1. [Create and run a token server](#create-and-run-a-token-server) +2. [Retrieve and use tokens from a token server](#authentication-using-the-sdk) + +### Create and run a token server + + + +### Authenticate your session + + + + +## Test authentication + + + +## Reference + +This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this product. + + diff --git a/shared/signaling/authentication-workflow/reference/android.mdx b/shared/signaling/authentication-workflow/reference/android.mdx new file mode 100644 index 000000000..70f3149de --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/android.mdx @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/reference/index.mdx b/shared/signaling/authentication-workflow/reference/index.mdx new file mode 100644 index 000000000..ee99b112a --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/index.mdx @@ -0,0 +1,20 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import ReactNative from './react-native.mdx'; +import Unity from './unity.mdx'; +import Web from './web.mdx'; +import Windows from './windows.mdx'; + +- To ensure communication security in a test or production environment, use a token server to generate token is +recommended to ensure communication security, see [Secure authentication with tokens](../develop/authentication-workflow). + +- [Downloads](../reference/downloads) + +- SDK Integration Methods: + + + + + + + diff --git a/shared/signaling/authentication-workflow/reference/ios.mdx b/shared/signaling/authentication-workflow/reference/ios.mdx new file mode 100644 index 000000000..b2418ba5a --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/ios.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/authentication-workflow/reference/react-native.mdx b/shared/signaling/authentication-workflow/reference/react-native.mdx new file mode 100644 index 000000000..25a8fca94 --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/react-native.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/reference/unity.mdx b/shared/signaling/authentication-workflow/reference/unity.mdx new file mode 100644 index 000000000..7a090839d --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/unity.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/reference/web.mdx b/shared/signaling/authentication-workflow/reference/web.mdx new file mode 100644 index 000000000..ab0d3723c --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/web.mdx @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/reference/windows.mdx b/shared/signaling/authentication-workflow/reference/windows.mdx new file mode 100644 index 000000000..d936cf6f0 --- /dev/null +++ b/shared/signaling/authentication-workflow/reference/windows.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/test/android.mdx b/shared/signaling/authentication-workflow/test/android.mdx new file mode 100644 index 000000000..70f3149de --- /dev/null +++ b/shared/signaling/authentication-workflow/test/android.mdx @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/test/index.mdx b/shared/signaling/authentication-workflow/test/index.mdx new file mode 100644 index 000000000..41d09ec7e --- /dev/null +++ b/shared/signaling/authentication-workflow/test/index.mdx @@ -0,0 +1,15 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import ReactNative from './react-native.mdx'; +import Unity from './unity.mdx'; +import Web from './web.mdx'; +import Windows from './windows.mdx'; + +To test authentication using a token server: + + + + + + + diff --git a/shared/signaling/authentication-workflow/test/ios.mdx b/shared/signaling/authentication-workflow/test/ios.mdx new file mode 100644 index 000000000..b2418ba5a --- /dev/null +++ b/shared/signaling/authentication-workflow/test/ios.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/authentication-workflow/test/react-native.mdx b/shared/signaling/authentication-workflow/test/react-native.mdx new file mode 100644 index 000000000..25a8fca94 --- /dev/null +++ b/shared/signaling/authentication-workflow/test/react-native.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/test/unity.mdx b/shared/signaling/authentication-workflow/test/unity.mdx new file mode 100644 index 000000000..7a090839d --- /dev/null +++ b/shared/signaling/authentication-workflow/test/unity.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/authentication-workflow/test/web.mdx b/shared/signaling/authentication-workflow/test/web.mdx new file mode 100644 index 000000000..e53740d8a --- /dev/null +++ b/shared/signaling/authentication-workflow/test/web.mdx @@ -0,0 +1,34 @@ + + +1. **Configure your project** + + In `/src/signaling_manager/config.json`, Replace: + - `appId` - with the value from . + - `serverUrl` - with the base URL for your token server. For example: `https://agora-token-service-production-yay.up.railway.app`. + + +1. **Run the reference app**: + + In Terminal, navigate to ``, then run the following command: + + ``` bash + pnpm dev + ``` + +1. **Test the authentication server functionality**: + + For each user you want to communicate between: + + 1. Use the URL displayed in Terminal to open the app in your browser. + + 1. Enter a numeric user ID. + + 1. Press **Login**. + + 1. Enter a channel name. + + 1. Press **Join** to join a stream channel. + + 1. Send messages between users. + + diff --git a/shared/signaling/authentication-workflow/test/windows.mdx b/shared/signaling/authentication-workflow/test/windows.mdx new file mode 100644 index 000000000..d936cf6f0 --- /dev/null +++ b/shared/signaling/authentication-workflow/test/windows.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/_cloud-proxy.mdx b/shared/signaling/cloud-proxy/_cloud-proxy.mdx new file mode 100644 index 000000000..c2f918486 --- /dev/null +++ b/shared/signaling/cloud-proxy/_cloud-proxy.mdx @@ -0,0 +1,54 @@ +import * as data from '@site/data/variables'; +import Setup from '@docs/shared/common/project-setup/index.mdx'; +import ProjectImplement from '@docs/shared/signaling/cloud-proxy/project-implementation/index.mdx'; +import ProjectTest from '@docs/shared/signaling/cloud-proxy/project-test/index.mdx'; +import Reference from '@docs/shared/signaling/cloud-proxy/reference/index.mdx'; + +You use to ensure reliable connectivity for your users when they connect from an +environment with a restricted network. + +## Understand the tech + +To accommodate your end users’ firewall settings and business needs, offers a HTTP proxy service. The +following figure shows the workflow: + +![cloud proxy](/images/signaling/cloud-proxy.svg) + +The steps you need to implement in your are: + +1. Before connecting to , set to request a connection to . + +2. When the request succeeds, sends back the proxy information. + +3. sends signaling and media data to , which forwards this data to . + +4. sends signaling and media data to , which forwards it to . + +## Prerequisites + +To follow this page, you must: + +- Setup the [ reference app](/en/signaling/get-started/get-started-sdk#project-setup) + +- Contact support@agora.io and enable for your project. + +- Configure your firewall to allow communication through the [allowed IP address](../reference/cloud-proxy-allowed-ips). + + +## Implement communication using + +This section shows how to use the to implement in your , step-by-step. + + + +## Test + + + + +## Reference + +This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this +product. + + diff --git a/shared/signaling/cloud-proxy/project-implementation/android.mdx b/shared/signaling/cloud-proxy/project-implementation/android.mdx new file mode 100644 index 000000000..e67aac9a2 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/android.mdx @@ -0,0 +1,19 @@ + +1. **Set to connect to before you join a channel** + + To access in a restricted network environment, call `setCloudProxy` and pass `0` as a parameter to select the automatic mode for transmission. The `setCloudProxy` method returns `0` upon + successful initiation of cloud proxy service. + + To enable the service in your , in `/app/java/com.example./MainActivity`, add the following code after `agoraEngine = RtcEngine.create(config);`: + + ``` java + // Start cloud proxy service and set automatic transmission mode. + int proxyStatus = agoraEngine.setCloudProxy(0); + if (proxyStatus == 0) { + showMessage("Proxy service started successfully"); + } else { + showMessage("Proxy service failed with error :" + proxyStatus); + } + ``` + + diff --git a/shared/signaling/cloud-proxy/project-implementation/electron.mdx b/shared/signaling/cloud-proxy/project-implementation/electron.mdx new file mode 100644 index 000000000..7419b6031 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/electron.mdx @@ -0,0 +1,34 @@ + + +1. **Import the required modules** + + In `preload.js`, add the following before `createAgoraRtcEngine,`: + + ``` javascript + CloudProxyType, + ``` + +2. **Enable the connection to ** + + To access in a restricted network environment, call `setCloudProxy` and set the force UDP transmission mode. To implement this logic, in `preload.js`, add the following code after + `agoraEngine.initialize({appId: appID});`: + + ``` javascript + // Start cloud proxy service in the forced UDP mode. + agoraEngine.setCloudProxy(CloudProxyType.UdpProxy); + ``` + +3. **Setup the cloud proxy callback function** + + The triggers `onConnectionStateChanged` callback to indicate the successful initiation of cloud proxy service. To setup this callback, in `preload.js`, add the following code after `const EventHandles = {`: + + ``` javascript + onConnectionStateChanged: (connection, state, reason) => + { + if(reason == 0) + { + console.log("The SDK is connecting to the Agora edge server"); + } + }, + ``` + diff --git a/shared/signaling/cloud-proxy/project-implementation/flutter.mdx b/shared/signaling/cloud-proxy/project-implementation/flutter.mdx new file mode 100644 index 000000000..747fefa9e --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/flutter.mdx @@ -0,0 +1,34 @@ + + +1. **Enable connection to ** + + + To access in a restricted network environment, call `setCloudProxy` and set the transmission mode. To implement this logic, in `setupVoiceSDKEngine`, add the following code after calling `agoraEngine.initialize`: + + + To access in a restricted network environment, call `setCloudProxy` and set the transmission mode. To implement this logic, in `setupVideoSDKEngine`, add the following code after calling `agoraEngine.initialize`: + + + ``` dart + // Start cloud proxy service in forced UDP mode. + await agoraEngine.setCloudProxy(CloudProxyType.udpProxy); + ``` + +1. **Set up the cloud proxy callback** + + + The triggers `onConnectionStateChanged` callback to indicate the successful initiation of cloud proxy service. To set up this callback, in `setupVoiceSDKEngine`, add the following code after `RtcEngineEventHandler(`: + + + The triggers `onConnectionStateChanged` callback to indicate the successful initiation of cloud proxy service. To set up this callback, in `setupVideoSDKEngine`, add the following code after `RtcEngineEventHandler(`: + + + ``` dart + onConnectionStateChanged: (RtcConnection connection, ConnectionStateType state, + ConnectionChangedReasonType reason) { + if (reason == ConnectionChangedReasonType.connectionChangedSettingProxyServer){ + showMessage("Proxy settings changed"); + } + }, + ``` + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-implementation/index.mdx b/shared/signaling/cloud-proxy/project-implementation/index.mdx new file mode 100644 index 000000000..7b1ffffef --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/index.mdx @@ -0,0 +1,20 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import ReactNative from './react-native.mdx'; +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx' +import Unity from './unity.mdx' +import Windows from './windows.mdx'; + + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-implementation/ios.mdx b/shared/signaling/cloud-proxy/project-implementation/ios.mdx new file mode 100644 index 000000000..e10531f95 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/ios.mdx @@ -0,0 +1,8 @@ +import Code from './swift.mdx'; + + + + + + + diff --git a/shared/signaling/cloud-proxy/project-implementation/macos.mdx b/shared/signaling/cloud-proxy/project-implementation/macos.mdx new file mode 100644 index 000000000..11043d017 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/macos.mdx @@ -0,0 +1,8 @@ +import Code from './swift.mdx'; + + + + + + + diff --git a/shared/signaling/cloud-proxy/project-implementation/react-native.mdx b/shared/signaling/cloud-proxy/project-implementation/react-native.mdx new file mode 100644 index 000000000..111b4383d --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/react-native.mdx @@ -0,0 +1,32 @@ + + +1. **Import the required modules** + + In `App.tsx`, add the following import before `createAgoraRtcEngine,`: + + ``` javascript + CloudProxyType, + ``` + +2. **Enable the connection to ** + + To access in a restricted network environment, call `setCloudProxy` and set the force UDP transmission mode. To implement this logic, in `App.tsx`, add the following code after + `agoraEngine.initialize({appId: appID});`: + + ``` javascript + // Start cloud proxy service in the forced UDP mode. + agoraEngine.setCloudProxy(CloudProxyType.UdpProxy); + ``` + +3. **Setup the cloud proxy callback function** + + The triggers `onConnectionStateChanged` callback to indicate the successful initiation of cloud proxy service. To setup this callback, in `App.tsx`, add the following code after `onUserOffline: (_connection, remoteUid) => {`: + + ``` javascript + onConnectionStateChanged(connection, state, reason) { + if (reason === 0) { + console.log('The SDK is connecting to the Agora edge server'); + } + }, + ``` + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-implementation/swift.mdx b/shared/signaling/cloud-proxy/project-implementation/swift.mdx new file mode 100644 index 000000000..0d060ad6d --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/swift.mdx @@ -0,0 +1,15 @@ + +1. **Start the service before you join a channel** + + To access in a restricted network environment, call `setCloudProxy` and select the automatic mode for data transmission. The `setCloudProxy` method returns `0` upon successful initiation of + cloud proxy service. + + To enable the cloud proxy service in your , in `ViewController`, add the following lines after `let option = AgoraRtcChannelMediaOptions()`: + + ```swift + // Start cloud proxy service and select automatic mode for data transmission. + let status = agoraEngine.setCloudProxy(AgoraCloudProxyType.noneProxy) + if (status != 0) { + showMessage(title: "Cloud proxy status", text: "Proxy failed") + } + ``` diff --git a/shared/signaling/cloud-proxy/project-implementation/unity.mdx b/shared/signaling/cloud-proxy/project-implementation/unity.mdx new file mode 100644 index 000000000..a31a4c9e6 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/unity.mdx @@ -0,0 +1,19 @@ + +1. **Set to connect to before you join a channel** + + To access in a restricted network environment, call `SetCloudProxy` and pass `0` as a parameter to select the automatic mode for transmission. The `setCloudProxy` method returns `0` upon + successful initiation of cloud proxy service. + + To enable the service in your , in your script file, locate `Start` and add the following code before `InitEventHandler();`: + + ``` csharp + // Start cloud proxy service and set automatic transmission mode. + int proxyStatus = RtcEngine.SetCloudProxy(0); + if (proxyStatus == 0) { + Debug.Log("Proxy service started successfully"); + } else { + Debug.Log("Proxy service failed with error :" + proxyStatus); + } + ``` + + diff --git a/shared/signaling/cloud-proxy/project-implementation/web.mdx b/shared/signaling/cloud-proxy/project-implementation/web.mdx new file mode 100644 index 000000000..cd3c915c6 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/web.mdx @@ -0,0 +1,15 @@ + + +### Set proxy configuration + + ``` javascript + Set proxy configuration + ``` + +### Apply the configuration to the + + ``` javascript + signalingEngine = new AgoraRTM.RTM(config.appId, config.uid, rtmConfig); + ``` + + diff --git a/shared/signaling/cloud-proxy/project-implementation/windows.mdx b/shared/signaling/cloud-proxy/project-implementation/windows.mdx new file mode 100644 index 000000000..730c1a8a7 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-implementation/windows.mdx @@ -0,0 +1,21 @@ + +1. **Set to connect to before you join a channel** + + To access in a restricted network environment, call `setCloudProxy` and pass `0` as a parameter to select the automatic mode for transmission. The `setCloudProxy` method returns `0` upon + successful initiation of cloud proxy service. + + To enable the service in your , in **Solution Explorer**, open `AgoraImplementationDlg.cpp` file and add the following code in `setupVideoSDKEngine()` after `agoraEngine->setClientRole(CLIENT_ROLE_TYPE::CLIENT_ROLE_BROADCASTER);`: + + ```cpp + // Start cloud proxy service and set automatic transmission mode + int proxyStatus = agoraEngine->setCloudProxy(CLOUD_PROXY_TYPE::NONE_PROXY); + if (proxyStatus == 0) { + AfxMessageBox(L"Proxy service started successfully"); + } else { + CString message; + message.Format(_T("Proxy service failed with error: %d"), proxyStatus); + AfxMessageBox(message); + } + ``` + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-setup/android.mdx b/shared/signaling/cloud-proxy/project-setup/android.mdx new file mode 100644 index 000000000..c56ca9b9b --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/android.mdx @@ -0,0 +1,3 @@ + + + diff --git a/shared/signaling/cloud-proxy/project-setup/electron.mdx b/shared/signaling/cloud-proxy/project-setup/electron.mdx new file mode 100644 index 000000000..826e1e76d --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/electron.mdx @@ -0,0 +1,3 @@ + + + diff --git a/shared/signaling/cloud-proxy/project-setup/flutter.mdx b/shared/signaling/cloud-proxy/project-setup/flutter.mdx new file mode 100644 index 000000000..f2141600a --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/flutter.mdx @@ -0,0 +1,3 @@ + + + diff --git a/shared/signaling/cloud-proxy/project-setup/index.mdx b/shared/signaling/cloud-proxy/project-setup/index.mdx new file mode 100644 index 000000000..59182844a --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/index.mdx @@ -0,0 +1,17 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import ReactNative from './react-native.mdx'; +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx' +import Windows from './windows.mdx'; + + + + + + + + + diff --git a/shared/signaling/cloud-proxy/project-setup/ios.mdx b/shared/signaling/cloud-proxy/project-setup/ios.mdx new file mode 100644 index 000000000..b17cd42dc --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/ios.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/cloud-proxy/project-setup/macos.mdx b/shared/signaling/cloud-proxy/project-setup/macos.mdx new file mode 100644 index 000000000..6a8810f6d --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/macos.mdx @@ -0,0 +1,5 @@ + + + + + diff --git a/shared/signaling/cloud-proxy/project-setup/react-native.mdx b/shared/signaling/cloud-proxy/project-setup/react-native.mdx new file mode 100644 index 000000000..25a8fca94 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/react-native.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-setup/web.mdx b/shared/signaling/cloud-proxy/project-setup/web.mdx new file mode 100644 index 000000000..8f737f379 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-setup/web.mdx @@ -0,0 +1,3 @@ + + + diff --git a/shared/signaling/cloud-proxy/project-setup/windows.mdx b/shared/signaling/cloud-proxy/project-setup/windows.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/shared/signaling/cloud-proxy/project-test/android.mdx b/shared/signaling/cloud-proxy/project-test/android.mdx new file mode 100644 index 000000000..02c772144 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/android.mdx @@ -0,0 +1,23 @@ + + +3. In Android Studio, open `app/java/com.example./MainActivity`, and update `appId`, `channelName` and `token` with the values for your temporary token. + +4. Connect a physical Android device to your development device. + +5. In Android Studio, click **Run app**. A moment later you see the project installed on your device. + + If this is the first time you run the project, grant microphone and camera access to your app. + + +6. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +6. Click **Join** to start a call. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + diff --git a/shared/signaling/cloud-proxy/project-test/electron.mdx b/shared/signaling/cloud-proxy/project-test/electron.mdx new file mode 100644 index 000000000..5ba3fe668 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/electron.mdx @@ -0,0 +1,25 @@ + + +3. In _preload.js_, update `appID`, `channel` and `token` with your values. + +4. Run the app + + Execute the following command in the terminal: + + ```bash + npm start + ``` + You see your app opens a window named **Get started with **. + + +5. To join as a host, select **Host** and click **Join**. + + + + +5. To connect to a channel, click **Join**. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + diff --git a/shared/signaling/cloud-proxy/project-test/flutter.mdx b/shared/signaling/cloud-proxy/project-test/flutter.mdx new file mode 100644 index 000000000..62daa8bba --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/flutter.mdx @@ -0,0 +1,23 @@ + + +3. In your IDE, open `main.dart`, and update `appId`, `channelName` and `token` with the values for your temporary token. + +4. Connect a test device to your development device. + +5. In your IDE, click *Run app* or execute `flutter run lib/main.dart`. A moment later you see the project installed on your device. + + If this is the first time you run the project, grant microphone and camera access to your . + + +6. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local stream is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +6. Click **Join** to start a call. + + + You see your connects to the from a restricted network environment using the cloud proxy service. + + diff --git a/shared/signaling/cloud-proxy/project-test/index.mdx b/shared/signaling/cloud-proxy/project-test/index.mdx new file mode 100644 index 000000000..f030391fe --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/index.mdx @@ -0,0 +1,24 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import ReactNative from './react-native.mdx'; +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx' +import Unity from './unity.mdx' +import Windows from './windows.mdx'; +import Test from '@docs/shared/common/project-test/index.mdx'; + +To test this functionality: + + + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-test/ios.mdx b/shared/signaling/cloud-proxy/project-test/ios.mdx new file mode 100644 index 000000000..f3011d0fa --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/ios.mdx @@ -0,0 +1,24 @@ + + +3. In the `ViewController`, update `appID`, `channelName`, and `token` with the values from . + +4. Run your using either a physical or a simulator iOS device. + + If this is the first time you run the project, grant microphone and camera access to your . + + If you use an iOS simulator, you see the remote video only. You cannot see the local video stream because of Apple simulator hardware restrictions. + + +5. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + + +You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + + diff --git a/shared/signaling/cloud-proxy/project-test/macos.mdx b/shared/signaling/cloud-proxy/project-test/macos.mdx new file mode 100644 index 000000000..268fbc910 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/macos.mdx @@ -0,0 +1,20 @@ + + +3. In the `ViewController`, update `appID`, `channelName`, and `token` with the values from . + +4. Run your . + + +5. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + + +You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + + diff --git a/shared/signaling/cloud-proxy/project-test/react-native.mdx b/shared/signaling/cloud-proxy/project-test/react-native.mdx new file mode 100644 index 000000000..ba94866cc --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/react-native.mdx @@ -0,0 +1,38 @@ + +3. In `App.tsx`, update `appId`, `channelName` and `token` with the values for your temporary token. + +1. Run your app: + + - *Android* + + 1. Enable Developer options on your Android device, and then connect it to your computer using a USB cable. + 1. Run `npx react-native run-android` in the project root directory. + + - *iOS:* + + 1. Open the `ProjectName/ios/ProjectName.xcworkspace` folder with Xcode. + 1. Connect your iOS device to your Mac using a USB cable. + 1. Click the **Build and run** button in Xcode. + + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + +5. Select an option and click **Join** to start a session. + - When you join as a **Host**, the local video is published and played in the . + - When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + +Now, you can see yourself on the device screen and talk to the remote user using your . + + + +5. Click **Join** to start a call. + +Now, you can talk to the remote user using your . + + + diff --git a/shared/signaling/cloud-proxy/project-test/unity.mdx b/shared/signaling/cloud-proxy/project-test/unity.mdx new file mode 100644 index 000000000..1557aa689 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/unity.mdx @@ -0,0 +1,17 @@ + + +3. In your script file, update `_appID`, `_channelName` and `_token` with the values for your temporary token. + +4. In **Unity Editor**, click **Play**. A moment later you see the running on your development device. + + +5. To join as a host, select **Host** and click **Join**. + + + +5. To connect to a channel, click **Join**. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/project-test/web.mdx b/shared/signaling/cloud-proxy/project-test/web.mdx new file mode 100644 index 000000000..5f9791406 --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/web.mdx @@ -0,0 +1,7 @@ + + +4. **Test Cloud Proxy** + + Login to , you send and receive messages through Cloud Proxy. + + diff --git a/shared/signaling/cloud-proxy/project-test/windows.mdx b/shared/signaling/cloud-proxy/project-test/windows.mdx new file mode 100644 index 000000000..22eade59e --- /dev/null +++ b/shared/signaling/cloud-proxy/project-test/windows.mdx @@ -0,0 +1,20 @@ + + 3. In `CAgoraImplementationDlg.h`, update `appId`, `channelName` and `token` with the values for your temporary token. + + 4. In Visual Studio, click **Local Windows Debugger**. A moment later you see the project running on your development device. + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + + 5. Select an option and click **Join** to start a session. + - When you join as a **Host**, the local video is published and played in the . + - When you join as **Audience**, the remote stream is subscribed and played. + + + + 5. Click **Join** to start a call. Now, you can see yourself on the device screen and talk to the remote user using your . + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/reference/android.mdx b/shared/signaling/cloud-proxy/reference/android.mdx new file mode 100644 index 000000000..30bc8406d --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/android.mdx @@ -0,0 +1,12 @@ + + +### API reference + + +* setCloudProxy + + +* setCloudProxy + + + diff --git a/shared/signaling/cloud-proxy/reference/electron.mdx b/shared/signaling/cloud-proxy/reference/electron.mdx new file mode 100644 index 000000000..5afec5a3a --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/electron.mdx @@ -0,0 +1,19 @@ + + +### API reference + + + +- setCloudProxy +- onConnectionStateChanged + + + + +- setCloudProxy +- onConnectionStateChanged + + + + + diff --git a/shared/signaling/cloud-proxy/reference/flutter.mdx b/shared/signaling/cloud-proxy/reference/flutter.mdx new file mode 100644 index 000000000..9e2f904d0 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/flutter.mdx @@ -0,0 +1,17 @@ + + +### API reference + + +* setCloudProxy + +* onConnectionStateChanged + + + +* setCloudProxy + +* onConnectionStateChanged + + + diff --git a/shared/signaling/cloud-proxy/reference/index.mdx b/shared/signaling/cloud-proxy/reference/index.mdx new file mode 100644 index 000000000..7ae892546 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/index.mdx @@ -0,0 +1,19 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import ReactNative from './react-native.mdx'; +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx' +import Unity from './unity.mdx' +import Windows from './windows.mdx'; + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/reference/ios.mdx b/shared/signaling/cloud-proxy/reference/ios.mdx new file mode 100644 index 000000000..103b2e211 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/ios.mdx @@ -0,0 +1,7 @@ + + +#### API reference + +* setCloudProxy + + diff --git a/shared/signaling/cloud-proxy/reference/macos.mdx b/shared/signaling/cloud-proxy/reference/macos.mdx new file mode 100644 index 000000000..93b97ab88 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/macos.mdx @@ -0,0 +1,7 @@ + + +#### API reference + +* setCloudProxy + + diff --git a/shared/signaling/cloud-proxy/reference/react-native.mdx b/shared/signaling/cloud-proxy/reference/react-native.mdx new file mode 100644 index 000000000..ad1b9afeb --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/react-native.mdx @@ -0,0 +1,14 @@ + + +### API reference + + +- setCloudProxy +- onConnectionStateChanged + + +- setCloudProxy +- onConnectionStateChanged + + + \ No newline at end of file diff --git a/shared/signaling/cloud-proxy/reference/unity.mdx b/shared/signaling/cloud-proxy/reference/unity.mdx new file mode 100644 index 000000000..5d55f0d71 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/unity.mdx @@ -0,0 +1,16 @@ +import * as data from '@site/data/variables'; + + +#### API references + + +- SetCloudProxy +- CLOUD_PROXY_TYPE + + + +- SetCloudProxy +- CLOUD_PROXY_TYPE + + + diff --git a/shared/signaling/cloud-proxy/reference/web.mdx b/shared/signaling/cloud-proxy/reference/web.mdx new file mode 100644 index 000000000..eada26adb --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/web.mdx @@ -0,0 +1,5 @@ + + +- [ API reference](/en/signaling/reference/api) +- [RTMConfig.cloudProxy](/en/signaling/reference/api?platform=web#rtmconfig) + diff --git a/shared/signaling/cloud-proxy/reference/windows.mdx b/shared/signaling/cloud-proxy/reference/windows.mdx new file mode 100644 index 000000000..6ab51cd60 --- /dev/null +++ b/shared/signaling/cloud-proxy/reference/windows.mdx @@ -0,0 +1,7 @@ + + +#### API reference + +* setCloudProxy + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/_data_encryption.mdx b/shared/signaling/data-encryption/_data_encryption.mdx new file mode 100644 index 000000000..b9cd07dfd --- /dev/null +++ b/shared/signaling/data-encryption/_data_encryption.mdx @@ -0,0 +1,62 @@ +import * as data from '@site/data/variables'; +import Prerequites from '@docs/shared/common/prerequities.mdx'; +import ProjectSetup from '@docs/shared/signaling/data-encryption/project-setup/index.mdx'; +import ProjectImplement from '@docs/shared/signaling/data-encryption/project-implementation/index.mdx'; +import ProjectTest from '@docs/shared/signaling/data-encryption/project-test/index.mdx'; +import Reference from '@docs/shared/signaling/data-encryption/reference/index.mdx'; + + +Data encryption ensures that only the authorized users in a channel communicate with each other. This ensures that +potential eavesdroppers cannot access sensitive and private information shared in a channel. While not every use +case requires data encryption, provides built-in encryption methods that guarantee data confidentiality +during transmission. + +This page shows you how to integrate built-in data encryption into your using . + +## Understand the tech + +The following figure shows the call flow for the data encryption: + +![Encrypt data ](/images/signaling/data-encryption.svg) + +All users in a channel must use the same encryption configuration to initiate `agoraEngine` and enable encryption before joining a channel. If you don’t have the correct configuration, you cannot decrypt channel content. Best practice is that your authentication system generates a new key and salt regularly. + + provides security for user applications in the following ways: + +- **Transport layer encryption**: for data transmission between your and . +- **Message encryption**: each message is protected with end-to-end AES_256_GCM encryption protection. +- **Token authorization** - time-based access access control strategy. + +To ensure secure communication, your uses the same SSL [key](https://en.wikipedia.org/wiki/Public_key_certificate) and [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) to encrypt and +decrypt data in the channel. You use the key and salt to create an encryption configuration. uses the encryption configuration to encrypt a stream and sends it to remote users. When the remote user receives +the encrypted data stream, the remote decrypts the data stream using the same salt and key. + +If your must be highly secure, or meet security compliance standards like HIPAA or SOC 2 +type 2, use message-level encryption. For a higher levels combine TLS encryption with end-to-end AES encryption. + +## Prerequisites + +To follow this page, you must have: + +- Setup the [ reference app](/en/signaling/get-started/get-started-sdk#project-setup). + +* Installed the latest version of [OpenSSL](https://www.openssl.org/) + + +## Implement data stream encryption + +To implement data encryption, do the following: + + + +## Test data encryption + + + +Communication between your test devices is end-to-end encrypted. This prevents data from being read or secretly modified by anyone other than the true sender and recipient. + +## Reference + +This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this product. + + diff --git a/shared/signaling/data-encryption/project-implementation/android.mdx b/shared/signaling/data-encryption/project-implementation/android.mdx new file mode 100644 index 000000000..06b451121 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/android.mdx @@ -0,0 +1,63 @@ + + +1. **Add the required imports** + + In `/app/java/com.example./MainActivity`, add the following imports after the last import statement: + + ``` java + import io.agora.rtc2.internal.EncryptionConfig; + import java.util.Base64; + ``` + + Base64 requires that you set the `Min SDK Version` property in your project to `26` or higher. + +2. **Add the required variables** + + In `/app/java/com.example./MainActivity`, add the following declarations to `MainActivity` class: + + ``` java + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate them locally. + + // A 32-byte string for encryption. + private String encryptionKey = ""; + // A 32-byte string in Base64 format for encryption. + private String encryptionSaltBase64 = ""; + ``` + +3. **Add the media stream encryption method** + + To enable media stream encryption in your , create an `EncryptionConfig` object and specify a key, salt, and encryption mode. Call `enableEncryption` and pass the `EncryptionConfig` object as a parameter. + + In `/app/java/com.example./MainActivity`, add the following method to `MainActivity` class: + + ``` java + public void enableEncryption() + { + if(encryptionSaltBase64 == null || encryptionKey == null) + return; + // Convert the salt string into bytes + byte[] encryptionSalt = Base64.getDecoder().decode(encryptionSaltBase64); + // An object to specify encryption configuration. + EncryptionConfig config = new EncryptionConfig(); + // Specify an encryption mode. + config.encryptionMode = EncryptionConfig.EncryptionMode.AES_128_GCM2; + // Set secret key and salt. + config.encryptionKey = encryptionKey; + System.arraycopy(encryptionSalt, 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.length); + // Call the method to enable media encryption. + if(agoraEngine.enableEncryption(true, config) == 0) + { + Toast.makeText(getApplicationContext(), "Media encryption enabled", Toast.LENGTH_SHORT).show(); + } + } + ``` + +4. **Start encryption before joining a channel** + + In `/app/java/com.example./MainActivity`, add the following code at the end of `SetupVideoSDKEngine`: + + ``` java + enableEncryption(); + ``` + diff --git a/shared/signaling/data-encryption/project-implementation/electron.mdx b/shared/signaling/data-encryption/project-implementation/electron.mdx new file mode 100644 index 000000000..dd60a9ed2 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/electron.mdx @@ -0,0 +1,52 @@ + + +1. **Add the required variables** + + In `preload.js`, add the following to the declarations: + + ``` javascript + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate locally. + + let encryptionKey = ""; + let encryptionSaltBase64 = ""; + ``` + +2. **Import the required modules** + + In `preload.js`, add the following before `createAgoraRtcEngine,`: + + ```javascript + EncryptionMode, + ``` + +3. **Call the channel encryption method to enable channel encryption** + + To enable channel encryption in your , you need to: + + 1. Convert the salt you generated using the OpenSSL command to a byte array. + + 1. Create an object of `EncryptionConfig` class and specify a configuration for the channel encryption. In the configuration, you specify `encryptionMode`, `encryptionKey`, and `encryptionKdfSalt`. + + 2. Call `enableEncryption` and pass `true` and the `EncryptionConfig` object as parameters to enable media encryption. + + To implement this logic, in `preload.js`, add the following code after `agoraEngine.initialize({appId: appID});` + + ``` javascript + const buffer = Buffer.from(encryptionSaltBase64, 'base64'); + var salt = Array(buffer.length); + for (var i = 0; i < buffer.length; i++) + { + salt[i] = buffer[i]; + } + let encryptionConfig = + { + encryptionKdfSalt: salt, + encryptionKey: encryptionKey, + encryptionMode: EncryptionMode.Aes128Gcm2 + } + // Start the channel encryption + agoraEngine.enableEncryption(true,encryptionConfig); + ``` + recommends using `Aes128Gcm2` or `Aes256Gcm2` encrypted mode. These two modes support the use of salt for higher security. + diff --git a/shared/signaling/data-encryption/project-implementation/flutter.mdx b/shared/signaling/data-encryption/project-implementation/flutter.mdx new file mode 100644 index 000000000..1c0d7bc62 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/flutter.mdx @@ -0,0 +1,62 @@ + + +1. **Add the required libraries** + + In `/lib/main.dart`, add the following lines after the last import statement: + + ``` dart + import 'dart:convert'; + import 'dart:typed_data'; + ``` + +1. **Declare the required variables** + + In a production environment, you retrieve the encryption key and salt from an authentication server. For this simple example, you generate them locally using `OpenSSL` and insert in your code. In `/lib/main.dart`, add the following declarations to the `_MyAppState` class: + + ``` dart + // A 32-byte string for encryption. + String encryptionKey = ""; + // A 32-byte string in Base64 format for encryption. + String encryptionSaltBase64 = ""; + ``` + +1. **Add the media stream encryption method** + + To enable media stream encryption in your , you create an `EncryptionConfig` object using an encryption key, salt, and encryption mode. You pass this configuration object as a parameter to the `enableEncryption` method. + + In `/lib/main.dart`, add the following method to the `_MyAppState` class: + + ``` dart + void enableEncryption() { + if (encryptionSaltBase64.isEmpty || encryptionKey.isEmpty) { + showMessage("Please set encryption key and salt"); + return; + } + + // Convert the salt string into the required format + Uint8List bytes = base64Decode(encryptionSaltBase64); + + // An object to specify encryption configuration. + EncryptionConfig config = EncryptionConfig( + encryptionMode: EncryptionMode.aes128Gcm2, + encryptionKey: encryptionKey, + encryptionKdfSalt: bytes + ); + + // Enable media encryption using the configuration + agoraEngine.enableEncryption( + enabled: true, config: config); + + showMessage("Media encryption enabled"); + } + ``` + +1. **Start encryption before joining a channel** + + In the `join()` method, add the following line before `agoraEngine.joinChannel`: + + ``` dart + enableEncryption(); + ``` + + diff --git a/shared/signaling/data-encryption/project-implementation/index.mdx b/shared/signaling/data-encryption/project-implementation/index.mdx new file mode 100644 index 000000000..9e8c5a5cf --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/index.mdx @@ -0,0 +1,19 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import Electron from './electron.mdx'; +import Unity from './unity.mdx'; +import Flutter from './flutter.mdx'; +import ReactNative from './react-native.mdx'; +import MacOS from './macos.mdx'; +import Windows from './windows.mdx'; + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-implementation/ios.mdx b/shared/signaling/data-encryption/project-implementation/ios.mdx new file mode 100644 index 000000000..170d386ef --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/ios.mdx @@ -0,0 +1,8 @@ +import Source from './swift.mdx'; + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-implementation/macos.mdx b/shared/signaling/data-encryption/project-implementation/macos.mdx new file mode 100644 index 000000000..74e608cdd --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/macos.mdx @@ -0,0 +1,8 @@ +import Source from './swift.mdx'; + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-implementation/react-native.mdx b/shared/signaling/data-encryption/project-implementation/react-native.mdx new file mode 100644 index 000000000..e2f8372f5 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/react-native.mdx @@ -0,0 +1,40 @@ + +1. **Add the required variables** + + In `App.tsx`, add the following to the declarations: + + ```typescript + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate locally. + const encryptionKey = ''; + const encryptionSaltBase64 = ''; + ``` + +2. **Import the required modules** + + In `App.tsx`, add the following import in `import {} from 'react-native-agora-rtc-ng';`: + + ```typescript + EncryptionMode, + ``` + +3. **Call the channel encryption method to enable channel encryption** + + To enable channel encryption in your , you need to: + + 1. Create an `EncryptionConfig` instance and specify a configuration for the channel encryption. In the configuration, you specify `encryptionMode`, `encryptionKey`, and `encryptionKdfSalt`. `encryptionKdfSalt` is required for `Aes128Gcm2` and `Aes256Gcm2` modes, it is optional for other encryption modes. + + 2. To enable media encryption, call `enableEncryption` with your `EncryptionConfig` instance. + + To implement this logic, in `App.tsx`, add the following code after `agoraEngine.initialize({appId: appID});` + + ```typescript + let encryptionConfig = { + encryptionBase64: encryptionBase64, + encryptionKey: encryptionKey, + encryptionMode: EncryptionMode.Aes128Ecb, + }; + engine.enableEncryption(true, encryptionConfig); + ``` + Best practice is to use Aes128Gcm2 or Aes256Gcm2. These modes use salt for higher security. + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-implementation/swift.mdx b/shared/signaling/data-encryption/project-implementation/swift.mdx new file mode 100644 index 000000000..13b4e9d04 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/swift.mdx @@ -0,0 +1,49 @@ + +1. **Add the required variables** + + Add the following declarations to the top of the `ViewController` class: + + ``` swift + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate locally. + + // A 32-byte string for encryption. + var encryptionKey = "" + // A 32-byte string in Base64 format for encryption. + var encryptionSaltBase64 = "" + ``` + +2. **Add the media stream encryption method** + + To enable media stream encryption in your , create an `AgoraEncryptionConfig` object and specify a key, salt, and encryption mode. Call `enableEncryption` and pass the `EncryptionConfig` object as a parameter. + + In `ViewController` class, add the following function: + + ``` swift + func enableEncryption() { + // Convert the salt string in the Base64 format into bytes + let encryptionSalt: Data = Data(base64Encoded: encryptionSaltBase64, options: .ignoreUnknownCharacters)! + + // An object to specify encryption configuration. + let config = AgoraEncryptionConfig() + + // Specify an encryption mode. + config.encryptionMode = AgoraEncryptionMode.AES128GCM2 + // Set secret key and salt. + config.encryptionKey = encryptionKey + config.encryptionKdfSalt = encryptionSalt + + // Call the method to enable media encryption. + if (agoraEngine.enableEncryption(true, encryptionConfig: config) == 0) { + print("Media encryption enabled.") + } + } + ``` + +3. **Start encryption before joining a channel** + + Add the following line to the end of `initializeAgoraEngine` function: + + ``` swift + enableEncryption() + ``` diff --git a/shared/signaling/data-encryption/project-implementation/unity.mdx b/shared/signaling/data-encryption/project-implementation/unity.mdx new file mode 100644 index 000000000..655109e48 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/unity.mdx @@ -0,0 +1,57 @@ + + +1. **Add the required imports** + + In your script file, add the following to after `using UnityEngine;`: + + ``` csharp + using System; + ``` + +2. **Add the required variables** + + In your script file, add the following to declarations: + + ``` csharp + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate them locally. + + string secretKey = ""; + string salt = ""; + ``` + +3. **Add the media stream encryption method** + + To enable media stream encryption in your , create an `EncryptionConfig` instance and specify a key, salt, and encryption mode. Call `EnableEncryption` and pass the instance of `EncryptionConfig` as a parameter. + + In your dcript file, add the following method before `SetupVideoSDKEngine`: + + ``` csharp + void enableEncryption() + { + if (RtcEngine != null) + { + // Create an encryption configuration. + var config = new EncryptionConfig + { + // Specify a encyption mode + encryptionMode = ENCRYPTION_MODE.AES_128_GCM2, + // Assign a secret key. + encryptionKey = secretKey, + // Assign a salt in Base64 format + encryptionKdfSalt = Convert.FromBase64String(salt) + }; + // Enable the built-in encryption. + RtcEngine.EnableEncryption(true, config); + } + } + ``` + +4. **Start encryption before joining a channel** + + In your script file, add the following code at the end of `SetupVideoSDKEngine`: + + ``` csharp + enableEncryption(); + ``` + diff --git a/shared/signaling/data-encryption/project-implementation/web.mdx b/shared/signaling/data-encryption/project-implementation/web.mdx new file mode 100644 index 000000000..c3acd6ef3 --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/web.mdx @@ -0,0 +1,70 @@ + + +### Set encryption configuration​ + +1. **Add the required variables** + + These variables hold the encrypted values of the salt and cypher key in your configuration. + + ``` javascript + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate locally. + + var encryptionKey = ""; + var encryptionSaltBase64 = ""; + var encryptionMode = ""; + ``` + +2. **Add a method to convert a string from `Base64` to `Uint8Array`** + + + ``` javascript + function base64ToUint8Array(base64Str) { + const raw = window.atob(base64Str); + const result = new Uint8Array(new ArrayBuffer(raw.length)); + for (let i = 0; i < raw.length; i += 1) { + result[i] = raw.charCodeAt(i); + } + return result; + } + ``` + +3. **Add a method to convert a string from `Hex` to `ASCII`** + + ``` javascript + function hex2ascii(hexx) + { + const hex = hexx.toString();//force conversion + let str = ''; + for (let i = 0; i < hex.length; i += 2) + str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); + return str; + } + ``` + +4. **Create the configuration object** + + ``` javascript + // Convert the encryptionSaltBase64 string to base64ToUint8Array. + encryptionSaltBase64 = base64ToUint8Array(config.salt); + // Convert the encryptionKey string to hex2ascii. + encryptionKey = hex2ascii(config.cipherKey); + // Set an encryption mode. + encryptionMode = config.encryptionMode; + // Start channel encryption + const rtmConfig = { + logLevel: config.logLevel, + useStringUserId: config.useStringUserId, + encryptionMode: config.encryptionMode, + salt: encryptionSaltBase64, + cipherKey: encryptionKey, + }; + ``` + +### Apply the configuration to the + + ``` javascript + signalingEngine = new AgoraRTM.RTM(config.appId, config.uid, rtmConfig); + ``` + + diff --git a/shared/signaling/data-encryption/project-implementation/windows.mdx b/shared/signaling/data-encryption/project-implementation/windows.mdx new file mode 100644 index 000000000..51f9e3c8d --- /dev/null +++ b/shared/signaling/data-encryption/project-implementation/windows.mdx @@ -0,0 +1,58 @@ + + +1. **Add the required variables** + + In `AgoraImplementationDlg.h`, add the following declarations to `CAgoraImplementationDlg`: + + ```cpp + // In a production environment, you retrieve the key and salt from + // an authentication server. For this code example you generate them locally. + + // A 32-byte string for encryption. + std::string encryptionKey = ""; + // A 32-byte string in Base64 format for encryption. + std::string encryptionSaltBase64 = ""; + ``` + +3. **Add the media stream encryption method** + + To enable media stream encryption in your , create an `EncryptionConfig` object and specify a key, salt, and encryption mode. Call `enableEncryption` and pass the `EncryptionConfig` object as a parameter. To implement this logic, take the following steps: + + 1. In `AgoraImplementationDlg.cpp`, add the following method before `OnInitDialog`: + + ```cpp + void CAgoraImplementationDlg::enableEncryption() + { + if (encryptionSaltBase64 == "" || encryptionKey == "") + return; + //set encrypt mode and encrypt secret + EncryptionConfig config; + config.encryptionMode = AES_256_GCM2; + config.encryptionKey = encryptionKey.c_str(); + memcpy(config.encryptionKdfSalt, encryptionSaltBase64.c_str(), 32); + // Call the method to enable media encryption. + if (agoraEngine->enableEncryption(true, config) == 0) + { + AfxMessageBox(L"Encryption Enabled"); + } + } + ``` + + 2. In `AgoraImplementationDlg.h`, add the following method declaration to `CAgoraImplementationDlg`: + + ```cpp + void enableEncryption(); + ``` + +4. **Start media encryption before joining a channel** + + In `AgoraImplementationDlg.cpp`, add the following code at the end of `SetupVoiceSDKEngine`: + + + + In `AgoraImplementationDlg.cpp`, add the following code at the end of `SetupVideoSDKEngine`: + + ``` cpp + enableEncryption(); + ``` + diff --git a/shared/signaling/data-encryption/project-setup/android.mdx b/shared/signaling/data-encryption/project-setup/android.mdx new file mode 100644 index 000000000..66dac7397 --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/android.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/shared/signaling/release-notes/electron.mdx b/shared/signaling/data-encryption/project-setup/electron.mdx similarity index 98% rename from shared/signaling/release-notes/electron.mdx rename to shared/signaling/data-encryption/project-setup/electron.mdx index 43851d807..d1cb5e40f 100644 --- a/shared/signaling/release-notes/electron.mdx +++ b/shared/signaling/data-encryption/project-setup/electron.mdx @@ -1,4 +1,3 @@ - diff --git a/shared/signaling/release-notes/flutter.mdx b/shared/signaling/data-encryption/project-setup/flutter.mdx similarity index 100% rename from shared/signaling/release-notes/flutter.mdx rename to shared/signaling/data-encryption/project-setup/flutter.mdx diff --git a/shared/signaling/data-encryption/project-setup/index.mdx b/shared/signaling/data-encryption/project-setup/index.mdx new file mode 100644 index 000000000..acab29c6d --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/index.mdx @@ -0,0 +1,17 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import Unity from './unity.mdx'; +import ReactNative from './react-native.mdx' +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx'; + + + + + + + + + diff --git a/shared/signaling/data-encryption/project-setup/ios.mdx b/shared/signaling/data-encryption/project-setup/ios.mdx new file mode 100644 index 000000000..53b70930e --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/ios.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/data-encryption/project-setup/macos.mdx b/shared/signaling/data-encryption/project-setup/macos.mdx new file mode 100644 index 000000000..01184fd38 --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/macos.mdx @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-setup/react-native.mdx b/shared/signaling/data-encryption/project-setup/react-native.mdx new file mode 100644 index 000000000..25a8fca94 --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/react-native.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-setup/unity.mdx b/shared/signaling/data-encryption/project-setup/unity.mdx new file mode 100644 index 000000000..daf235c54 --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/unity.mdx @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-setup/web.mdx b/shared/signaling/data-encryption/project-setup/web.mdx new file mode 100644 index 000000000..44170f8d8 --- /dev/null +++ b/shared/signaling/data-encryption/project-setup/web.mdx @@ -0,0 +1,3 @@ + + + diff --git a/shared/signaling/data-encryption/project-test/android.mdx b/shared/signaling/data-encryption/project-test/android.mdx new file mode 100644 index 000000000..f158e5de4 --- /dev/null +++ b/shared/signaling/data-encryption/project-test/android.mdx @@ -0,0 +1,24 @@ + + +4. In Android Studio, in `app/java/com.example.\/MainActivity`, update `appId`, `channelName` and `token` with the values for your temporary token. + +5. Connect a physical Android device to your development machine. + +6. In Android Studio, click **Run app**. You see the running on your device. + + If this is the first time you run your , grant microphone and camera access. + +7. Copy and install the `apk` for your on a second Android test device. + + +8. Select **Broadcaster** mode on the test device and **Audience** on the development device. + +9. Press **Join** on both Android devices to join the same channel. + + + +8. Press **Join** on both Android devices to join the same channel. + + + You see the local and remote videos on the two devices. + diff --git a/shared/signaling/data-encryption/project-test/electron.mdx b/shared/signaling/data-encryption/project-test/electron.mdx new file mode 100644 index 000000000..3782a951f --- /dev/null +++ b/shared/signaling/data-encryption/project-test/electron.mdx @@ -0,0 +1,28 @@ + + +4. In *main.js*, update `appID`, `channel` and `token` with your values. + +5. Start the dev server + + Execute the following command in the terminal: + + ``` bash + npm start + ``` + + You see your app opens a window named **Get started with **. + + +6. Select a user role using the radio buttons and click **Join**. + + + + +6. To connect to a channel, click **Join**. + + + +7. Open another instance of your on a test device and update `appID`, `channel` and `token` with your values, then click **Join**. + + You see the local and remote videos on the two devices. + diff --git a/shared/signaling/data-encryption/project-test/flutter.mdx b/shared/signaling/data-encryption/project-test/flutter.mdx new file mode 100644 index 000000000..7f52de18c --- /dev/null +++ b/shared/signaling/data-encryption/project-test/flutter.mdx @@ -0,0 +1,27 @@ + + +4. In `/lib/main.dart`, update `appId`, `channelName` and `token` with the values for your temporary token. + +5. Connect a test device to your development machine. + +6. In your IDE, click **Run app** or execute `flutter run`. You see the running on your device. + + If this is the first time you run your , grant microphone and camera access. + +7. Copy and install the package for your on a second test device. + + +8. Select **Host** mode on one test device and **Audience** on the other. + +9. Press **Join** on both devices to join the same channel. + + You see local and remote videos on the two devices. + + + +8. Press **Join** on both Android devices to join the same channel. + + You see local and remote videos on the two devices. + + + diff --git a/shared/signaling/data-encryption/project-test/index.mdx b/shared/signaling/data-encryption/project-test/index.mdx new file mode 100644 index 000000000..334e2ed32 --- /dev/null +++ b/shared/signaling/data-encryption/project-test/index.mdx @@ -0,0 +1,52 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import Electron from './electron.mdx'; +import Unity from './unity.mdx'; +import Flutter from './flutter.mdx'; +import ReactNative from './react-native.mdx' +import MacOS from './macos.mdx'; +import Windows from './windows.mdx'; +import Test from '@docs/shared/common/project-test/index.mdx'; + +To test this functionality: + + +1. **Create the cypher key and salt** + + 1. Create the 32-byte key with the following command: + + ``` bash + openssl rand -hex 32 + ``` + + 2. Create the 64-byte salt with the following command + + ``` bash + openssl rand -base64 32 + ``` +1. **Configure data encryption** + + In `/src/signaling_manager/config.json`: + + 1. Paste the `-hex 32 key` into the `cipherKey` variable. + + 1. Paste the salt from the `-base64 32` call into the `salt` variable. + + 1. Set `encryptionMode` to 1. + + + + +4. **Test data encryption** + + Login to as multiple users, then send and receive secure messages. + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-test/ios.mdx b/shared/signaling/data-encryption/project-test/ios.mdx new file mode 100644 index 000000000..170d386ef --- /dev/null +++ b/shared/signaling/data-encryption/project-test/ios.mdx @@ -0,0 +1,8 @@ +import Source from './swift.mdx'; + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-test/macos.mdx b/shared/signaling/data-encryption/project-test/macos.mdx new file mode 100644 index 000000000..74e608cdd --- /dev/null +++ b/shared/signaling/data-encryption/project-test/macos.mdx @@ -0,0 +1,8 @@ +import Source from './swift.mdx'; + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-test/react-native.mdx b/shared/signaling/data-encryption/project-test/react-native.mdx new file mode 100644 index 000000000..306c0460a --- /dev/null +++ b/shared/signaling/data-encryption/project-test/react-native.mdx @@ -0,0 +1,12 @@ + +4. In *App.tsx*, update `appId`, `channelName` and `token` with your values. + +- *Android* + + 1. Enable the Developer options on your Android device, and then connect it. + 1. Run npx react-native run-android in the project root directory. + +- *iOS:* + + 1. In Xcode, run your project. + \ No newline at end of file diff --git a/shared/signaling/data-encryption/project-test/swift.mdx b/shared/signaling/data-encryption/project-test/swift.mdx new file mode 100644 index 000000000..72f9cd6e4 --- /dev/null +++ b/shared/signaling/data-encryption/project-test/swift.mdx @@ -0,0 +1,17 @@ + +4. In Xcode, in `ViewController`, update `appID`, `channelName` and `token` with the values for your temporary token. + +5. Run your , then wait a few seconds until the installation is complete. + + If this is the first time you run the project, grant microphone and camera access to your . + + If you use an iOS simulator, you see the remote video only. You cannot see the local video stream because of [Apple simulator hardware restrictions](https://help.apple.com/simulator/mac/current/#/devb0244142d). + + +6. Select an option and click **Join** to start a session. When you join as a **Host**, the local video is published and played in the . When you join as **Audience**, the remote stream is subscribed and played. + + + +6. Click **Join** to start a call. Now, you can see yourself on the test device and talk to the web demo app using your . + + diff --git a/shared/signaling/data-encryption/project-test/unity.mdx b/shared/signaling/data-encryption/project-test/unity.mdx new file mode 100644 index 000000000..1ee6053ea --- /dev/null +++ b/shared/signaling/data-encryption/project-test/unity.mdx @@ -0,0 +1,24 @@ + + +4. In your script file, update `_appID`, `_channelName` and `_token` with the values for your temporary token. + +5. In Unity Editor, build the project and then install the on a test device. + +6. Run the on the test device. + +7. In Unity Editor, click **Play**. You see the running on your development device. + + If this is the first time you run your , grant microphone and camera access. + + +8. Select **Broadcaster** mode on the test device and **Audience** on the development device. + +9. Press **Join** on both devices to join the same channel. + + + +8. Press **Join** on both devices to join the same channel. + + + You see the local and remote videos on the two devices. + diff --git a/shared/signaling/data-encryption/project-test/web.mdx b/shared/signaling/data-encryption/project-test/web.mdx new file mode 100644 index 000000000..cdd010fd9 --- /dev/null +++ b/shared/signaling/data-encryption/project-test/web.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/data-encryption/project-test/windows.mdx b/shared/signaling/data-encryption/project-test/windows.mdx new file mode 100644 index 000000000..41e5f0a78 --- /dev/null +++ b/shared/signaling/data-encryption/project-test/windows.mdx @@ -0,0 +1,36 @@ + + +4. In `AgoraImplementationDlg.h`, update `appId`, `channelName` and `token` with the values for your temporary token. + +5. In Visual Studio, click **Local Window Debugger**. A moment later you see the project running on your development device. + + +6. Select an option and click **Join** to start a session. + - When you join as a **Host**, the local video is published and played in the . + - When you join as **Audience**, the remote stream is subscribed and played. + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + + + + +6. Click **Join** to start . + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + + + + +6. Click **Join** to start . + + If this is the first time you run the project, you need to grant microphone access to your . + + + + +7. Open another instance of your on a test device and update `appId`, `channelName` and `token` with your values, then click **Join**. + + + diff --git a/shared/signaling/data-encryption/reference/android.mdx b/shared/signaling/data-encryption/reference/android.mdx new file mode 100644 index 000000000..45599d9e4 --- /dev/null +++ b/shared/signaling/data-encryption/reference/android.mdx @@ -0,0 +1,16 @@ + + +### API reference + + +- enableEncryption +- EncryptionConfig + + + +- enableEncryption +- EncryptionConfig + + + + diff --git a/shared/signaling/data-encryption/reference/electron.mdx b/shared/signaling/data-encryption/reference/electron.mdx new file mode 100644 index 000000000..2740919ae --- /dev/null +++ b/shared/signaling/data-encryption/reference/electron.mdx @@ -0,0 +1,19 @@ +import * as data from '@site/data/variables'; + + + + +### API reference + + + +- enableEncryption +- EncryptionConfig + + + +- enableEncryption +- EncryptionConfig + + + diff --git a/shared/signaling/data-encryption/reference/flutter.mdx b/shared/signaling/data-encryption/reference/flutter.mdx new file mode 100644 index 000000000..03f91d766 --- /dev/null +++ b/shared/signaling/data-encryption/reference/flutter.mdx @@ -0,0 +1,16 @@ + + +### API reference + +* enableEncryption + +* EncryptionConfig + + + +* enableEncryption + +* EncryptionConfig + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/reference/index.mdx b/shared/signaling/data-encryption/reference/index.mdx new file mode 100644 index 000000000..0be29d57a --- /dev/null +++ b/shared/signaling/data-encryption/reference/index.mdx @@ -0,0 +1,20 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import Electron from './electron.mdx'; +import Unity from './unity.mdx'; +import Flutter from './flutter.mdx'; +import ReactNative from './react-native.mdx'; +import MacOS from './macos.mdx'; +import Windows from './windows.mdx'; + + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/reference/ios.mdx b/shared/signaling/data-encryption/reference/ios.mdx new file mode 100644 index 000000000..bf4e083ee --- /dev/null +++ b/shared/signaling/data-encryption/reference/ios.mdx @@ -0,0 +1,8 @@ + + +### API reference + +- enableEncryption +- EncryptionConfig + + diff --git a/shared/signaling/data-encryption/reference/macos.mdx b/shared/signaling/data-encryption/reference/macos.mdx new file mode 100644 index 000000000..c9b3b3957 --- /dev/null +++ b/shared/signaling/data-encryption/reference/macos.mdx @@ -0,0 +1,8 @@ + + +### API reference + +- enableEncryption +- EncryptionConfig + + diff --git a/shared/signaling/data-encryption/reference/react-native.mdx b/shared/signaling/data-encryption/reference/react-native.mdx new file mode 100644 index 000000000..bf7551f12 --- /dev/null +++ b/shared/signaling/data-encryption/reference/react-native.mdx @@ -0,0 +1,14 @@ + +### API reference + + +- enableEncryption +- EncryptionConfig + + + +- enableEncryption +- EncryptionConfig + + + \ No newline at end of file diff --git a/shared/signaling/data-encryption/reference/unity.mdx b/shared/signaling/data-encryption/reference/unity.mdx new file mode 100644 index 000000000..e7a4d1fba --- /dev/null +++ b/shared/signaling/data-encryption/reference/unity.mdx @@ -0,0 +1,7 @@ + + + ### API reference + + - EnableEncryption + - EncryptionConfig + \ No newline at end of file diff --git a/shared/signaling/data-encryption/reference/web.mdx b/shared/signaling/data-encryption/reference/web.mdx new file mode 100644 index 000000000..42f78007d --- /dev/null +++ b/shared/signaling/data-encryption/reference/web.mdx @@ -0,0 +1,5 @@ + + +- [ API reference](/en/signaling/reference/api) + + diff --git a/shared/signaling/data-encryption/reference/windows.mdx b/shared/signaling/data-encryption/reference/windows.mdx new file mode 100644 index 000000000..c8f885bd0 --- /dev/null +++ b/shared/signaling/data-encryption/reference/windows.mdx @@ -0,0 +1,16 @@ + + +### API reference + + +- enableEncryption +- EncryptionConfig + + + +- enableEncryption +- EncryptionConfig + + + + diff --git a/shared/signaling/geofencing/index.mdx b/shared/signaling/geofencing/index.mdx new file mode 100644 index 000000000..8f707a781 --- /dev/null +++ b/shared/signaling/geofencing/index.mdx @@ -0,0 +1,55 @@ +import Code from '@docs/shared/signaling/geofencing/sample-code/index.mdx'; +import ProjectTest from '@docs/shared/signaling/geofencing/project-test/index.mdx'; +import Reference from '@docs/shared/signaling/geofencing/reference/index.mdx'; + + +export const toc = [{}]; + + +When a user joins a channel, automatically connects them to the closest geographical region of . However, to meet the laws and regulations of your region, you may want to filter in or filter out connections to a specific geographical region. geofencing enables you to control and customize data routing in your by specifying the region users connect to. + +## Understand the tech + +This section shows you how to enable geofencing in your . The following figure shows the workflow you implement for geofencing: + +![Network Geofencing](/images/common/geofencing.png) + +## Prerequisites + +In order to follow this procedure you must have: + +- Implemented the [](../get-started/get-started-sdk) project for . + + +## Implement geofencing in your + +This section shows how to use the to implement geofencing in your . + +### Set the geofencing configuration + +Call `AgoraRTM.setArea` to specify the region to connect to. After specifying the region, connects +to the Agora servers within that region. + + + +The following regions are supported: + +- `GLOBAL`: (Default) Global. +- `CHINA`: Mainland China. +- `ASIA`: Asia excluding mainland China. +- `EUROPE`: Europe. +- `INDIA`: India. +- `JAPAN`: Japan. +- `NORTH_AMERICA`: North America. + +The following code shows you how to set the geolocation: + +## Test geofencing + + + +## Reference + +This section contains information that completes the information in this page, or points you to documentation that explains other aspects to this product. + + diff --git a/shared/signaling/geofencing/project-test/android.mdx b/shared/signaling/geofencing/project-test/android.mdx new file mode 100644 index 000000000..02c772144 --- /dev/null +++ b/shared/signaling/geofencing/project-test/android.mdx @@ -0,0 +1,23 @@ + + +3. In Android Studio, open `app/java/com.example./MainActivity`, and update `appId`, `channelName` and `token` with the values for your temporary token. + +4. Connect a physical Android device to your development device. + +5. In Android Studio, click **Run app**. A moment later you see the project installed on your device. + + If this is the first time you run the project, grant microphone and camera access to your app. + + +6. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +6. Click **Join** to start a call. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + diff --git a/shared/signaling/geofencing/project-test/electron.mdx b/shared/signaling/geofencing/project-test/electron.mdx new file mode 100644 index 000000000..5ba3fe668 --- /dev/null +++ b/shared/signaling/geofencing/project-test/electron.mdx @@ -0,0 +1,25 @@ + + +3. In _preload.js_, update `appID`, `channel` and `token` with your values. + +4. Run the app + + Execute the following command in the terminal: + + ```bash + npm start + ``` + You see your app opens a window named **Get started with **. + + +5. To join as a host, select **Host** and click **Join**. + + + + +5. To connect to a channel, click **Join**. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + diff --git a/shared/signaling/geofencing/project-test/flutter.mdx b/shared/signaling/geofencing/project-test/flutter.mdx new file mode 100644 index 000000000..62daa8bba --- /dev/null +++ b/shared/signaling/geofencing/project-test/flutter.mdx @@ -0,0 +1,23 @@ + + +3. In your IDE, open `main.dart`, and update `appId`, `channelName` and `token` with the values for your temporary token. + +4. Connect a test device to your development device. + +5. In your IDE, click *Run app* or execute `flutter run lib/main.dart`. A moment later you see the project installed on your device. + + If this is the first time you run the project, grant microphone and camera access to your . + + +6. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local stream is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +6. Click **Join** to start a call. + + + You see your connects to the from a restricted network environment using the cloud proxy service. + + diff --git a/shared/signaling/geofencing/project-test/index.mdx b/shared/signaling/geofencing/project-test/index.mdx new file mode 100644 index 000000000..c6e08dc30 --- /dev/null +++ b/shared/signaling/geofencing/project-test/index.mdx @@ -0,0 +1,28 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Web from './web.mdx'; +import ReactNative from './react-native.mdx'; +import Electron from './electron.mdx'; +import Flutter from './flutter.mdx'; +import MacOS from './macos.mdx' +import Unity from './unity.mdx' +import Windows from './windows.mdx'; +import Test from '@docs/shared/common/project-test/index.mdx'; + +To test this functionality: + + + +4. **Test data encryption** + + Login to as multiple users, then send and receive messages using geofencing. + + + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/geofencing/project-test/ios.mdx b/shared/signaling/geofencing/project-test/ios.mdx new file mode 100644 index 000000000..f3011d0fa --- /dev/null +++ b/shared/signaling/geofencing/project-test/ios.mdx @@ -0,0 +1,24 @@ + + +3. In the `ViewController`, update `appID`, `channelName`, and `token` with the values from . + +4. Run your using either a physical or a simulator iOS device. + + If this is the first time you run the project, grant microphone and camera access to your . + + If you use an iOS simulator, you see the remote video only. You cannot see the local video stream because of Apple simulator hardware restrictions. + + +5. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + + +You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + + diff --git a/shared/signaling/geofencing/project-test/macos.mdx b/shared/signaling/geofencing/project-test/macos.mdx new file mode 100644 index 000000000..268fbc910 --- /dev/null +++ b/shared/signaling/geofencing/project-test/macos.mdx @@ -0,0 +1,20 @@ + + +3. In the `ViewController`, update `appID`, `channelName`, and `token` with the values from . + +4. Run your . + + +5. Select an option and click **Join** to start a session. + * When you join as a **Host**, the local video is published and played in the . + * When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + + +You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + + diff --git a/shared/signaling/geofencing/project-test/react-native.mdx b/shared/signaling/geofencing/project-test/react-native.mdx new file mode 100644 index 000000000..ba94866cc --- /dev/null +++ b/shared/signaling/geofencing/project-test/react-native.mdx @@ -0,0 +1,38 @@ + +3. In `App.tsx`, update `appId`, `channelName` and `token` with the values for your temporary token. + +1. Run your app: + + - *Android* + + 1. Enable Developer options on your Android device, and then connect it to your computer using a USB cable. + 1. Run `npx react-native run-android` in the project root directory. + + - *iOS:* + + 1. Open the `ProjectName/ios/ProjectName.xcworkspace` folder with Xcode. + 1. Connect your iOS device to your Mac using a USB cable. + 1. Click the **Build and run** button in Xcode. + + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + +5. Select an option and click **Join** to start a session. + - When you join as a **Host**, the local video is published and played in the . + - When you join as **Audience**, the remote stream is subscribed and played. + + + +5. Click **Join** to start a call. + +Now, you can see yourself on the device screen and talk to the remote user using your . + + + +5. Click **Join** to start a call. + +Now, you can talk to the remote user using your . + + + diff --git a/shared/signaling/geofencing/project-test/unity.mdx b/shared/signaling/geofencing/project-test/unity.mdx new file mode 100644 index 000000000..1557aa689 --- /dev/null +++ b/shared/signaling/geofencing/project-test/unity.mdx @@ -0,0 +1,17 @@ + + +3. In your script file, update `_appID`, `_channelName` and `_token` with the values for your temporary token. + +4. In **Unity Editor**, click **Play**. A moment later you see the running on your development device. + + +5. To join as a host, select **Host** and click **Join**. + + + +5. To connect to a channel, click **Join**. + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + \ No newline at end of file diff --git a/shared/signaling/geofencing/project-test/web.mdx b/shared/signaling/geofencing/project-test/web.mdx new file mode 100644 index 000000000..5c2aa9d29 --- /dev/null +++ b/shared/signaling/geofencing/project-test/web.mdx @@ -0,0 +1,4 @@ + + + + diff --git a/shared/signaling/geofencing/project-test/windows.mdx b/shared/signaling/geofencing/project-test/windows.mdx new file mode 100644 index 000000000..22eade59e --- /dev/null +++ b/shared/signaling/geofencing/project-test/windows.mdx @@ -0,0 +1,20 @@ + + 3. In `CAgoraImplementationDlg.h`, update `appId`, `channelName` and `token` with the values for your temporary token. + + 4. In Visual Studio, click **Local Windows Debugger**. A moment later you see the project running on your development device. + + If this is the first time you run the project, you need to grant microphone and camera access to your . + + + 5. Select an option and click **Join** to start a session. + - When you join as a **Host**, the local video is published and played in the . + - When you join as **Audience**, the remote stream is subscribed and played. + + + + 5. Click **Join** to start a call. Now, you can see yourself on the device screen and talk to the remote user using your . + + + You see your starts the proxy service and magically connects to the which was not possible in a restricted network environment. + + \ No newline at end of file diff --git a/shared/signaling/geofencing/reference/index.mdx b/shared/signaling/geofencing/reference/index.mdx index 1077dbc4f..304b89858 100644 --- a/shared/signaling/geofencing/reference/index.mdx +++ b/shared/signaling/geofencing/reference/index.mdx @@ -6,6 +6,75 @@ import Unity from './unity.mdx'; import Web from './web.mdx'; import Windows from './windows.mdx'; +### Firewall requirements + +If a firewall is deployed in your network environment, ensure that you add the domains in the following table according to the region you specify, allow all IP addresses, and open the following firewall ports. + +- Whitelist domains + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RegionDomain

Mainland China

webrtc2-ap-web-2.agoraio.cn

+

webrtc2-ap-web-4.agoraio.cn

+

statscollector-3.agoraio.cn

+

statscollector-4.agoraio.cn

+

logservice-china.agora.io

North America

ap-web-1-north-america.agora.io

+

ap-web-2-north-america.agora.io

+

statscollector-1-north-america.agora.io

+

statscollector-2-north-america.agora.io

+

logservice-north-america.agora.io

Europe

ap-web-1-europe.agora.io

+

ap-web-2-europe.agora.io

+

statscollector-1-europe.agora.io

+

statscollector-2-europe.agora.io

+

logservice-europe.agora.io

Japan

ap-web-1-japan.agora.io

+

ap-web-2-japan.agora.io

+

statscollector-1-japan.agora.io

+

statscollector-2-japan.agora.io

+

logservice-japan.agora.io

India

ap-web-1-india.agora.io

+

ap-web-2-india.agora.io

+

statscollector-1-india.agora.io

+

statscollector-2-india.agora.io

+

logservice-india.agora.io

Asia excluding mainland China

ap-web-1-asia.agora.io

+

ap-web-2-asia.agora.io

+

statscollector-1-asia.agora.io

+

statscollector-2-asia.agora.io

+

logservice-asia.agora.io

+ +- Port - See the [Firewall Requirements](../reference/firewall) + +### API reference + diff --git a/shared/signaling/geofencing/reference/web.mdx b/shared/signaling/geofencing/reference/web.mdx index e9d37f892..764fe370b 100644 --- a/shared/signaling/geofencing/reference/web.mdx +++ b/shared/signaling/geofencing/reference/web.mdx @@ -1,5 +1,3 @@ -- createInstance - -- setArea +- [ API reference](/en/signaling/reference/api) diff --git a/shared/signaling/geofencing/sample-code/web.mdx b/shared/signaling/geofencing/sample-code/web.mdx index a41a72914..136d5fdc4 100644 --- a/shared/signaling/geofencing/sample-code/web.mdx +++ b/shared/signaling/geofencing/sample-code/web.mdx @@ -1,7 +1,7 @@ ```javascript - // Set region for geofencing - AgoraRTM.setArea({ areaCodes: ["GLOBAL"], excludedArea: "CHINA" }) + // Set whitelist and blacklist areas + AgoraRTM.setArea({ areaCodes: ["CHINA", "INDIA"], excludedArea: "JAPAN" }); ``` diff --git a/shared/signaling/get-started-sdk/android.mdx b/shared/signaling/get-started-sdk/android.mdx deleted file mode 100644 index 8b0b7dbd5..000000000 --- a/shared/signaling/get-started-sdk/android.mdx +++ /dev/null @@ -1,642 +0,0 @@ - - -## Project setup - -Follow the steps to create the environment necessary to add Signaling into your app. - -### 1. Create an Android project - -Use Android Studio to [create an Android project](https://developer.android.com/studio/projects/create-project). - -1. Select the Project Template as **Empty Activity**. - -2. Enter `RtmQuickstart` as the **Name**. - -3. Enter `com.example.rtmquickstart` as the **Package name**. - -4. Select **Language** as **Java**. - -### 2. Add permissions - -Add the following permissions in the `AndroidManifest.xml` file. - -```xml - - - // As of v1.4.10, you don't need to add the WRITE_EXTERNAL_STORAGE permission: - - // As of v1.4.9, you also need to add the following permission to check the connection status of the WIFI network: - -``` - -If your app targets Android 6.0 or higher, you need to dynamically apply for the above permissions, see [Request app permissions](https://developer.android.com/training/permissions/requesting) for details. - -If your app targets Android 10 or higher, refer to [Privacy changes in Android 10](https://developer.android.com/about/versions/10/privacy/changes). - -### 3. Prevent code obfuscation - -Add the following line in the `app/proguard-rules.pro` file to prevent code obfuscation: - - ```shell - -keep class io.agora.**{*;} - ``` - -If an error is reported, you can change the code as: - ```shell - -keep class io.agora**{\*;} - ``` - -### 4. Integrate the SDK - -Integrate the Agora Android SDK into your project with Maven Central. For more integration methods, see [Other approaches to integrate the SDK](#othermethods). - -1. In `/Gradle Scripts/build.gradle(Project: )`, add the following lines to add the Maven Central dependency: - - ```xml - buildscript { - repositories { - … - mavenCentral() - } - … - } - - allprojects { - repositories { - … - mavenCentral() - } - } - ``` - -2. In `/Gradle Scripts/build.gradle(Module: .app)`, add the following lines to integrate the Agora Android SDK into your Android project: - - ```xml - … - dependencies { - … - // For x.y.z, fill in a specific SDK version number. For example, 1.4.9. - // Get the latest version number through the release notes. - implementation 'io.agora.rtm:rtm-sdk:x.y.z' - } - ``` - -## Implement Signaling - -This section shows how to use the Agora to implement Signaling into your app step by step. - -### 1. Implement the UI and resource files - -To help you quickly understand and implement functions of Agora , this section shows how to implement the following functions in an Activity with minimum effort: - -- Log in to and log out of Agora - -- Join and leave a channel - -- Send and receive peer-to-peer or channel messages - -- See the changes in connection state of the user - - 1. Open the `app/res/layout/activity_main.xml` file with Android Studio, edit it in Code mode, and replace the contents of the file with the following: - - ```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -``` - -### 2. Implement the logic of sending and receiving messages - -To help you quickly understand and implement functions of Agora , this section shows how to implement the following functions in a single view with minimum effort: - -- Log in to and log out of Agora - -- Join and leave a channel - -- Send and receive peer-to-peer or channel messages - -- See the changes in connection state of the user - -To implement this functionality: - -1. In Xcode, replace the contents of the `ViewController.h` file with the following: - - ```c - // - // ViewController.h - // RtmQuickstart - // - // Created by macoscatalina on 2021/6/8. - // Copyright © 2021 macoscatalina. All rights reserved. - // - - #import - - #import - - @interface ViewController : UIViewController - - // Buttons - @property (weak, nonatomic) IBOutlet UIButton *LoginButton; - @property (weak, nonatomic) IBOutlet UIButton *LogoutButton; - @property (weak, nonatomic) IBOutlet UIButton *JoinButton; - @property (weak, nonatomic) IBOutlet UIButton *LeaveButton; - @property (weak, nonatomic) IBOutlet UIButton *GroupMsgButton; - @property (weak, nonatomic) IBOutlet UIButton *PeerMsgButton; - - // Textfields - @property (weak, nonatomic) IBOutlet UITextField *UserIDTextField; - @property (weak, nonatomic) IBOutlet UITextField *ChannelIDTextField; - @property (weak, nonatomic) IBOutlet UITextField *GroupMsgTextField; - @property (weak, nonatomic) IBOutlet UITextField *PeerMsgTextField; - @property (weak, nonatomic) IBOutlet UITextField *PeerIDTextField; - - @property (weak, nonatomic) IBOutlet UITextView *MsgTextView; - - @end - ``` - -2. In Xcode, replace the contents of the `ViewController.m` file with the following: You need to replace `Your_App_ID` with the App ID of your project, and `Your_Token` with the Token you obtained. - - ```c - // - // ViewController.m - // RtmQuickstart - // - // Created by macoscatalina on 2021/6/8. - // Copyright © 2021 macoscatalina. All rights reserved. - // - - #import "ViewController.h" - - @interface ViewController () - - @property(nonatomic, strong)AgoraRtmKit* kit; - @property(nonatomic, strong)AgoraRtmChannel* channel; - @property(nonatomic, strong)AgoraRtmSendMessageOptions* options; - - @property NSString* appID; - @property NSString* token; - - @property NSString* uid; - @property NSString* peerID; - @property NSString* channelID; - @property NSString* peerMsg; - @property NSString* channelMsg; - - @property NSString* text; - @property NSMutableArray* textArray; - - * (void)AddMsgToRecord:(NSString*)text; - - @end - - @implementation ViewController - - * (void)viewDidLoad { - [super viewDidLoad]; - // Enter your App ID - self.appID = @"Your_App_ID"; - // Create an AgoraRtmKit instance - _kit = [[AgoraRtmKit alloc] initWithAppId:self.appID delegate:self]; - - self.MsgTextView.textColor = UIColor.blueColor; - self.textArray = [[NSMutableArray alloc]init]; - } - - // Add message to the UI TextView - - (void)AddMsgToRecord:(NSString*)text { - - - [self.textArray addObject:(self.text)]; - self.MsgTextView.text = [self.textArray componentsJoinedByString:(@"\n")]; - - } - - // Button to log in to Signaling - - (IBAction)Login:(id)sender { - self.uid = self.UserIDTextField.text; - // Enter your token - self.token = @"Your_Token"; - // Log in to Signaling - [_kit loginByToken:(self.token) user:(self.uid) completion:^(AgoraRtmLoginErrorCode errorCode) { - if (errorCode != AgoraRtmLoginErrorOk){ - self.text = [NSString stringWithFormat:@"Login failed for user %@. Code: %ld",self.uid, (long)errorCode]; - NSLog(@"%@", self.text); - } - - else { - NSLog(@"%@", self.text); - self.text = [NSString stringWithFormat:@"Login successful for user %@. Code: %ld",self.uid, (long)errorCode]; - } - - [self AddMsgToRecord:(self.text)]; - - } - - ];} - - // Button to log out of Signaling - - (IBAction)Logout:(id)sender { - // Log out of Signaling - [_kit logoutWithCompletion:^(AgoraRtmLogoutErrorCode errorCode) { - if (errorCode == AgoraRtmLogoutErrorOk){ - self.text = [NSString stringWithFormat:@"Logout successful. Code: %ld",(long)errorCode]; - NSLog(@"%@", self.text); - } else { - - self.text = [NSString stringWithFormat:@"Logout failed. Code: %ld",(long)errorCode]; - NSLog(@"%@", self.text); } - - [self AddMsgToRecord:(self.text)]; - - }]; - - } - - // Button to join the Signaling channel - - (IBAction)JoinChannel:(id)sender { - - self.channelID = self.ChannelIDTextField.text; - // Create an Signaling channel - _channel = [_kit createChannelWithId:self.channelID delegate:self]; - // Join an Signaling channel - [_channel joinWithCompletion:^(AgoraRtmJoinChannelErrorCode errorCode) { - - if(errorCode == AgoraRtmJoinChannelErrorOk){ - self.text = [NSString stringWithFormat:@"Successfully joined channel %@ Code: %ld",self.channelID,(long)errorCode]; - NSLog(@"%@", self.text); - } else { - self.text = [NSString stringWithFormat:@"Failed to join channel %@ Code: %ld",self.channelID, (long)errorCode]; - NSLog(@"%@", self.text); } - - [self AddMsgToRecord:(self.text)]; - }]; - - } - - -(void)channel:(AgoraRtmChannel *)channel memberLeft:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"%@ left channel %@", member.channelId, member.userId]; - [self AddMsgToRecord:(self.text)]; - } - - -(void)channel:(AgoraRtmChannel *)channel memberJoined:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"%@ joined channel %@", member.channelId, member.userId]; - [self AddMsgToRecord:(self.text)]; - } - - // Button to leave the Signaling channel - - (IBAction)LeaveChannel:(id)sender { - [_channel leaveWithCompletion:^(AgoraRtmLeaveChannelErrorCode errorCode) { - if (errorCode == AgoraRtmLeaveChannelErrorOk){ - self.text = [NSString stringWithFormat:@"Leave channel successful Code: %ld", (long)errorCode]; - } else { - self.text = [NSString stringWithFormat:@"Failed to leave channel Code: %ld", (long)errorCode]; } - - [self AddMsgToRecord:(self.text)]; - }]; - - } - - // Button to send group message - - (IBAction)SendGroupMsg:(id)sender { - - self.channelMsg = self.GroupMsgTextField.text; - self.options.enableOfflineMessaging = true; - - [_channel sendMessage:[[AgoraRtmMessage alloc] initWithText:self.channelMsg] sendMessageOptions:self.options completion:^(AgoraRtmSendChannelMessageErrorCode errorCode) { - if (errorCode == AgoraRtmSendChannelMessageErrorOk) - { - self.text = [NSString stringWithFormat:@"Message sent to channel %@ : %@", self.channelID, self.channelMsg]; } - else - { - self.text = [NSString stringWithFormat:@"Message failed to send to channel %@ : %@ ErrorCode: %ld", self.channelID, self.channelMsg, (long)errorCode]; } - - [self AddMsgToRecord:(self.text)]; - }]; - - } - - // Display received group message - - (void)channel:(AgoraRtmChannel *)channel messageReceived:(AgoraRtmMessage *)message fromMember:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"Message received in channel: %@ from user: %@ content: %@",member.channelId, member.userId, message.text]; - [self AddMsgToRecord:(self.text)]; - } - - // Button to send peer message - - (IBAction)SendPeerMsg:(id)sender { - - self.peerMsg = self.PeerMsgTextField.text; - self.peerID = self.PeerIDTextField.text; - - [_kit sendMessage:[[AgoraRtmMessage alloc] initWithText:self.peerMsg] toPeer:self.peerID completion:^(AgoraRtmSendPeerMessageErrorCode errorCode) { - if (errorCode == AgoraRtmSendPeerMessageErrorOk) - { - self.text = [NSString stringWithFormat:@"Message sent from user: %@ to user: %@ content: %@", self.uid, self.peerID, self.peerMsg]; - } - else - { - self.text = [NSString stringWithFormat:@"Message failed to send from user: %@ to user: %@ content: %@ Error: %ld", self.uid, self.peerID, self.peerMsg, (long)errorCode]; } - [self AddMsgToRecord:(self.text)]; - - }]; - - } - - // Display received peer message - - (void)rtmKit:(AgoraRtmKit *)kit messageReceived:(AgoraRtmMessage _)message fromPeer:(NSString_)peerId - { - self.text = [NSString stringWithFormat:@"Message received from user: %@ content: %@", peerId, message.text]; - [self AddMsgToRecord:(self.text)];} - // Display connection status of the current user - - (void)rtmKit:(AgoraRtmKit *)kit connectionStateChanged:(AgoraRtmConnectionState)state reason:(AgoraRtmConnectionChangeReason)reason - { - self.text = [NSString stringWithFormat:@"Connection status changed to: %ld Reason: %ld", (long)state, (long)reason]; - [self AddMsgToRecord:(self.text)]; - } - @end - ``` - -## Test your app - -### 1. Set your signing and team - -1. In Xcode, navigate to **TARGETS > Project Name > General > Signing**, and choose **Automatically manage signing**. - -2. Read the prompts carefully, and click **Enable Automatic**. - -3. After you successfully set your signing, choose a developer in **Team**. - -### 2. Run and experience the project - -Compile and run the project on a simulator or a physical mobile device. You can see the following page if your project runs successfully: - -![1623236724183](https://web-cdn.agora.io/docs-files/1623236724183) - -## Considerations - -- The Agora supports creating multiple AgoraRtmKit instances that are independent of each other. - -- To send and receive peer-to-peer or channel messages, ensure that you have successfully logged in the Agora (you have received `AgoraRtmLoginErrorOk`). - -- To use any of the channel features, you must first call the createChannelWithId method to create a channel instance. - -- You can create multiple channel instances for each AgoraRtmKit instance, but you can only join a maximum of 20 channels at the same time. The `channelId` parameter needs to be channel-specific. - -- When you leave a channel and do not want to join it again, you can call the destroyChannelWithId method to release all resources used by the channel instance. - -- You cannot reuse a received AgoraRtmMessage instance. - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start Signaling with a token that you retrieve from your server. - -## See also - -### Sample project - -Agora also provides an open-source [sample project](https://github.com/AgoraIO/Signaling/tree/master/Agora-Signaling-Tutorial-iOS-Objective-C) for Objective-C and [sample project](https://github.com/AgoraIO/Signaling/tree/master/Agora-Signaling-Tutorial-iOS-Swift) for Swift on GitHub for your reference. - -### SDK Integration Methods - -[Downloads](../reference/downloads) shows you alternative ways to add in your project. - - diff --git a/shared/signaling/get-started-sdk/java.mdx b/shared/signaling/get-started-sdk/java.mdx deleted file mode 100644 index f0791f89a..000000000 --- a/shared/signaling/get-started-sdk/java.mdx +++ /dev/null @@ -1,470 +0,0 @@ - - - -## Create a Java project - -Create a new folder `RTM_quickstart` with the following subfolders: - -```text -RTM_quickstart/ -├── src -└── lib -``` - -## Integrate for Java - -1. Download the latest version of [](../reference/downloads) and decompress the file. Copy the `*.so` file and the `*.jar` file to the `lib` folder. - -2. Create a file named `pom.xml` in `RTM_quickstart` with the following content: - -```xml - - - 4.0.0 - - io.agora - -Client-Demo - 1.0-SNAPSHOT - - - UTF-8 - 1.6 - 1.6 - - - - - io.agora.rtm - agora-rtm-sdk - 1.0 - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.0 - - - - package - - shade - - - - - io.agora.mainClass.RtmJavaDemo - - - - - - - - - - - ``` - -## Implement - -Create a `RtmJavaDemo.java` file in `RTM_quickstart\src\main\java\io\agora` and implement the file with the following steps: - -1. Import the following libraries. - -```java - package io.agora.mainClass; - - import java.util.ArrayList; - import java.util.List; - import java.util.Map; - import java.util.Scanner; - - import io.agora.rtm.RtmClient; - import io.agora.rtm.RtmClientListener; - import io.agora.rtm.RtmMessage; - import io.agora.rtm.RtmFileMessage; - import io.agora.rtm.RtmImageMessage; - import io.agora.rtm.RtmMediaOperationProgress; - - import io.agora.rtm.ErrorInfo; - import io.agora.rtm.ResultCallback; - import io.agora.rtm.RtmChannel; - import io.agora.rtm.RtmChannelListener; - import io.agora.rtm.RtmChannelMember; - import io.agora.rtm.RtmStatusCode; - import io.agora.rtm.RtmChannelAttribute; - ``` - -2. Configure your App ID and token. - -```java - class Auth { - public static final String APP_ID = ""; - public static final String Token = ""; - } - ``` - -3. Implement the `RtmChannelListener` interface and override the following callbacks: - -- `onMessageReceived`: Occurs when the user receives a channel message. This callback returns sender uid and message instance. -- `onMemberJoined`: Occurs when a member joins the channel. This callback returns the member uid. -- `onMemberLeft`: Occurs when a member left the channel. This callback returns the member uid. - -```java -class ChannelListener implements RtmChannelListener { - private String channel_; - - public ChannelListener(String channel) { - channel_ = channel; - } - - @Override - public void onMemberCountUpdated(int memberCount) { - } - - @Override - public void onAttributesUpdated(List attribute) { - } - // Occurs when the user receives a channel message. This callback returns sender uid and message instance. - @Override - public void onMessageReceived( - final RtmMessage message, final RtmChannelMember fromMember) { - String account = fromMember.getUserId(); - String msg = message.getText(); - System.out.println("Receive message from channel: " + channel_ + - " member: " + account + " message: " + msg); - } - // Occurs when a member joins the channel. This callback returns the member uid. - @Override - public void onMemberJoined(RtmChannelMember member) { - String account = member.getUserId(); - System.out.println("member " + account + " joined the channel " - + channel_); - } - // Occurs when a member left the channel. This callback returns the member uid. - @Override - public void onMemberLeft(RtmChannelMember member) { - String account = member.getUserId(); - System.out.println("member " + account + " left the channel " - + channel_); - } - - @Override - public void onImageMessageReceived(RtmImageMessage message, RtmChannelMember fromMember){ - - } - - @Override - public void onFileMessageReceived(RtmFileMessage message, RtmChannelMember fromMember){ - - } -} - ``` - -4. Implement the app class `RtmJavaDemo` with the following logic: - - Initialize the client instance - - Override the following callbacks: - - `onConnectionStateChanged`: Occurs when the connection state changes and returns the new state with reason - - `onMessageReceived`: Occurs when receiving a peer-to-peer message and returns a message instance and the sender uid - - Log in to the - - Log out of the - - Send a peer-to-peer message - - Send a channel message - - Get channel member list - - ```java - public class RtmJavaDemo { - private RtmClient mRtmClient; - private RtmChannel mRtmChannel; - private boolean loginStatus = false; - private Scanner scn; - - public void init() { - try { - // Initialize the client instance - mRtmClient = RtmClient.createInstance(Auth.APP_ID, - new RtmClientListener() { - // Occurs when the connection state changes and returns the new state with reason - @Override - public void onConnectionStateChanged(int state, int reason) { - System.out.println("on connection state changed to " - + state + " reason: " + reason); - } - - // Occurs when receiving a peer-to-peer message and returns a message instance and the sender uid - @Override - public void onMessageReceived(RtmMessage rtmMessage, String peerId) { - String msg = rtmMessage.getText(); - System.out.println("Receive message: " + msg - + " from " + peerId); - } - - @Override - public void onTokenExpired() { - } - - @Override - public void onPeersOnlineStatusChanged(Map peersStatus) { - } - - @Override - public void onImageMessageReceivedFromPeer(RtmImageMessage message, String peerId){ - - } - - @Override - public void onFileMessageReceivedFromPeer(RtmFileMessage message, String peerId){ - - } - - @Override - public void onMediaUploadingProgress(RtmMediaOperationProgress progress, long requestId){ - - } - - @Override - public void onMediaDownloadingProgress(RtmMediaOperationProgress progress, long requestId){ - - } - }); - } catch (Exception e) { - System.out.println("Rtm sdk init fatal error!"); - throw new RuntimeException("Need to check rtm sdk init process"); - } - scn = new Scanner(System.in); - } - - public boolean login() { - System.out.println("Please enter userID (literal \"null\" or starting " + - "with space is not allowed, no more than 64 characters!):"); - String userId = scn.nextLine(); - if (userId.equals("") || - userId.startsWith(" ") || - userId.equals("null")) { - System.out.println("Invalid userID detected!"); - return false; - } - // Log in to Signaling - mRtmClient.login(Auth.Token, userId, new ResultCallback() { - //@Override - public void onSuccess(Void responseInfo) { - loginStatus = true; - System.out.println("login success!"); - } - //@Override - public void onFailure(ErrorInfo errorInfo) { - loginStatus = false; - System.out.println("login failure!"); - } - }); - return true; - } - // Log out of Signaling - public void logout() { - loginStatus = false; - mRtmClient.logout(null); - } - // CLI interface to send a peer-to-peer message - public void p2pChat(String dst) { - String msg; - while(true) { - System.out.println("please input message you want to send,"+ - " or input \'quit\' " + " to leave p2pChat"); - msg = scn.nextLine(); - if (msg.equals("quit")) { - return; - } else { - sendPeerMessage(dst, msg); - } - } - } - // CLI interface to send a channel message - public void groupChat(String channel) { - String msg; - mRtmChannel = mRtmClient.createChannel(channel, - new ChannelListener(channel)); - if (mRtmChannel == null) { - System.out.println("channel created failed!"); - return; - } - mRtmChannel.join(new ResultCallback() { - @Override - public void onSuccess(Void responseInfo) { - System.out.println("join channel success!"); - } - - @Override - public void onFailure(ErrorInfo errorInfo) { - System.out.println("join channel failure! errorCode = " - + errorInfo.getErrorCode()); - } - }); - while(true) { - System.out.println("please input message you want to send,"+ - " or input \'quit\' " + " to leave groupChat, " + - "or input \'members\' to list members"); - msg = scn.nextLine(); - if (msg.equals("quit")) { - mRtmChannel.leave(null); - mRtmChannel.release(); - mRtmChannel = null; - return; - } else if (msg.equals("members")) { - getChannelMemberList(); - } else { - sendChannelMessage(msg); - } - } - } - // Send peer-to-peer message - public void sendPeerMessage(String dst, String message) { - RtmMessage msg = mRtmClient.createMessage(); - msg.setText(message); - - mRtmClient.sendMessageToPeer(dst, msg, new ResultCallback() { - @Override - public void onSuccess(Void aVoid) { - } - - @Override - public void onFailure(ErrorInfo errorInfo) { - final int errorCode = errorInfo.getErrorCode(); - System.out.println("Send Message to peer failed, errorCode = " - + errorCode); - } - }); - } - // Get member list of a channel - public void getChannelMemberList() { - mRtmChannel.getMembers(new ResultCallback>() { - @Override - public void onSuccess(final List responseInfo) { - for (int i = 0; i < responseInfo.size(); i++) { - System.out.println("memberlist[" + i + "]" + ": " - + responseInfo.get(i).getUserId()); - } - } - - @Override - public void onFailure(ErrorInfo errorInfo) { - System.out.println("failed to get channel members, errCode = " - + errorInfo.getErrorCode()); - } - }); - } - // Send channel message - public void sendChannelMessage(String msg) { - RtmMessage message = mRtmClient.createMessage(); - message.setText(msg); - - mRtmChannel.sendMessage(message, new ResultCallback() { - @Override - public void onSuccess(Void aVoid) { - } - - @Override - public void onFailure(ErrorInfo errorInfo) { - final int errorCode = errorInfo.getErrorCode(); - System.out.println("Send Message to channel failed, erroCode = " - + errorCode); - } - }); - } - // Implement the main CLI logic - public static void main(String[] args) { - RtmJavaDemo client_ = new RtmJavaDemo(); - client_.init(); - while(true) { - if (!client_.loginStatus) { - if (!client_.login()) - continue; - } - System.out.println("1: peer to peer chat\n" - + "2: group chat\n" - + "3: logout"); - System.out.println("please input your choice:"); - Scanner scn = new Scanner(System.in); - int choice; - if (scn.hasNextInt()) { - choice = scn.nextInt(); - } else { - System.out.println("your input is not an int type"); - continue; - } - if (choice == 1) { - System.out.println("please input your destination user ID:"); - scn.nextLine(); - String dst = scn.nextLine(); - System.out.println("input destination ID:" + dst); - client_.p2pChat(dst); - } else if (choice == 2) { - System.out.println("please input your channel ID:"); - scn.nextLine(); - String channel = scn.nextLine(); - client_.groupChat(channel); - } else if (choice == 3) { - client_.logout(); - System.out.println("quit the demo? yes/no"); - scn.nextLine(); - if (scn.hasNextLine()) { - String quit = scn.nextLine(); - if (quit.equals("yes")) { - break; - } - } - } else { - continue; - } - } - System.out.println("leaving demo..."); - System.exit(0); - } - } - - ``` - -## Test your Java app - -Refer to the following steps to run the sample project: - -1. Install the `.jar` file to local maven. - - ```shell - $ mvn install:install-file -Dfile=lib/agora_rtm.jar -DgroupId=io.agora.rtm -DartifactId=agora-rtm-sdk -Dversion=1.0 -Dpackaging=jar - ``` - -2. Run `mvn package` in the folder of `pom.xml`. - - ```shell - $ mvn package - ``` - -3. Run the sample project. - - ```shell - $ java -cp target/-Client-Demo-1.0-SNAPSHOT.jar -Dsun.boot.library.path=lib/ io.agora.mainClass.RtmJavaDemo - ``` - -![](https://web-cdn.agora.io/docs-files/1619686748194) - -## Considerations for Java - -- The Agora supports creating multiple RtmClient instances that are independent of each other. - -- To send and receive peer-to-peer or channel messages, ensure that you have successfully logged in the Agora (you have received onSuccess. - -- To use any of the channel features, you must first call the createChannel method to create a channel instance. -- You can create multiple channel instances for each RtmClient instance, but you can only join a maximum of 20 channels at the same time. The `channelId` parameter needs to be channel-specific. - -- When you leave a channel and do not want to join it again, you can call the release method to release all resources used by the channel instance. - -- You cannot reuse a received RtmMessage instance. - - \ No newline at end of file diff --git a/shared/signaling/get-started-sdk/linux.mdx b/shared/signaling/get-started-sdk/linux.mdx deleted file mode 100644 index 4d7c86482..000000000 --- a/shared/signaling/get-started-sdk/linux.mdx +++ /dev/null @@ -1,12 +0,0 @@ -import CPP from './cpp.mdx'; -import JAVA from './java.mdx'; - - - - - - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start live streaming with a token that you retrieve from your server. - diff --git a/shared/signaling/get-started-sdk/macos.mdx b/shared/signaling/get-started-sdk/macos.mdx deleted file mode 100644 index b1700ec5e..000000000 --- a/shared/signaling/get-started-sdk/macos.mdx +++ /dev/null @@ -1,640 +0,0 @@ - - -## Project setup - -In this section, we create a Unity project and integrate the SDK into the project. - -### 1. Create a macOS project in Xcode - -The following steps show how to create a macOS App in Xcode: - -- Enter `RtmQuickstart` as the **Product Name**. - -- Enter `agora` as the **Organization Identifier**. - -- Select **User Interface** as **Storyboard**. - -- Select **Language** as **Objective-C**. - -### 2. Integrate the SDK - -1. In **Terminal**, go to the project path and run the `pod init` command to create a **Podfile** in the project folder. - -2. Open the **Podfile**, delete all contents and input the following contents. - - ```bash - # platform :macos, '10.10' - target 'RtmQuickstart' do - use_frameworks! - pod 'AgoraRtm_macOS' - end - ``` - -3. Run the `pod update` command to update the local libraries. - -4. Run the `pod install` command to install the Agora SDK. Once you successfully install the SDK, it shows `Pod installation complete!` in **Terminal**, and you can see a **workspace** file in the project folder. - -If you are in China, and have network problems that lead to the failed execution of the pod command, you can use mirror sites such as [Gitee Mirror](https://gitee.com/mirrors/CocoaPods-Specs) or [TUNA Mirror](https://mirrors.tuna.tsinghua.edu.cn/help/CocoaPods/). - -## Implement Signaling - -### 1. Create the UI - -1. Open the `Main.storyboard` file in Xcode, edit it in Text mode, and replace the contents of the file with the following: - - ```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ``` - -2. Make sure you set the **View Controller Scene** as **Storyboard Entry Point**. - - ![1623406434804](https://web-cdn.agora.io/docs-files/1623406434804) - -### 2. Implement the logic of sending and receiving messages - -To help you quickly understand and implement functions of Agora , this section shows how to implement the following functions in a single view with minimum effort: - -- Log in to and log out of Agora - -- Join and leave a channel - -- Send and receive peer-to-peer or channel messages - -- See the changes in connection state of the user - -To implement this functionality: - -1. In Xcode, replace the contents of the `ViewController.h` file with the following: - - ```c - // - // ViewController.h - // RtmQuickstart - // - // Created by macoscatalina on 2021/6/10. - // Copyright © 2021 macoscatalina. All rights reserved. - // - - #import - - #import - - @interface ViewController : NSViewController - - // Buttons - @property (weak, nonatomic) IBOutlet NSButton *LoginButton; - @property (weak, nonatomic) IBOutlet NSButton *LogoutButton; - @property (weak, nonatomic) IBOutlet NSButton *JoinButton; - @property (weak, nonatomic) IBOutlet NSButton *LeaveButton; - @property (weak, nonatomic) IBOutlet NSButton *GroupMsgButton; - @property (weak, nonatomic) IBOutlet NSButton *PeerMsgButton; - - // Textfields - @property (weak, nonatomic) IBOutlet NSTextField *UserIDTextField; - @property (weak, nonatomic) IBOutlet NSTextField *ChannelIDTextField; - @property (weak, nonatomic) IBOutlet NSTextField *GroupMsgTextField; - @property (weak, nonatomic) IBOutlet NSTextField *PeerMsgTextField; - @property (weak, nonatomic) IBOutlet NSTextField *PeerIDTextField; - - @property (weak) IBOutlet NSScrollView *MsgTextView; - - @end - ``` - -2. In Xcode, replace the contents of the `ViewController.m` file with the following: You need to replace `Your_App_ID` with the App ID of your project, and `Your_Token` with the Token you obtained. - - ```c - // - // ViewController.m - // RtmQuickstart - // - // Created by macoscatalina on 2021/6/10. - // Copyright © 2021 macoscatalina. All rights reserved. - // - - #import "ViewController.h" - - @interface ViewController () - - @property(nonatomic, strong)AgoraRtmKit* kit; - @property(nonatomic, strong)AgoraRtmChannel* channel; - @property(nonatomic, strong)AgoraRtmSendMessageOptions* options; - - @property NSString* appID; - @property NSString* token; - - @property NSString* uid; - @property NSString* peerID; - @property NSString* channelID; - @property NSString* peerMsg; - @property NSString* channelMsg; - - @property NSString* text; - @property NSMutableArray* textArray; - @property NSTextView* textView; - - * (void)AddMsgToRecord:(NSString*)text; - - @end - - @implementation ViewController - - * (void)viewDidLoad { - [super viewDidLoad]; - // Enter your App ID - self.appID = @"Your_App_ID"; - // Create an AgoraRtmKit instance - _kit = [[AgoraRtmKit alloc] initWithAppId:self.appID delegate:self]; - self.textArray = [[NSMutableArray alloc]init]; - } - - // Add message to the UI TextView - - (void)AddMsgToRecord:(NSString*)text { - - - [self.textArray addObject:(self.text)]; - NSSize contentSize = [self.MsgTextView contentSize]; - self.textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, contentSize.height, contentSize.width)]; - [self.textView setTextColor:NSColor.blueColor]; - [self.textView setString:[self.textArray componentsJoinedByString:(@"\n")]]; - [self.MsgTextView setDocumentView:self.textView]; - - - } - - // Button to log in to Signaling - - (IBAction)Login:(id)sender { - self.uid = [self.UserIDTextField stringValue]; - // Enter your token - self.token = @"Your_Token"; - // Log in to Signaling - [_kit loginByToken:(self.token) user:(self.uid) completion:^(AgoraRtmLoginErrorCode errorCode) { - if (errorCode != AgoraRtmLoginErrorOk){ - self.text = [NSString stringWithFormat:@"Login failed for user %@. Code: %ld",self.uid, (long)errorCode]; - NSLog(@"%@", self.text); - } - else { - self.text = [NSString stringWithFormat:@"Login successful for user %@. Code: %ld",self.uid, (long)errorCode]; - NSLog(@"%@", self.text); - } - - [self AddMsgToRecord:(self.text)]; - - } - - ];} - - - // Button to log out of Signaling - - (IBAction)Logout:(id)sender { - // Log out of Signaling - [_kit logoutWithCompletion:^(AgoraRtmLogoutErrorCode errorCode) { - if (errorCode == AgoraRtmLogoutErrorOk){ - self.text = [NSString stringWithFormat:@"Logout successful. Code: %ld",(long)errorCode]; - NSLog(@"%@", self.text); - } else { - - - self.text = [NSString stringWithFormat:@"Logout failed. Code: %ld",(long)errorCode]; - NSLog(@"%@", self.text); } - - [self AddMsgToRecord:(self.text)]; - - }]; - - - } - - // Button to join the channel - - (IBAction)JoinChannel:(id)sender { - - self.channelID = [self.ChannelIDTextField stringValue]; - // Create an channel - _channel = [_kit createChannelWithId:self.channelID delegate:self]; - // Join an channel - [_channel joinWithCompletion:^(AgoraRtmJoinChannelErrorCode errorCode) { - - if(errorCode == AgoraRtmJoinChannelErrorOk){ - self.text = [NSString stringWithFormat:@"Successfully joined channel %@ Code: %ld",self.channelID,(long)errorCode]; - NSLog(@"%@", self.text); - } else { - - self.text = [NSString stringWithFormat:@"Failed to join channel %@ Code: %ld",self.channelID, (long)errorCode]; - NSLog(@"%@", self.text); } - - [self AddMsgToRecord:(self.text)]; - }]; - - } - - -(void)channel:(AgoraRtmChannel *)channel memberLeft:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"%@ left channel %@", member.channelId, member.userId]; - [self AddMsgToRecord:(self.text)]; - } - - -(void)channel:(AgoraRtmChannel *)channel memberJoined:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"%@ joined channel %@", member.channelId, member.userId]; - [self AddMsgToRecord:(self.text)]; - } - - // Button to leave the channel - - (IBAction)LeaveChannel:(id)sender { - [_channel leaveWithCompletion:^(AgoraRtmLeaveChannelErrorCode errorCode) { - if (errorCode == AgoraRtmLeaveChannelErrorOk){ - self.text = [NSString stringWithFormat:@"Leave channel successful Code: %ld", (long)errorCode]; - } else { - self.text = [NSString stringWithFormat:@"Failed to leave channel Code: %ld", (long)errorCode]; } - - - [self AddMsgToRecord:(self.text)]; - }]; - - - } - - // Button to send group message - - (IBAction)SendGroupMsg:(id)sender { - - - self.channelMsg = [self.GroupMsgTextField stringValue]; - - self.options.enableOfflineMessaging = true; - - [_channel sendMessage:[[AgoraRtmMessage alloc] initWithText:self.channelMsg] sendMessageOptions:self.options completion:^(AgoraRtmSendChannelMessageErrorCode errorCode) { - if (errorCode == AgoraRtmSendChannelMessageErrorOk) - { - self.text = [NSString stringWithFormat:@"Message sent to channel %@ : %@", self.channelID, self.channelMsg]; } - else - { - self.text = [NSString stringWithFormat:@"Message failed to send to channel %@ : %@ ErrorCode: %ld", self.channelID, self.channelMsg, (long)errorCode]; - } - - [self AddMsgToRecord:(self.text)]; - }]; - - } - - // Display received group message - - (void)channel:(AgoraRtmChannel *)channel messageReceived:(AgoraRtmMessage *)message fromMember:(AgoraRtmMember *)member - { - self.text = [NSString stringWithFormat:@"Message received in channel: %@ from user: %@ content: %@",member.channelId, member.userId, message.text]; - [self AddMsgToRecord:(self.text)]; - } - - // Button to send peer message - - (IBAction)SendPeerMsg:(id)sender { - - self.peerMsg = [self.PeerMsgTextField stringValue]; - self.peerID = [self.PeerIDTextField stringValue]; - - [_kit sendMessage:[[AgoraRtmMessage alloc] initWithText:self.peerMsg] toPeer:self.peerID completion:^(AgoraRtmSendPeerMessageErrorCode errorCode) { - if (errorCode == AgoraRtmSendPeerMessageErrorOk) - { - self.text = [NSString stringWithFormat:@"Message sent from user: %@ to user: %@ content: %@", self.uid, self.peerID, self.peerMsg]; - } - else - { - self.text = [NSString stringWithFormat:@"Message failed to send from user: %@ to user: %@ content: %@ Error: %ld", self.uid, self.peerID, self.peerMsg, (long)errorCode]; } - [self AddMsgToRecord:(self.text)]; - - }]; - - } - - // Display received peer message - - (void)rtmKit:(AgoraRtmKit *)kit messageReceived:(AgoraRtmMessage _)message fromPeer:(NSString_)peerId - { - self.text = [NSString stringWithFormat:@"Message received from user: %@ content: %@", peerId, message.text]; - [self AddMsgToRecord:(self.text)];} - - // Display connection status of the current user - - (void)rtmKit:(AgoraRtmKit *)kit connectionStateChanged:(AgoraRtmConnectionState)state reason:(AgoraRtmConnectionChangeReason)reason - { - self.text = [NSString stringWithFormat:@"Connection status changed to: %ld Reason: %ld", (long)state, (long)reason]; - [self AddMsgToRecord:(self.text)]; - } - - * (void)setRepresentedObject:(id)representedObject { - [super setRepresentedObject:representedObject]; - - // Update the view, if already loaded. - } - - @end - ``` - -## Test your app - -Compile and run the project on a simulator or a physical mobile device. You can see the following page if your project runs successfully: - -![1623407401770](https://web-cdn.agora.io/docs-files/1623407401770) - -## Considerations - -- The Agora supports creating multiple AgoraRtmKit/) instances that are independent of each other. - -- To send and receive peer-to-peer or channel messages, ensure that you have successfully logged in the Agora (you have received `AgoraRtmLoginErrorOk`). - -- To use any of the channel features, you must first call the createChannelWithId method to create a channel instance. - -- You can create multiple channel instances for each AgoraRtmKit) instance, but you can only join a maximum of 20 channels at the same time. The `channelId` parameter needs to be channel-specific. - -- When you leave a channel and do not want to join it again, you can call the destroyChannelWithId method to release all resources used by the channel instance. - -- You cannot reuse a received AgoraRtmMessage instance. - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start Signaling with a token that you retrieve from your server. - -## See also - -### Sample project - -Agora also provides an open-source [sample project](https://github.com/AgoraIO/Signaling/tree/master/Agora-Signaling-Tutorial-macOS-Swift) for Swift on GitHub for your reference. - -### SDK Integration Methods - -[Downloads](../reference/downloads) shows you alternative ways to add in your project. - - diff --git a/shared/signaling/get-started-sdk/reference/index.mdx b/shared/signaling/get-started-sdk/reference/index.mdx new file mode 100644 index 000000000..e44782ef7 --- /dev/null +++ b/shared/signaling/get-started-sdk/reference/index.mdx @@ -0,0 +1,11 @@ +import Web from './web.mdx'; + + + +For more information, see: + +- [Downloads](../reference/downloads) + +- [API limitations](/en/signaling/reference/limitations) + +- [ API reference](/en/signaling/reference/api) diff --git a/shared/signaling/get-started-sdk/reference/web.mdx b/shared/signaling/get-started-sdk/reference/web.mdx new file mode 100644 index 000000000..ec091ebcc --- /dev/null +++ b/shared/signaling/get-started-sdk/reference/web.mdx @@ -0,0 +1,7 @@ + + +### Token expiration + +After a token expires, you call the logout method to log out of , then use the new Token to create an `RTM` instance, and then call the login method to log in to again. + + \ No newline at end of file diff --git a/shared/signaling/get-started-sdk/test/index.mdx b/shared/signaling/get-started-sdk/test/index.mdx new file mode 100644 index 000000000..5863d2d9b --- /dev/null +++ b/shared/signaling/get-started-sdk/test/index.mdx @@ -0,0 +1,12 @@ +import Web from './web.mdx'; + +In , each authentication token you create is specific for a user ID. You create a token for each +user in the channel, each user must log in from different instance of your . +To test , you run 2 or more instances of your . When you call `login` using , ensure that the UID is the same as you used to create the token. + +For each user in your tests: + +1. **[Generate a temporary token](../reference/manage-agora-account#generate-a-temporary-token)**. + + diff --git a/shared/signaling/get-started-sdk/test/web.mdx b/shared/signaling/get-started-sdk/test/web.mdx new file mode 100644 index 000000000..3f238ac77 --- /dev/null +++ b/shared/signaling/get-started-sdk/test/web.mdx @@ -0,0 +1,28 @@ + +2. **Configure the project**: + + In `/src/signaling_manager/config.json`: + + 1. Replace the value for `token` with the token. + + 1. Replace the value for `appId` with the value from . + + 1. Replace the value for UID with the the same value you used to generate the token. + + 1. Ensure that the `channelName` is filled in. The channel name can be any string. + +1. **Run the reference app**: + + Open Terminal in the project folder, then run the following command: + + ``` bash + pnpm dev + ``` + + Use the URL displayed in Terminal to open the app in your browser. + +1. **Test this functionality**: + + Choose **SDK quickstart**, then log in to and send and receive messages. When you open the reference app in multiple tabs, after login you see the messages sent and received in the log. + + diff --git a/shared/signaling/get-started-sdk/unity.mdx b/shared/signaling/get-started-sdk/unity.mdx deleted file mode 100644 index 7ac88ef97..000000000 --- a/shared/signaling/get-started-sdk/unity.mdx +++ /dev/null @@ -1,506 +0,0 @@ - - -## Project setup - -In this section, we create a Unity project and integrate the SDK into the project. - -### Create a Unity project - -1. Click **File** > **New Project** in Unity. - -2. Select **2D** as the template. Set the project name and location, and click **Create**. After the creation is complete, Unity will display the project editing interface. - -### Integrate the SDK - -#### Approach 1: Integrate the SDK by importing the asset package - -1. Go to [GitHub](https://github.com/AgoraIO-Community/Agora-Unity--SDK/releases) to download the latest version of the Agora Unity asset package and unzip it. - -2. In the Unity Editor, select **Assets** > **Import Package** > **Custom Package**. - -3. Select the Agora Unity asset package and click **Open**. - -4. All packages of the SDK are chosen by default. Uncheck the packages you do not need and click **Import**. - -#### Approach 2: Manually add the SDK files - -1. Download and extract the latest version of the [Agora ](../reference/downloads). - -2. Copy the `Rtm-Scripts` folder under the `libs` folder in the SDK package to the `Assets` folder of the project path. - -3. Copy the following files under the `libs/Plugins` path in the SDK package to the corresponding path of the project: - -\| Development Platform \| File or folder \| Project directory \| -\| :——————- \| :—————- \| :————————- \| -\| Android \| `Plugins/Android` \| `/Assets/Plugins/Android/` \| -\| iOS \| `Plugins/iOS` \| `/Assets/Plugins/iOS` \| -\| macOS \| `Plugins/macOS` \| `/Assets/Plugins/macOS` \| -\| Windows \| `Plugins/x86` \| `/Assets/Plugins/x86` \| -\| Windows \| `Plugins/x86_64` \| `/Assets/Plugins/x86_64` \| - -## Implement Signaling - -This section shows how to use the Agora to implement Signaling into your app step by step. - -### 1.Create the UI - -Create the following user interface elements in Unity: - -- **Canvas** - -- **Panel**: The main operation interface. - - - **Text**: Title text, include App ID field and Token field. - - - **InputField**: The User IDs of the sender and receiver, Peer-to-peer message, Channel name, and Channel message. - - - **Button**: Log in, Log out, Send peer-to-peer message, Join channel, Send channel message and Leave channel. - -- **ScrollView**: Display message records and status change records. - -When you are finished, your interface should look like the following figure: - -![1625627589066](https://web-cdn.agora.io/docs-files/1625627589066) - -### 2. Implement the interface script - -Create an empty GameObject in the **scene** and name it **MessageManager**. Add two scripts into the GameObject: - -- `MessageManager.cs`: The basic logic of sending and receiving messages. - -- `MessageDisplay.cs`: Display messages and status changes on the user interface. - -**MessageManager.cs sample code** - ```csharp - using System.Collections.Generic; - using UnityEngine; - using UnityEngine.UI; - - - using agora_rtm; - - namespace io.agora.rtm.quickstart - { - public class MessageManager : MonoBehaviour - { - - - // Serialization field, used to fill in the App ID and the Token in the Unity Editor - [Header("Agora Properties")] - [SerializeField] - private string appId = ""; - [SerializeField] - private string token = ""; - // Serialization field, used to connect Unity objects and script variables in the Unity Editor - [Header("Application Properties")] - - [SerializeField] InputField userNameInput, channelNameInput; - [SerializeField] InputField channelMsgInputBox; - [SerializeField] InputField peerUserBox; - [SerializeField] InputField peerMessageBox; - [SerializeField] MessageDisplay messageDisplay; - - - private RtmClient rtmClient = null; - private RtmChannel channel; - - private RtmClientEventHandler clientEventHandler; - private RtmChannelEventHandler channelEventHandler; - private RtmCallEventHandler callEventHandler; - - string _userName = ""; - string UserName { - get { return _userName; } - set { - _userName = value; - PlayerPrefs.SetString("RTM_USER", _userName); - PlayerPrefs.Save(); - } - } - - string _channelName = ""; - string ChannelName - { - get { return _channelName; } - set { - _channelName = value; - PlayerPrefs.SetString("RTM_CHANNEL", _channelName); - PlayerPrefs.Save(); - } - } - - agora_rtm.SendMessageOptions _MessageOptions = new agora_rtm.SendMessageOptions() { - enableOfflineMessaging = true, - enableHistoricalMessaging = true - }; - - private void Awake() - { - userNameInput.text = PlayerPrefs.GetString("RTM_USER", ""); - channelNameInput.text = PlayerPrefs.GetString("RTM_CHANNEL", ""); - - - } - - // Initialize - void Start() - { - clientEventHandler = new RtmClientEventHandler(); - channelEventHandler = new RtmChannelEventHandler(); - callEventHandler = new RtmCallEventHandler(); - - rtmClient = new RtmClient(appId, clientEventHandler); - #if UNITY_EDITOR - rtmClient.SetLogFile("./rtm_log.txt"); - #endif - - clientEventHandler.OnQueryPeersOnlineStatusResult = OnQueryPeersOnlineStatusResultHandler; - clientEventHandler.OnLoginSuccess = OnClientLoginSuccessHandler; - clientEventHandler.OnLoginFailure = OnClientLoginFailureHandler; - clientEventHandler.OnMessageReceivedFromPeer = OnMessageReceivedFromPeerHandler; - - channelEventHandler.OnJoinSuccess = OnJoinSuccessHandler; - channelEventHandler.OnJoinFailure = OnJoinFailureHandler; - channelEventHandler.OnLeave = OnLeaveHandler; - channelEventHandler.OnMessageReceived = OnChannelMessageReceivedHandler; - - } - - void OnApplicationQuit() - { - if (channel != null) - { - channel.Dispose(); - channel = null; - } - if (rtmClient != null) - { - rtmClient.Dispose(); - rtmClient = null; - } - } - // Log in - public void Login() - { - UserName = userNameInput.text; - - if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(appId)) - { - Debug.LogError("We need a username and appId to login"); - return; - } - - rtmClient.Login(token, UserName); - } - // Log out - public void Logout() - { - messageDisplay.AddTextToDisplay(UserName + " logged out of the rtm", Message.MessageType.Info); - rtmClient.Logout(); - } - - // Join the channel - public void JoinChannel() - { - ChannelName = channelNameInput.GetComponent().text; - channel = rtmClient.CreateChannel(ChannelName, channelEventHandler); - ShowCurrentChannelName(); - channel.Join(); - } - // leave the channel - public void LeaveChannel() - { - messageDisplay.AddTextToDisplay(UserName + " left the chat", Message.MessageType.Info); - channel.Leave(); - } - // Send channel message - public void SendMessageToChannel() - { - string msg = channelMsgInputBox.text; - string peer = "[channel:" + ChannelName + "]"; - - string displayMsg = string.Format("{0}->{1}: {2}", UserName, peer, msg); - - messageDisplay.AddTextToDisplay(displayMsg, Message.MessageType.PlayerMessage); - channel.SendMessage(rtmClient.CreateMessage(msg)); - } - // Send peer-to-peer message - public void SendPeerMessage() - { - string msg = peerMessageBox.text; - string peer = peerUserBox.text; - - string displayMsg = string.Format("{0}->{1}: {2}", UserName, peer, msg); - messageDisplay.AddTextToDisplay(displayMsg, Message.MessageType.PlayerMessage); - - rtmClient.SendMessageToPeer( - peerId: peer, - message: rtmClient.CreateMessage(msg), - options: _MessageOptions - ); - - peerMessageBox.text = ""; - } - - - - void ShowCurrentChannelName() - { - ChannelName = channelNameInput.GetComponent().text; - Debug.Log("Channel name is " + ChannelName); - } - - - void OnQueryPeersOnlineStatusResultHandler(int id, long requestId, PeerOnlineStatus[] peersStatus, int peerCount, QUERY_PEERS_ONLINE_STATUS_ERR errorCode) - { - if (peersStatus.Length > 0) - { - Debug.Log("OnQueryPeersOnlineStatusResultHandler requestId = " + requestId + - " peersStatus: peerId=" + peersStatus[0].peerId + - " online=" + peersStatus[0].isOnline + - " onlinestate=" + peersStatus[0].onlineState); - messageDisplay.AddTextToDisplay("User " + peersStatus[0].peerId + " online status = " + peersStatus[0].onlineState, Message.MessageType.Info); - } - } - // Callback when joining a channel successfully - void OnJoinSuccessHandler(int id) - { - string msg = "channel:" + ChannelName + " OnJoinSuccess id = " + id; - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - - } - // Callback when failed to join a channel - void OnJoinFailureHandler(int id, JOIN_CHANNEL_ERR errorCode) - { - string msg = "channel OnJoinFailure id = " + id + " errorCode = " + errorCode; - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Error); - } - // Callback when log in successfully - void OnClientLoginSuccessHandler(int id) - { - string msg = "client login successful! id = " + id; - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - } - // Callback when failed to log in - void OnClientLoginFailureHandler(int id, LOGIN_ERR_CODE errorCode) - { - string msg = "client login unsuccessful! id = " + id + " errorCode = " + errorCode; - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Error); - } - // Callback when leave the channel - void OnLeaveHandler(int id, LEAVE_CHANNEL_ERR errorCode) - { - string msg = "client onleave id = " + id + " errorCode = " + errorCode; - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - } - // Callback when receiving a channel message - void OnChannelMessageReceivedHandler(int id, string userId, TextMessage message) - { - Debug.Log("client OnChannelMessageReceived id = " + id + ", from user:" + userId + " text:" + message.GetText()); - messageDisplay.AddTextToDisplay(userId + ": " + message.GetText(), Message.MessageType.ChannelMessage); - } - // Callback when receiving a peer-to-peer message - void OnMessageReceivedFromPeerHandler(int id, string peerId, TextMessage message) - { - Debug.Log("client OnMessageReceivedFromPeer id = " + id + ", from user:" + peerId + " text:" + message.GetText()); - messageDisplay.AddTextToDisplay(peerId + ": " + message.GetText(), Message.MessageType.PeerMessage); - } - // Callback when a remote member joins the channel - void OnMemberJoinedHandler(int id, RtmChannelMember member) - { - string msg = "channel OnMemberJoinedHandler member ID=" + member.GetUserId() + " channelId = " + member.GetChannelId(); - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - } - // Callback when a remote member leaves the channel - void OnMemberLeftHandler(int id, RtmChannelMember member) - { - string msg = "channel OnMemberLeftHandler member ID=" + member.GetUserId() + " channelId = " + member.GetChannelId(); - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - } - - // Returns the result of the `SendMessage` method call - - void OnSendMessageResultHandler(int id, long messageId, PEER_MESSAGE_ERR_CODE errorCode) - { - string msg = string.Format("Sent message with id:{0} MessageId:{1} errorCode:{2}", id, messageId, errorCode); - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, errorCode == PEER_MESSAGE_ERR_CODE.PEER_MESSAGE_ERR_OK ? Message.MessageType.Info : Message.MessageType.Error); - } - - // Callback when the connection state changes between the SDK and the Agora system - void OnConnectionStateChangedHandler(int id, CONNECTION_STATE state, CONNECTION_CHANGE_REASON reason) - { - string msg = string.Format("connection state changed id:{0} state:{1} reason:{2}", id, state, reason); - Debug.Log(msg); - messageDisplay.AddTextToDisplay(msg, Message.MessageType.Info); - } - } - - } - ``` - -**MessageDisplay.cs sample code** - ```csharp - using System.Collections.Generic; - using UnityEngine; - using UnityEngine.UI; - - namespace io.agora.rtm.quickstart - { - public class MessageDisplay : MonoBehaviour - { - #pragma warning disable 0649 - [SerializeField] int maxMessages = 25; - [SerializeField] GameObject chatPanel, textPrefab; - [SerializeField] MessageColorStruct MessageColors; - [SerializeField] List messageList = new List(); - #pragma warning restore 0649 - - private void Awake() - { - } - // Convert Text to prefab and add it to the Content object of ScrollView to display the text line by line - public void AddTextToDisplay(string text, Message.MessageType messageType) - { - if (messageList.Count >= maxMessages) - { - Destroy(messageList[0].textObj.gameObject); - messageList.Remove(messageList[0]); - } - - Message newMessage = new Message(); - newMessage.text = text; - - GameObject newText = Instantiate(textPrefab, chatPanel.transform); - newMessage.textObj = newText.GetComponent(); - newMessage.textObj.text = newMessage.text; - newMessage.textObj.color = MessageTypeColor(messageType); - messageList.Add(newMessage); - } - - - public void Clear() - { - - foreach (Message msg in messageList) { - Destroy(msg.textObj.gameObject); - } - messageList.Clear(); - } - - Color MessageTypeColor(Message.MessageType messageType) - { - Color color = MessageColors.infoColor; - - switch (messageType) - { - case Message.MessageType.PlayerMessage: - color = MessageColors.playerColor; - break; - case Message.MessageType.ChannelMessage: - color = MessageColors.channelColor; - break; - case Message.MessageType.PeerMessage: - color = MessageColors.peerColor; - break; - case Message.MessageType.Error: - color = MessageColors.errorColor; - break; - } - - return color; - } - } - - - [System.Serializable] - public class Message - { - public string text; - public Text textObj; - public MessageType messageType; - - public enum MessageType - { - Info, - Error, - PlayerMessage, - ChannelMessage, - PeerMessage - } - } - - [System.Serializable] - public struct MessageColorStruct - { - public Color infoColor, errorColor, playerColor, peerColor, channelColor; - } - } - ``` - -### 3. Connect the script to the user interface elements - -1. Select the user interface elements and script resources according to the attributes in the **MessageManager**. - - - **userNameInput:** Select the InputField object of the local user ID. - - - **channelNameInput:** Select the InputField object of the channel name. - - - **channelMsgInputBox:** Select the InputField object of the channel message. - - - **peerUserBox:** Select the InputField object of the remote user ID. - - - **peerMessageBox:** Select the InputField object of the peer-to-peer message. - - - **messageDisplay:** Select the MessageManager script. - -2. Set the properties of the **MessageDisplay** object : - - - **chatPanel:** Select the **Content** object in **ScrollView** > **Viewport**. - - - **textPrefab:** Select the **prefab** in the asset. You must create a prefab of type Text in advance. - - - **MessageColors:** Choose the colors of the different types of text. - -3. Set the OnClick trigger logic of the Button. When you click each Button, the corresponding method in the script will be triggered : - - - **Log in**: `MessageManager.Login` - - - **Send peer-to-peer message**: `MessageManager.SendPeerMessage` - - - **Log out**: `MessageManager.Logout` - - - **Join the channel**: `MessageManager.JoinChannel` - - - **Send channel message**: `MessageManager.SendMessageToChannel` - - - **Leave the channel**: `MessageManager.LeaveChannel` - -## Test your app - -To test your app, follow the steps: - -1. Fill in the App ID and Token in the Agora Properties field of the **MessageManager** object. - -2. Click the **File** menu bar in Unity, and set the device you need to run through **Build Settings**. - -3. Click the **Play** button at the top of the Unity main interface to run the sample project directly, or click **File** > **Build And Run** in the menu bar to compile and run the sample project. If the project runs successfully, you can see the following screen on your device: - -![1625628015802](https://web-cdn.agora.io/docs-files/1625628015802) - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start Signaling with a token that you retrieve from your server. - -## See also - -Agora also provides an open-source [sample project](https://github.com/AgoraIO-Community/Agora-Unity-RTM-SDK/tree/master/Unity-RTM-Demo) on GitHub for your reference. - - diff --git a/shared/signaling/get-started-sdk/web.mdx b/shared/signaling/get-started-sdk/web.mdx deleted file mode 100644 index c1072d0a3..000000000 --- a/shared/signaling/get-started-sdk/web.mdx +++ /dev/null @@ -1,362 +0,0 @@ - - -## Project setup - -### 1. Create a web project - -Create a new directory named `RTM_quickstart`. Go to the directory, and run `npm init` to create a `package.json` file. Then, create the following files: - -- `index.html` - -- `index.js` - -The project directory now has the following structure: - -```text -RTM_quickstart -├─ index.html -├─ index.js -└─ package.json -``` - -### 2. Integrate the SDK - -Integrate the Agora for Web into your project through npm, as follows: - -1. In the `package.json` file, add `agora-rtm-sdk` and its version number to the `dependencies` field: - - ```json - { - "name": "web", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "dependencies": { - "agora-rtm-sdk": "latest" - }, - "author": "", - "license": "ISC" - } - ``` - -2. Import the `AgoraRTM` module in the JS or TS file: - - ```javascript - import AgoraRTM from 'agora-rtm-sdk' - ``` - -## Implement Signaling - -### 1. Create the UI - -Refer to the following code sample to modify the `index.html` file: `` is used to refer to the `bundle.js` file packaged by webpack. A sample webpack configuration is shown in later steps. - -```html - - - - - Signaling Quickstart - - - -

Signaling Quickstart

-
-
-
-
-
- - -
-
-
- - -
-
-
- -
-
-
- - -
-
-
- - - -
-
- - -
-
- - - -
-
-
-
-
-
-
- - -``` - -### 2. Implement peer-to-peer and channel messaging - -Refer to the following code sample to modify the `index.js` file. Note that to avoid browser-compatibility issues, the sample uses the import command to import the SDK and webpack to package the JS file. You need to replace `""` and `""` with the App ID and token you have acquired in the previous step. - -```javascript -import AgoraRTM from 'agora-rtm-sdk' - -// Params for login -let options = { - uid: "", - token: "" -} - -// Your app ID -const appID = "" -// Your token -options.token = "" - -// Initialize client -const client = AgoraRTM.createInstance(appID) - -// Client Event listeners -// Display messages from peer -client.on('MessageFromPeer', function (message, peerId) { - - document.getElementById("log").appendChild(document.createElement('div')).append("Message from: " + peerId + " Message: " + message) -}) -// Display connection state changes -client.on('ConnectionStateChanged', function (state, reason) { - - document.getElementById("log").appendChild(document.createElement('div')).append("State changed To: " + state + " Reason: " + reason) - -}) - -let channel = client.createChannel("demoChannel") - -channel.on('ChannelMessage', function (message, memberId) { - - document.getElementById("log").appendChild(document.createElement('div')).append("Message received from: " + memberId + " Message: " + message) - -}) -// Display channel member stats -channel.on('MemberJoined', function (memberId) { - - document.getElementById("log").appendChild(document.createElement('div')).append(memberId + " joined the channel") - -}) -// Display channel member stats -channel.on('MemberLeft', function (memberId) { - - document.getElementById("log").appendChild(document.createElement('div')).append(memberId + " left the channel") - -}) - -// Button behavior -window.onload = function () { - - // Buttons - // login - document.getElementById("login").onclick = async function () { - options.uid = document.getElementById("userID").value.toString() - await client.login(options) - } - - // logout - document.getElementById("logout").onclick = async function () { - await client.logout() - } - - // create and join channel - document.getElementById("join").onclick = async function () { - // Channel event listeners - // Display channel messages - await channel.join().then (() => { - document.getElementById("log").appendChild(document.createElement('div')).append("You have successfully joined channel " + channel.channelId) - }) - } - - // leave channel - document.getElementById("leave").onclick = async function () { - - if (channel != null) { - await channel.leave() - } - - else - { - console.log("Channel is empty") - } - - } - - // send peer-to-peer message - document.getElementById("send_peer_message").onclick = async function () { - - let peerId = document.getElementById("peerId").value.toString() - let peerMessage = document.getElementById("peerMessage").value.toString() - - await client.sendMessageToPeer( - { text: peerMessage }, - peerId, - ).then(sendResult => { - if (sendResult.hasPeerReceived) { - - document.getElementById("log").appendChild(document.createElement('div')).append("Message has been received by: " + peerId + " Message: " + peerMessage) - - } else { - - document.getElementById("log").appendChild(document.createElement('div')).append("Message sent to: " + peerId + " Message: " + peerMessage) - - } - }) - } - - // send channel message - document.getElementById("send_channel_message").onclick = async function () { - - let channelMessage = document.getElementById("channelMessage").value.toString() - - if (channel != null) { - await channel.sendMessage({ text: channelMessage }).then(() => { - - document.getElementById("log").appendChild(document.createElement('div')).append("Channel message: " + channelMessage + " from " + channel.channelId) - - } - - ) - } - } -} -``` - -## Test your app - -This article uses [webpack](https://webpack.js.org/) to package the project and `webpack-dev-server` to run the project. - -1. In the `package.json` file, add `webpack`, `webpack-cli`, and `webpack-dev-server` to the `dependencies` field, and the `build` and `start:dev` commands to the `scripts` field. - - ```json - { - "name": "web", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "build": "webpack --config webpack.config.js", - "start:dev": "webpack serve --config webpack.config.js" - }, - "dependencies": { - "agora-rtm-sdk": "latest", - "webpack": "^5.28.0", - "webpack-dev-server": "^4.0.0" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "webpack-cli": "^5.1.1" - } - } - ``` - -2. Create a file named `webpack.config.js` in the project directory to configure webpack. The JS file should contain the following lines: - - ```javascript - const path = require("path"); - - module.exports = { - entry: "./index.js", - output: { - filename: "bundle.js", - path: path.resolve(__dirname, "./dist"), - }, - devServer: { - static: path.resolve(__dirname, "./"), - compress: true, - port: 9000, - }, - }; - ``` - - The project directory now has the following structure: - - ```text - RTM_quickstart - ├─ index.html - ├─ index.js - ├─ package.json - └─ webpack.config.js - ``` - -3. Run the following command in the project directory to install dependencies: - - ```shell - $ npm install - ``` - -4. Run the following command to build and run the project using webpack: - - ```shell - # Use webpack to package the project - $ npm run build - ``` - -5. Use webpack-dev-server to run the project - - ```shell - $ npm run start:dev - ``` - -If the project runs successfully, you can send and receive peer-to-peer messages and channel messages. - -![1618225131946](https://web-cdn.agora.io/docs-files/1618225131946) - -## Considerations - -- The Agora supports creating multiple RtmClient instances that are independent of each other. - -- To send and receive peer-to-peer or channel messages, ensure that you have successfully logged in the Agora . - -- To use any of the channel features, you must first call the createChannel method to create a channel instance. - -- You can create multiple channel instances for each RtmClient instance, but you can only join a maximum of 20 channels at the same time. The `channelId` parameter needs to be channel-specific. - -- When you do not want to use a specific instance any more, you can use the `removeAllListeners` method to remove all its listeners. - -- You cannot reuse a received RtmMessage instance. - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start Signaling with a token that you retrieve from your server. - -## See also - -### Sample project - -Agora provides an open-source [sample project](https://github.com/AgoraIO/Signaling/tree/master/Agora-Signaling-Tutorial-Web) on GitHub for your reference. - -### SDK Integration Methods - -[Downloads](../reference/downloads) shows you alternative ways to add in your project. - -
diff --git a/shared/signaling/get-started-sdk/windows.mdx b/shared/signaling/get-started-sdk/windows.mdx deleted file mode 100644 index f32c783f1..000000000 --- a/shared/signaling/get-started-sdk/windows.mdx +++ /dev/null @@ -1,401 +0,0 @@ - - - - -## Project setup - -### Create a C++ console app - -[Create a C++ console app with Visual Studio](https://docs.microsoft.com/en-us/cpp/build/vscpp-step-1-create?view=msvc-150). - -- Select **Visual C++ > Console App**. -- Set **Name** and the **Solution name** as `RtmQuickstart`. - -### Integrate the SDK - -Complete the following steps to integrate the Agora into your project. - -1. Configure the project files. - -- Go to [SDK Downloads](/sdks), download the latest version of the C++ SDK for Windows, and unzip the downloaded SDK package. -- Copy all subfolders of the **sdk** folder of the downloaded SDK package to the solution directory. Ensure that the subfolders are in the same location as your **.sln** file. - -2. Configure the project properties. - -Right-click the project name in the **Solution Explorer** window, click **Properties** to configure the following project properties, and click **OK**. - -- Go to the **C/C++ > General > Additional Include Directories** menu, click **Edit**, and input **$(SolutionDir)include** in the pop-up window. -- Go to the **Linker > General > Additional Library Directories** menu, click **Edit**, and input **$(SolutionDir)lib** in the pop-up window. -- Go to the **Linker > Input > Additional Dependencies** menu, click **Edit**, and input **agora_rtm_sdk.lib** in the pop-up window. - -## Implement real-time messaging - -Open `RtmQuickstart.cpp` and replace the file content with the following code. You need to replace `` with your App ID; replace `` with your token. - -```cpp -// RtmQuickstart.cpp : This file contains the 'main' function. Program execution begins and ends there. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IAgoraRtmService.h" - -using namespace std; - -// Your App ID -string APP_ID = ""; -// Your Token -string Token = ""; - -class RtmEventHandler : public agora::rtm::IRtmServiceEventHandler { -public: - RtmEventHandler() {} - ~RtmEventHandler() {} - // Login successful. - virtual void onLoginSuccess() override { - cout << "on login success" << endl; - } - // Login failed. - virtual void onLoginFailure(agora::rtm::LOGIN_ERR_CODE errorCode) override { - cout << "on login failure: errorCode = " << errorCode << endl; - } - // Logout successful. - virtual void onLogout(agora::rtm::LOGOUT_ERR_CODE errorCode) override { - cout << "on logout" << endl; - } - // Occurs when connection state changes. - virtual void onConnectionStateChanged(agora::rtm::CONNECTION_STATE state, - agora::rtm::CONNECTION_CHANGE_REASON reason) override { - cout << "on connection state changed: state = " << state << endl; - } - // Occurs when the peer message send status is returned. - virtual void onSendMessageResult(long long messageId, - agora::rtm::PEER_MESSAGE_ERR_CODE state) override { - cout << "on send message messageId: " << messageId << " state: " << state << endl; - } - // Occurs when the peer message is received. - virtual void onMessageReceivedFromPeer(const char *peerId, - const agora::rtm::IMessage *message) override { - cout << "on message received from peer: peerId = " << peerId - << " message = " << message->getText() << endl; - } -}; - - -class ChannelEventHandler : public agora::rtm::IChannelEventHandler { -public: - ChannelEventHandler(string channel) { - channel_ = channel; - } - ~ChannelEventHandler() {} - // The user successfully joined channel. - virtual void onJoinSuccess() override { - cout << "on join channel success" << endl; - } - // The user failed to join channel. - virtual void onJoinFailure(agora::rtm::JOIN_CHANNEL_ERR errorCode) override { - cout << "on join channel failure: errorCode = " << errorCode << endl; - } - // The user leaves channel. - virtual void onLeave(agora::rtm::LEAVE_CHANNEL_ERR errorCode) override { - cout << "on leave channel: errorCode = " << errorCode << endl; - } - // The user receives a channel message. - virtual void onMessageReceived(const char* userId, - const agora::rtm::IMessage *msg) override { - cout << "receive message from channel: " << channel_.c_str() - << " user: " << userId << " message: " << msg->getText() - << endl; - } - // Occurs when a user joins a channel. - virtual void onMemberJoined(agora::rtm::IChannelMember *member) override { - cout << "member: " << member->getUserId() << " joined channel: " - << member->getChannelId() << endl; - } - // Occurs when a user leaves a channel. - virtual void onMemberLeft(agora::rtm::IChannelMember *member) override { - cout << "member: " << member->getUserId() << " lefted channel: " - << member->getChannelId() << endl; - } - // Gets a list of channel members. - virtual void onGetMembers(agora::rtm::IChannelMember **members, - int userCount, - agora::rtm::GET_MEMBERS_ERR errorCode) override { - cout << "list all members for channel: " << channel_.c_str() - << " total members num: " << userCount << endl; - for (int i = 0; i < userCount; i++) { - cout << "index[" << i << "]: " << members[i]->getUserId(); - } - } - // Occurs when the channel message send status is returned. - virtual void onSendMessageResult(long long messageId, - agora::rtm::CHANNEL_MESSAGE_ERR_CODE state) override { - cout << "send messageId: " << messageId << " state: " << state << endl; - } -private: - string channel_; -}; - - -class Quickstart { -public: - // Creates an IRtmService instance. - Quickstart() { - eventHandler_.reset(new RtmEventHandler()); - agora::rtm::IRtmService* p_rs = agora::rtm::createRtmService(); - rtmService_.reset(p_rs, [](agora::rtm::IRtmService* p) { - p->release(); - }); - - if (!rtmService_) { - cout << "Failed to create service! Check your App ID" << endl; - exit(0); - } - - if (rtmService_->initialize(APP_ID.c_str(), eventHandler_.get())) { - cout << "Failed to initialize service!" << endl; - exit(0); - } - } - // Releases an IRtmService instance. - ~Quickstart() { - rtmService_->release(); - } - -public: - // Logs in to . - bool login() { - cout << "Please enter userID:" - << endl; - string userID; - getline(std::cin, userID); - if (rtmService_->login(Token.c_str(), userID.c_str())) { - cout << "login failed!" << endl; - return false; - } - cout << "here" << endl; - return true; - } - // Logs out of . - void logout() { - rtmService_->logout(); - cout << "log out!" << endl; - } - // One-to-one chat using peer messaging. - void p2pChat(const std::string& dst) { - string msg; - while (true) { - cout << "please input message you want to send, or input \"quit\" " - << "to leave p2pChat" << endl; - getline(std::cin, msg); - if (msg.compare("quit") == 0) { - return; - } - else { - sendMessageToPeer(dst, msg); - } - } - } - // Group chat using channel messaging. - void groupChat(const std::string& channel) { - string msg; - channelEvent_.reset(new ChannelEventHandler(channel)); - agora::rtm::IChannel * channelHandler = - rtmService_->createChannel(channel.c_str(), channelEvent_.get()); - if (!channelHandler) { - cout << "create channel failed!" << endl; - } - channelHandler->join(); - while (true) { - cout << "please input message you want to send, or input \"quit\" " - << " to leave groupChat, or input \"members\" to list members" - << endl; - getline(std::cin, msg); - if (msg.compare("quit") == 0) { - channelHandler->leave(); - return; - } - else if (msg.compare("members") == 0) { - channelHandler->getMembers(); - } - else { - sendMessageToChannel(channelHandler, msg); - } - } - } - // Send peer message. - void sendMessageToPeer(std::string peerID, std::string msg) { - agora::rtm::IMessage* rtmMessage = rtmService_->createMessage(); - rtmMessage->setText(msg.c_str()); - int ret = rtmService_->sendMessageToPeer(peerID.c_str(), - rtmMessage); - rtmMessage->release(); - if (ret) { - cout << "send message to peer failed! return code: " << ret - << endl; - } - } - // Send channel message. - void sendMessageToChannel(agora::rtm::IChannel * channelHandler, - string &msg) { - agora::rtm::IMessage* rtmMessage = rtmService_->createMessage(); - rtmMessage->setText(msg.c_str()); - channelHandler->sendMessage(rtmMessage); - rtmMessage->release(); - } -private: - std::unique_ptr eventHandler_; - std::unique_ptr channelEvent_; - std::shared_ptr rtmService_; -}; - -int main(int argc, const char * argv[]) { - // Select the number of instances to create. - int count; - while (true) { - cout << "Please input the number which indicates how many instances " - << "will be created... Limit 3 instances for this demo" << endl; - string input; - getline(std::cin, input); - try { - count = std::stoi(input); - } - catch (...) { - cout << "invalid input" << endl; - continue; - } - if (count <= 0 || count > 3) { - cout << "valid range: 1~3" << endl; - continue; - } - break; - } - // Define feature list for you to choose. - std::vector> FunctionList; - std::vector loginStatus; - for (int i = 0; i < count; i++) { - std::unique_ptr tmp; - tmp.reset(new Quickstart()); - FunctionList.push_back(std::move(tmp)); - loginStatus.push_back(false); - } - int index; - - // Select the created instance - while (true) { - cout << "Please input which instance you want to use range[1,3]" - << endl; - string input_idx; - getline(std::cin, input_idx); - try { - index = std::stoi(input_idx); - } - catch (...) { - cout << "invalid input" << endl; - continue; - } - if (index < 1 || index > count) { - cout << "invalid index range" << endl; - continue; - } - - // One-to-one chat, group chat, or exit - while (true) { - if (!loginStatus[index - 1]) { - if (!FunctionList[index - 1]->login()) - continue; - loginStatus[index - 1] = true; - } - cout << "1: peer to peer chat\n" - << "2: group chat\n" - << "3: logout" - << endl; - cout << "please input your choice: " << endl; - string input_choice; - getline(std::cin, input_choice); - int choice = 0; - try { - choice = std::stoi(input_choice); - } - catch (...) { - cout << "invalid input" << endl; - continue; - } - if (choice == 1) { - cout << "please input your destination user id" << endl; - string dst; - getline(std::cin, dst); - FunctionList[index - 1]->p2pChat(dst); - continue; - } - else if (choice == 2) { - cout << "please input your channel id" << endl; - string channel; - getline(std::cin, channel); - FunctionList[index - 1]->groupChat(channel); - continue; - } - else if (choice == 3) { - FunctionList[index - 1]->logout(); - loginStatus[index - 1] = false; - break; - } - else { - continue; - } - } - - // Quit the program - cout << "Quit the program? yes/no" << endl; - string input_quit; - getline(std::cin, input_quit); - if (input_quit.compare("yes") == 0) { - break; - } - } - - exit(0); -} - -``` - -## Test your app - -1. Press **<Ctrl> + shift + B** to generate the solution. -2. Copy the `.dll` file in the SDK to the folder where the generated `.exe` file is located. -3. Press **<Ctrl> + F5** to run the solution. - -![](https://web-cdn.agora.io/docs-files/1624266224141) - -## Considerations -- The Agora supports creating multiple IRtmService instances that are independent of each other. - -- To send and receive peer-to-peer or channel messages, ensure that you have successfully logged in the Agora (you have received onLoginSuccess. - -- To use any of the channel features, you must first call the createChannel method to create a channel instance. -- You can create multiple channel instances for each IRtmService instance, but you can only join a maximum of 20 channels at the same time. The `channelId` parameter needs to be channel-specific. - -- When you leave a channel and do not want to join it again, you can call the release method to release all resources used by the channel instance. - -- You cannot reuse a received IMessage instance. - -## Next steps - -Generating a token by hand is not helpful in a production context. [Authenticate Your Users with Tokens](../develop/authentication-workflow) shows you how to start real-time messaging with a token that you retrieve from your server. - -## See also - -### Sample project - -Agora also provides an open-source [sample project](https://github.com/AgoraIO/Signaling/tree/master/Agora-Signaling-Tutorial-Windows) on GitHub for your reference. - - - diff --git a/shared/signaling/limitations/index.mdx b/shared/signaling/limitations/index.mdx index 668b0a615..8fce423be 100644 --- a/shared/signaling/limitations/index.mdx +++ b/shared/signaling/limitations/index.mdx @@ -6,7 +6,95 @@ import Unity from './unity.mdx'; import Web from './web.mdx'; import Windows from './windows.mdx'; +## API call limit +Unless otherwise specified below, limit the API call frequency by a single client to 20 calls per second. If the number of calls per second exceeds 20, some calls are ignored by the SDK. If you need to call more APIs per second, contact [rtm@agora.io](mailto:rtm@agora.io). + +### General + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Number of projects in an account | 1000 | N/A | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of client instances | 1 | 1 | Attempts to create multiple instances fail. | +| Number of message channels per app ID | Unlimited | N/A | Channel resources are public, users can take them as needed. | +| Number of stream channels per app ID | Unlimited | N/A | Channel resources are public, users can take them as needed. | +| User ID length | 64 ASCII characters | 64 ASCII characters | Exceeding the soft limit produces an error. | + +### Message channel + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Number of messages per second in a channel | 30 messages/sec | 60 messages/sec | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of subscribers per channel | Unlimited | N/A | | +| Number of publishers per channel | Unlimited | N/A | | +| Number of subscribed channels per client | 50 | N/A | Exceeding the soft limit produces an error. | +| Message packet size | 32 KB | 32 KB | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Channel name length | 64 ASCII characters | 64 ASCII characters | Exceeding the soft limit produces an error. | +| Custom message type length | 32 ASCII characters | 32 ASCII characters | Exceeding the soft limit produces an error. | + +### Stream channel + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Number of created channels per client | Unlimited | N/A | | +| Number of joined channels per client | 100 | N/A | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of users per channel | 1000 | N/A | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of topics per channel | Unlimited | N/A | | +| Channel name length | 64 ASCII characters | 64 ASCII characters | Exceeding the soft limit produces an error. | + +### Topic + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Number of topics joined by a client in a channel | 8 | 8 | Exceeding the soft limit produces an error. | +| Number of messages published by a client in a topic per second | 120 messages/sec | 200 messages/sec | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io).| +| Number of topics subscribed to by a client in a channel | 50 | 50 | Exceeding the soft limit produces an error. | +| Number of users subscribed to a topic by a client | 64 | 64 | A single client can subscribe up to 64 user IDs to a single topic. Exceeding the soft limit produces an error. | +| Number of publishers in a topic | Unlimited | N/A | | +| Topic name length | 8 ASCII characters | 8 ASCII characters | The topic name length will be extended to 64 ASCII characters in future releases. | +| Message packet size | 32 KB | 32 KB | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Custom message type length | 32 ASCII characters | 32 ASCII characters | Exceeding the soft limit produces an error. | + +### Presence + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Presence timeout | 10 seconds - 300 seconds. Defaults to 300 seconds. | N/A | When the set timeout value is exceeded, the SDK matches the closest boundary value. For example, if you set presence timeout to 400 seconds, the actual application time is 300 seconds. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of temporary user state key/value pairs | 32 pairs | 32 pairs | Exceeding the soft limit produces an error. | +| Number of temporary user states cached before joining the channel | 100 | 100 | Exceeding the soft limit produces an error. | + +### Storage + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Metadata item key length | 32 ASCII characters | N/A | | +| Number of metadata sets per user or channel | 1 | 1 | Each channel and each user can only have one set of channel or user metadata, respectively. | +| Number of items per channel metadata or user metadata set | Unlimited | N/A | | +| Storage space per channel or user metadata set | 64KB | N/A | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Storage space per metadata item | 64KB | N/A | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Channel metadata API call frequency by a single client | 10 times/sec | 20 times/sec | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| User metadata API call frequency by a single client | 10 times/sec | 20 times/sec | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of channel metadata sets per app ID | 1 million | N/A | | +| Number of user metadata sets per app ID | 1 million | N/A | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | + +### Lock + +| Item | Soft limit | Hard limit | Comments | +|:---:|:---:|:---:|:---:| +| Number of locks per channel | 32 | N/A | To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Number of locked locks per client | Unlimited | N/A | | +| Lock TTL (Time to live) | 10 seconds - 300 seconds | 10 seconds - 300 seconds | When a user leaves a channel or disconnects, the lock held by that user is automatically released after the set time. When the set value is exceeded, the SDK matches the closest boundary value. For example, if you set lock TTL to 400 seconds, the actual application time is 300 seconds. | +| Lock length | 64 ASCII characters | 64 ASCII characters | Exceeding the soft limit produces an error. | +| Number of locks per app ID | 1 million | N/A | Exceeding the soft limit produces an error. To change the limit, contact [rtm@agora.io](mailto:rtm@agora.io). | +| Lock acquisition API call frequency | 10 times/sec | N/A | | + +## String size + +The maximum size of the response in a call invitation is 8 KB. + +## Unicode support + +Supports channel and peer-to-peer messages, invitation content, and invitation response in UTF-8 only. diff --git a/shared/signaling/limitations/web.mdx b/shared/signaling/limitations/web.mdx index 5270990a6..3c97a67b5 100644 --- a/shared/signaling/limitations/web.mdx +++ b/shared/signaling/limitations/web.mdx @@ -1,40 +1,4 @@ -## API call limit - -The call limit is for one RtmClient instance. If an operation corresponds to multiple methods, the number of the method calls of an operation equals the sum of the method calls of all corresponding methods in a specific time frame. - -
We do not recommend increasing the call limit by creating multiple RtmClient instances.
- -| Function | Method | Call limit | -| ----------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------ | -| Log in to the Agora | login | Two calls per second | -| Retrieve member count of specified channels | getChannelMemberCount | One call per second | -| Join the same channel each time1 | join | 50 calls every three seconds | -| Join a different channel each time1 | join | Two calls every five seconds | -| Send messages |
  • sendMessageToPeer
  • sendMessage
  • | 180 calls every three seconds | -| Retrieve a member list of the channel | getMembers | Five calls every two seconds | -| Renew the Token | renewToken | Two calls per second | -| Query the online status of the specified users | queryPeersOnlineStatus | 10 calls every five seconds | -| Set user attributes |
  • setLocalUserAttributes
  • addOrUpdateLocalUserAttributes
  • deleteLocalUserAttributesByKeys
  • clearLocalUserAttributes
  • | 10 calls every five seconds | -| Get user attributes |
  • getUserAttributes
  • getUserAttributesByKeys
  • | 40 calls every five seconds | -| Set channel attributes |
  • setChannelAttributes
  • addOrUpdateChannelAttributes
  • deleteChannelAttributesByKeys
  • clearChannelAttributes
  • | 10 calls every five seconds | -| Get channel attributes |
  • getChannelAttributes
  • getChannelAttributesByKeys
  • | 10 calls every five seconds | - - -## String size - -- The maximum size of a peer-to-peer or channel message is 32 KB. See RtmMessage.text. -- The maximum size of the response in a call invitation is 8 KB. See RemoteInvitation.response - -## Supported browsers - -See [Supported Browsers](../overview/supported-platforms). - -## Unicode support - -Supports channel and peer-to-peer messages, invitation content, and invitation response in UTF-8 only. - -
    \ No newline at end of file diff --git a/shared/signaling/metadata-sdk.mdx b/shared/signaling/metadata-sdk.mdx new file mode 100644 index 000000000..cab5d8ca9 --- /dev/null +++ b/shared/signaling/metadata-sdk.mdx @@ -0,0 +1,19 @@ +--- +title: 'Metadata SDK' +sidebar_position: 8 +type: docs +description: > + Easy-to-use, serverless storage for user and channel data +--- +import MetadataAPI from '@docs/shared/signaling/metadata-sdk/index.mdx'; + +export const toc = [{}] + +Metadata provides easy-to-use, serverless storage for user and channel data you need to build innovative, reliable, +scalable applications. Use Metadata SDK to easily store metadata about the users and channels in your app without +setting up your own databases. + +Signalling triggers events when metadata is set or removed. Your app can receive these events in real +time in order to update the front-end accordingly. + + diff --git a/shared/signaling/metadata-sdk/android.mdx b/shared/signaling/metadata-sdk/android.mdx new file mode 100644 index 000000000..416cbbed7 --- /dev/null +++ b/shared/signaling/metadata-sdk/android.mdx @@ -0,0 +1,753 @@ + + +
    +## User metadata + +Creates an `RtmMetadataItem` instance. + +**Method** + +```javascript + public class RtmMetadataItem +``` + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("mode", "emo"); +``` + +**Response** + +Returns a `RtmMetadataItem` instance. `RtmMetadataItem` is a basic unit item of a `UserMetadata` and + `ChannelMetadata`. It contains the following properties: + +| Property Name | Type | Description | +| --------------------------------- | -------- | ------------------------------------------------------------------- | +| `void setKey(String key)` | function | Set key for current `RtmMetadataItem` | +| `String getKey()` | function | Get key for current `RtmMetadataItem` | +| `void setValue(String value)` | function | Set value for current `RtmMetadataItem` | +| `String getValue()` | function | Get value for current `RtmMetadataItem` | +| `void setRevision(long revision)` | function | Set revision for current `RtmMetadataItem` | +| `long getRevision()` | function | Get revision for current `RtmMetadataItem` | +| `long getLastUpdateTs()` | function | Get updated time for current `RtmMetadataItem` | +| `String getAuthorUserId()` | function | Get the uid of who update this record for current `RtmMetadataItem` | + +#### Get user metadata + + + +Gets all metadataItems of a specified user. + +**Method** + +```java +void getUserMetadata(String userId, ResultCallback resultCallback) +``` + +| Parameter | Type | Required | Default | Description | +|:----------------:|:--------:|:--------:|:-------:|:-----------------------:| +| `userId` | String | yes | | Unique user identifier. | +| `resultCallback` | function | yes | | callback function | + +**Basic Use** + +```java +mRtmClient.getUserMetadata("Tony", new ResultCallback(){ + @Override + public void onSuccess(RtmMetadata userMetadata){ + // process success result! + } + @Override + public void onFailure(int errorInfo){ + // process failure result! + } +}); +``` + +**Response** + +Returns a type `RtmMetadata` for the specific `uid` which contains the following properties: + +| Property Name | Type | Description | +|:---------------:|:------------------------:|:------------------------------------------------------------------------------------------------------------------------------- | +| `items` | `List` | `RtmMetadataItem` type array which contains a single Key-Value metadata item for user, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `majorRevision` | number | The major revision for this user metadata | + + + + + + +#### Set user metadata + + + +Set the local user’s metadata. + +**Method** + +```java +void setLocalUserMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:------------------------:|:------------------------------------------------------------------------------------------------------------------------------ | +| `items` | `List` | `RtmMetadataItem` type list which contains a single Key-Value metadata item for user, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + + +`RtmMetadataOptions` is a set of optional properties for operations, it contains the following properties: + +| Property Name | Type | Description | +| -------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `majorRevision` | number | Revison control parametes. when the `majorRevision` you supplied is as same as the one in the storage, this operation will success. | +| `enableRecordTs` | bool | When it is set to `true`, the final `RtmMetadataItem` will record the updating time automatically | +| `enableRecordUserId` | bool | When it is set to `true`, the final `RtmMetadataItem` will record who have updated this item automatically | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("mode", "emo"); +RtmMetadataItem item2 = new RtmMetadataItem("gender", "male"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmClient.setLocalUserMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "setLocalUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "setLocalUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> caution: This operation will reset all current meatadata and set a new one. + +#### Add user metadata + + + +Adds metadata items to local user’s metadata. + +**Method** + +```javascript +void addLocalUserMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback); +``` + +| Property Name | Type | Description | +|:----------------:|:-------------------------:|:------------------------------------------------------------------------------------------------------------------------------- | +| `items` | List\< `RtmMetadataItem` > | `RtmMetadataItem` type array which contains a single Key-Value metadata item for user, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("mode", "emo"); +RtmMetadataItem item2 = new RtmMetadataItem("gender", "male"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmClient.addLocalUserMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "addLocalUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "addLocalUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution: This operation will add new metadata items for current user. It will report errors if the key of new `RtmMetadataItem` has already existed in the user metadata. + +#### Clear user metadata + + + +Delete all the local user’s metadata items. + +**Method** + +```java +void clearLocalUserMetadata(RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:--------------------:|:--------------------------------------------------------------------------------------------------- | +| `options` | `RtmMetadataOptions` | add optional propeties for current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmClient.clearLocalUserMetadata(options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "clearLocalUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "clearLocalUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution: This operation will clean all user metadata. + +#### Update user metadata + + + +Update the local user’s metadata items. + +**Method** + +```java +void updateLocalUserMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:------------------------:|:------------------------------------------------------------------------------------------------------------------------------- | +| `items` | `List`| `RtmMetadataItem` type array which contains a single Key-Value metadata item for user, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("mode", "emo"); +RtmMetadataItem item2 = new RtmMetadataItem("gender", "male"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmClient.updateLocalUserMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "updateLocalUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "updateLocalUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution : This operation can only valid for updating the existing metadata items, or it will report errors. + +#### Delete user metadata + + + +Delete the local user’s metadata items. + +**Method** + +```java +void deleteLocalUserMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:-------------------------:|:------------------------------------------------------------------------------------------------------------------------------- | +| `items` | List\< `RtmMetadataItem` > | `RtmMetadataItem` type array which contains a single Key-Value metadata item for user, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("mode", ""); +RtmMetadataItem item2 = new RtmMetadataItem("gender", ""); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmClient.deleteLocalUserMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "deleteLocalUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "deleteLocalUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution:This operation will always excute regardless of the existing of metadata items + +#### Subscribe user metadata + + + +Subscribe to user metadata update events for a specific user. + +**Method** + +```java +void subscribeUserMetadata(String userId, ResultCallback resultCallback); +``` + +| Parameter | Type | Required | Default | Description | +|:----------------:|:--------:|:--------:|:-------:|:-----------------------:| +| `userid` | String | yes | | Unique user identifier. | +| `resultCallback` | function | yes | | callback function | + +**Basic Use** + +```java +mRtmClient.subscribeUserMetadata("Tony", new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "subscribeUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "subscribeUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +#### Unsubscribe user metadata + + + +Unsubscribe to user metadata update events for a specific user. + +**Method** + +```java +void unsubscribeUserMetadata(String userId, ResultCallback resultCallback) +``` + +| Parameter | Type | Required | Default | Description | +|:----------------:|:--------:|:--------:|:-------:|:-----------------------:| +| `userId` | String | yes | | Unique user identifier. | +| `resultCallback` | function | yese | | callback function | + +**Basic Use** + +```java +mRtmClient.unsubscribeUserMetadata("Tony", new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "unsubscribeUserMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "unsubscribeUserMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +#### User metadata event + + + +it will occur when user's metadata are updated(`Add`/`Set`/`Clear`/`Update`/`Delete`), You need to complete this procedure yourself, and then you can handle this event when you are subscribing user's metadata. + +**Method** + +```java +void onUserMetadataUpdated(String userId, RtmMetadata data) +``` + +**Basic Use** + +```java +class RtmClientListener implements RtmClientListener { + //.. + @Override + public void onUserMetadataUpdated(String userId, RtmMetadata data) { + visualLog_CALLBACK("onUserMetadataUpdated, userId: " + userId); + for (RtmMetadataItem item: data.items) { + visualLog("Item key: " + item.getKey() + ", value: " + item.getValue() + + ", revision: " + item.getRevision() + ", ts: " + item.getLastUpdateTs() + + ", uid: " + item.getAuthorUserId()); + } + } + //.. +} + +rtmClient = RtmClient.createInstance(context, appId, new RtmClientListener()); +``` + +**Response** + +When this event occurs, you can recieve a uid which indicating whose metadata have changed and a type `RtmMetadata` for the user which contains the following properties: + +| Property Name | Type | Description | +|:---------------:|:--------------------------:| -------------------------------------------------------------------------------- | +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single Key-Value metadata item for user | +| `majorRevision` | number | The major revision for this user metadata | + +> **Caution**: It should be noted that the returned data contains the full amount of data of the current user, `Add`/`Set`/`Clear`/`Update`/`Delete` operation all will trigger this event, and you cannot distinguish which operation caused the current event. Need more features, you can use our new version 2.1. + +## Channel metadata + +#### Set channel metadata + + + +set the metadata of the channel. + +**Method** + +```java +void setChannelMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:-----------------------:|:---------------------------------------------------------------------------------------------------------------------------------- | +| `items` | List\<`RtmMetadataItem`> | `RtmMetadataItem` type array which contains a single Key-Value metadata item for channel, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +The `RtmMetadataOptions` is a set of optional properties for operations, it contains the following properties: + +| Property Name | Type | Description | +| -------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `majorRevision` | number | Revison control parametes. when the `majorRevision` you supplied is as same as the one in the storage, this operation will success. | +| `enableRecordTs` | bool | When it is set to `true`, the final `RtmMetadataItem` will record the updating time automatically | +| `enableRecordUserId` | bool | When it is set to `true`, the final `RtmMetadataItem` will record who have updated this item automatically | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("Announcement", "Welcome to RTM"); +RtmMetadataItem item2 = new RtmMetadataItem("Channel_type", "Public"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmChannel.setChannelMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "setChannelMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "setChannelMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> caution: This operation will `reset` all current meatadata of channel and set a new one for channel. + +#### Add channel metadata + + + +Add new metadata items to the channel. + +**Method** + +```java +void addChannelMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:-------------------------:|:---------------------------------------------------------------------------------------------------------------------------------- | +| `items` | List\<(`RtmMetadataItem` > | `RtmMetadataItem` type array which contains a single Key-Value metadata item for channel, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("Announcement", "Welcome to RTM"); +RtmMetadataItem item2 = new RtmMetadataItem("Channel_type", "Public"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmChannel.addChannelMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "addChannelMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "addChannelMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution: This operation will add new metadata items for current channel. It will report errors if the key of new `RtmMetadataItem` has already existed in the channel metadata. + +#### Clear channel metadata + + + +delete all metadata items of the channel. + +**Method** + +```java +clearChannelMetadata(RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:--------------------:|:------------------------------------------------------------------------------------------------------ | +| `options` | `RtmMetadataOptions` | add optional propeties for current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmChannel.clearChannelMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "clearChannelMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "clearChannelMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution: This operation will clean all metadata of the specific channel. + +#### Update channel metadata + + + +Update metadata items of the channel. + +**Method** + +```java +updateChannelMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:------------------------:|:---------------------------------------------------------------------------------------------------------------------------------- | +| `items` | `List`| `RtmMetadataItem` type array which contains a single Key-Value metadata item for channel, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("Announcement", "Welcome to RTM"); +RtmMetadataItem item2 = new RtmMetadataItem("Channel_type", "Public"); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmChannel.updateChannelMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "updateChannelMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "updateChannelMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution : This operation can only valid for updating the existing metadata items, or it will report errors. + +#### Delete channel metadata + + + +delete metadata items of the channel. + +**Method** + +```java +void deleteChannelMetadata(List items, RtmMetadataOptions options, ResultCallback resultCallback) +``` + +| Property Name | Type | Description | +|:----------------:|:-----------------------:|:---------------------------------------------------------------------------------------------------------------------------------- | +| `items` | `List` | `RtmMetadataItem` type array which contains a single Key-Value metadata item for channel, see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | add optional propeties for current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | +| `resultCallback` | function | callback function | + +**Basic Use** + +```java +RtmMetadataItem item1 = new RtmMetadataItem("Announcement", ""); +RtmMetadataItem item2 = new RtmMetadataItem("Channel_type", ""); +ArrayList metadata = new ArrayList(); +metadata.add(item1); +metadata.add(item2); +RtmMetadataOptions options = new RtmMetadataOptions(-1, ture, false); +mRtmChannel.deleteChannelMetadata(metadata, options, new ResultCallback() { + @Override + public void onSuccess(Void unused) { + visualLog_CALLBACK( "deleteChannelMetadata onSuccess"); + } + + @Override + public void onFailure(ErrorInfo errorInfo) { + visualLog_CALLBACK( "deleteChannelMetadata onFailure, error: " + errorInfo.toString()); + } +}); +``` + +**Response** + +None + +> Caution:This operation will always excute regardless of the existing of metadata items + +#### Get channel metadata + + + +get all metadata items of the channel. + +**Method** + +```javascript +getChannelMetadata(ResultCallback resultCallback) +``` + +| Parameter | Type | Required | Default | Description | +|:----------------:|:--------:|:--------:|:-------:|:-----------------:| +| `resultCallback` | function | yes | | callback function | + +**Basic Use** + +```java +mRtmChannel.getChannelMetadata( new ResultCallback(){ + @Override + public void onSuccess(RtmMetadata channelMetadata){ + // process success result! + } + @Override + public void onFailure(int errorInfo){ + // process failure result! + } +}); +``` + +**Response** + +Returns a type `RtmMetadata` for the specific `channel` which contains the following properties: + +| Property Name | Type | Description | +| --------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `items` | List< `RtmMetadataItem` > | `RtmMetadataItem` type array which contains a single Key-Value metadatafor channel, see `[RtmMetadataIte](1)` for more information | +| `majorRevision` | number | The major revision for this channel metadata | + +> **Caution**: If the specific `channel` have not set any user metadata yet, this operation will return a empty {}. + +#### Listen channel metadata update event + +When you join channel ,you will automatically Listen the Channel metadata Update Event + +#### Channel metadata event + +This occurs when channel's metadata are updated, You need to complete this procedure yourself, and then you can handle + this event when you are in the channel + +**Method** + +```javascript +void onMetadataUpdated(RtmMetadata data) +``` + +**Basic Use** + +```java +private RtmChannelListener rtmChannelListener = new RtmChannelListener(){ + + @Override + public void onMetadataUpdated(RtmMetadata data) { + visualLog_CALLBACK("onMetadataUpdated"); + for (RtmMetadataItem item: data.items) { + visualLog( "Item key: " + item.getKey() + ", value: " + item.getValue() + + ", revision: " + item.getRevision() + ", ts: " + item.getLastUpdateTs() + + ", userId: " + item.getAuthorUserId()); + } + } +}; + +RtmChannel rtmChannel = mRtmClient.createChannel(channelId.toString(), rtmChannelListener); +``` + +**Response** + +When this event occurs, you can recieve a type `RtmMetadata` for the specific `channel` which contains the following properties: + +| Property Name | Type | Description | +|:---------------:|:-------------------------:| ----------------------------------------------------------------------------------- | +| `items` | List\< `RtmMetadataItem` > | `RtmMetadataItem` type array which contains a single Key-Value metadata itemfor channel | +| `majorRevision` | number | The major revision for this channel metadata | + +> **Caution**: It should be noted that the returned data contains the full amount of data of the current channel, `Add`/`Set`/`Clear`/`Update`/`Delete` operation all will trigger this event, and you cannot distinguish which operation caused the current event. Need more features, you can use our new version 2.1. + +
    diff --git a/shared/signaling/metadata-sdk/index.mdx b/shared/signaling/metadata-sdk/index.mdx new file mode 100644 index 000000000..1077dbc4f --- /dev/null +++ b/shared/signaling/metadata-sdk/index.mdx @@ -0,0 +1,15 @@ +import Android from './android.mdx'; +import Ios from './ios.mdx'; +import Linux from './linux.mdx'; +import Macos from './macos.mdx'; +import Unity from './unity.mdx'; +import Web from './web.mdx'; +import Windows from './windows.mdx'; + + + + + + + + \ No newline at end of file diff --git a/shared/signaling/metadata-sdk/ios.mdx b/shared/signaling/metadata-sdk/ios.mdx new file mode 100644 index 000000000..b7e1a68c5 --- /dev/null +++ b/shared/signaling/metadata-sdk/ios.mdx @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/shared/signaling/metadata-sdk/linux.mdx b/shared/signaling/metadata-sdk/linux.mdx new file mode 100644 index 000000000..f665e017e --- /dev/null +++ b/shared/signaling/metadata-sdk/linux.mdx @@ -0,0 +1,3 @@ + +Metadata SDK is not currently available for this platform. + diff --git a/shared/signaling/metadata-sdk/macos.mdx b/shared/signaling/metadata-sdk/macos.mdx new file mode 100644 index 000000000..c57b76049 --- /dev/null +++ b/shared/signaling/metadata-sdk/macos.mdx @@ -0,0 +1,4 @@ + + + Metadata SDK is not currently available for this platform. + diff --git a/shared/signaling/metadata-sdk/unity.mdx b/shared/signaling/metadata-sdk/unity.mdx new file mode 100644 index 000000000..f5a2d874f --- /dev/null +++ b/shared/signaling/metadata-sdk/unity.mdx @@ -0,0 +1,4 @@ + + + Metadata SDK is not currently available for this platform. + diff --git a/shared/signaling/metadata-sdk/web.mdx b/shared/signaling/metadata-sdk/web.mdx new file mode 100644 index 000000000..520f742c5 --- /dev/null +++ b/shared/signaling/metadata-sdk/web.mdx @@ -0,0 +1,806 @@ + + + +### User metadata + +Creates an `RtmMetadataItem` instance. + +**Method** + +```javascript + createMetadataItem(): RtmMetadataItem; +``` + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("mode"); +item1.setValue("mode"); +item2.SetKey("gender"); +item2.setValue("male"); +``` + +**Response** + +Returns a `RtmMetadataItem` instance. `RtmMetadataItem` is a basic unit item of `UserMetadata` and `ChannelMetadata`. + It contains the following properties: + +| Property Name | Type | Description | +| -------------------------------------- | -------- | ------------------------------------------------------------------- | +| `setKey(key: string): void` | function | Set key for the current `RtmMetadataItem` | +| `getKey(): string` | function | Get key for the current `RtmMetadataItem` | +| `setValue(value: string\| null): void` | function | Set value for the current `RtmMetadataItem` | +| `getValue(): string\| null` | function | Get the value for the current `RtmMetadataItem` | +| `setRevision(revision: number): void` | function | Set revision for the current `RtmMetadataItem` | +| `getRevision(): number` | function | Get revision for the current `RtmMetadataItem` | +| `getUpdateTs(): number` | function | Get updated time for the current `RtmMetadataItem` | +| `getAuthorUserId(): string` | function | Get the uid of who update this record for the current `RtmMetadataItem` | + +#### Get user metadata + +Get the metadata for a specified user. + +**Method** + +```javascript +getUserMetadata(uid: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +|:---------:|:------:|:--------:|:-------:|:-----------------------:| +| uid | string | yes | | Unique user identifier. | + +**Basic Use** + +```javascript +try{ + const rtmMetadata = await getUserMetadata("Tony"); + console.log(rtmMetadata); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +Returns a `RtmMetadata` object for the specific `uid`. The returned object contains the following properties: + +| Property Name | Type | Description | +|:---------------:|:--------------------------:|:--------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single Key-Value metadata item for a user | +| `majorRevision` | number | The major revision for this user metadata | + +The `RtmMetadataItem` is a basic unit item of a UserMetadata, it contains the following properties: + +| Property Name | Type | Description | +|:---------------------------------------:|:--------:|:-------------------------------------------------------------------:| +| `setKey(key: string): void` | function | Set key for the current `RtmMetadataItem` | +| `getKey(): string` | function | Get key for the current `RtmMetadataItem` | +| `setValue(value: string \| null): void` | function | Set value for the current `RtmMetadataItem` | +| `getValue(): string \| null` | function | Get the value for the current `RtmMetadataItem` | +| `setRevision(revision: number): void` | function | Set revision for the current `RtmMetadataItem` | +| `getRevision(): number` | function | Get revision for the current `RtmMetadataItem` | +| `getUpdateTs(): number` | function | Get updated time for the current `RtmMetadataItem` | +| `getAuthorUserId(): string` | function | Get the uid of who update this record for the current `RtmMetadataItem` | + +If no user metadata is set for the specific `uid`, this operation returns an empty {}. + +#### Set user metadata + +Set the local user’s metadata. + +**Method** + +```javascript +setLocalUserMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:-------------:|:-------------:| +|`items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item + for a user,see [`RtmMetadataItem`](#RtmMetadataItem) for more information. | +| `options` | `RtmMetadataOptions` | Add optional properties to the current user metadata, see + [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | + + +The `RtmMetadataOptions` is a set of optional properties for operations, it contains the following properties: + +| Property Name | Type | Description | +| -------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `majorRevision` | number | Revison control parametes. when the `majorRevision` you supplied is as same as the one in the storage, this operation will success. | +| `enableRecordTs` | bool | When it is set to `true`, the final `RtmMetadataItem` records the updating time + automatically | +| `enableRecordUserId` | bool | When it is set to `true`, the final `RtmMetadataItem` records who have updated + this item automatically | + + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("mode"); +item1.setValue("mode"); +item2.SetKey("gender"); +item2.setValue("male"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await setLocalUserMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> caution: This operation will reset all current metadata and set a new one. + +#### Add user metadata + +Adds metadata items to the local user’s metadata. + +**Method** + +```javascript +addLocalUserMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:-------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a user,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current user metadata, see + [`RtmMetadataOptions`](#RtmMetadataOptions) for more information | + + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("mode"); +item1.setValue("mode"); +item2.SetKey("gender"); +item2.setValue("male"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await addLocalUserMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution: This operation adds new metadata items for the current user. Reports errors if the key of new + `RtmMetadataItem` has already existed in the user metadata. + +#### Clear user metadata + +Delete all the local user’s metadata items. + +Method + +```javascript +clearLocalUserMetadata(options?: RtmMetadataOptions): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------:|:---------------------------------------------------------------------------------------------------:| +| `options` | `RtmMetadataOptions` | Add optional properties to the current user metadata, see + [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +cosnt metadataOption = { + majorRevision: 1234567; +}; + +try{ + await clearLocalUserMetadata(metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution: This operation will clean all user metadata. + +#### Update user metadata + + + +Update the local user’s metadata items. + +Method + +```javascript +updateLocalUserMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:-------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a user,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("mode"); +item1.setValue("mode"); +item2.SetKey("gender"); +item2.setValue("male"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await updateLocalUserMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution : This operation can only valid for updating the existing metadata items, or it will report errors. + +#### Delete user metadata + + + +Delete the local user’s metadata items. + +**Method** + +```javascript +deleteLocalUserMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:-------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | An `RtmMetadataItem` type array which contains a single key-value + metadata item for a user,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current user metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("mode"); +item2.SetKey("gender"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await deleteLocalUserMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution:This operation will always excute regardless of the existing of metadata items + +#### Subscribe user metadata + + + +Subscribe to user metadata update events for a specific user. + +**Method** + +```javascript +subscribeUserMetadata(uid: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +|:---------:|:------:|:--------:|:-------:|:-----------------------:| +| uid | string | yes | | Unique user identifier. | + +**Basic Use** + +```javascript +try{ + await subscribeUserMetadata("Tony"); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +#### Unsubscribe user metadata + + + +Unsubscribe to user metadata update events for a specific user. + +**Method** + +```javascript +unsubscribeUserMetadata(uid: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +|:---------:|:------:|:--------:|:-------:|:-----------------------:| +| uid | string | yes | | Unique user identifier. | + +**Basic Use** + +```javascript +try{ + await unsubscribeUserMetadata("Tony"); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +#### User metadata event + + + +it will occur when user's metadata are updated(`Add`/`Set`/`Clear`/`Update`/`Delete`), You need to complete this procedure yourself, and then you can handle this event when you are subscribing user's metadata. + +**Method** + +```javascript +UserMetaDataUpdated: (uid: string, data: RtmMetadata) => void; +``` + +**Basic Use** + +```javascript +UserMetaDataUpdated: (uid: string, data: RtmMetadata) => { + // handle the event +} +``` + +**Response** + +When this event occurs, you can recieve a uid which indicating whose metadata have changed and a type `RtmMetadata` for the user which contains the following properties: + +| Property Name | Type | Description | +|:---------------:|:--------------------------:| -------------------------------------------------------------------------------- | +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a user | +| `majorRevision` | number | The major revision for this user metadata | + +The `RtmMetadataItem` is a basic unit item of a `userMetadata`, it contains the following properties: + +| Property Name | Type | Description | +|:-------------------------------------:|:--------:| ------------------------------------------------------------------- | +| `setKey(key: string): void` | function | Set key for the current `RtmMetadataItem` | +| `getKey(): string` | function | Get key for the current `RtmMetadataItem` | +| `setValue(value: string\|null): void` | function | Set Value for the current `RtmMetadataItem` | +| `getValue(): string \| null` | function | Get Value for the current `RtmMetadataItem` | +| `setRevision(revision: number): void` | function | Set revision for the current `RtmMetadataItem` | +| `getRevision(): number` | function | Get revision for the current `RtmMetadataItem` | +| `getUpdateTs(): number` | function | Get updated time for the current `RtmMetadataItem` | +| `getAuthorUserId(): string` | function | Get the uid of who update this record for the current `RtmMetadataItem` | + +> **Caution**: It should be noted that the returned data contains the full amount of data of the current user, `Add`/`Set`/`Clear`/`Update`/`Delete` operation all will trigger this event, and you cannot distinguish which operation caused the current event. Need more features, you can use our new version 2.1. + +## Channel metadata + +#### Set channel metadata + + + +set the metadata of the channel. + +**Method** + +```javascript +setChannelMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:----------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +The `RtmMetadataOptions` is a set of optional properties for operations, it contains the following properties: + +| Property Name | Type | Description | +| -------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `majorRevision` | number | Revison control parametes. when the `majorRevision` you supplied is as same as the one in the storage, this operation will success. | +| `enableRecordTs` | bool | When it is set to `true`, the final `RtmMetadataItem` will record the updating time automatically | +| `enableRecordUserId` | bool | When it is set to `true`, the final `RtmMetadataItem` will record who have updated this item automatically | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("Announcement"); +item1.setValue("Welcome to RTM"); +item2.SetKey("Channel_type"); +item2.setValue("Public"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await setChannelMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> caution: This operation will `reset` all current metadata of channel and set a new one for a channel. + +#### Add channel metadata + + + +Add new metadata items to the channel. + +**Method** + +```javascript +addChannelMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:----------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("Announcement"); +item1.setValue("Welcome to RTM"); +item2.SetKey("Channel_type"); +item2.setValue("Public"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await addChannelMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution: This operation adds new metadata items for the channel. Reports errors if the key of new `RtmMetadataItem` already exists in the channel metadata. + +#### Clear channel metadata + +Delete all metadata items of the channel. + +**Method** + +```javascript +clearChannelMetadata(options?: RtmMetadataOptions): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------:|:------------------------------------------------------------------------------------------------------:| +| `options` | `RtmMetadataOptions` | Add optional properties to the current channel metadata, see + [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +cosnt metadataOption = { + majorRevision: 1234567; +}; + +try{ + await clearChannelMetadata(metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution: This operation will clean all metadata of the specific channel. + +#### Update channel metadata + + + +Update metadata items of the channel. + +**Method** + +```javascript +updateChannelMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:----------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("Announcement"); +item1.setValue("Welcome to RTM!"); +item2.SetKey("Channel_Type"); +item2.setValue("Public"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await updateChannelMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution : This operation can only valid for updating the existing metadata items, or it will report errors. + +#### Delete channel metadata + + + +delete metadata items of the channel. + +**Method** + +```javascript +deleteChannelMetadata( + items: RtmMetadataItem[], + options?: RtmMetadataOptions + ): Promise; +``` + +| Property Name | Type | Description | +|:-------------:|:--------------------------:|:----------------------------------------------------------------------------------------------------------------------------------:| +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel,see [`RtmMetadataItem`](#RtmMetadataItem) for more information | +| `options` | `RtmMetadataOptions` | Add optional properties to the current channel metadata, see [`RtmMetadataOptions`](#RtmMetadataOptions)for more information | + +**Basic Use** + +```javascript +const item1 = createMetadataItem(); +const item2 = createMetadataItem(); +item1.setKey("Announcement"); +item2.SetKey("Channel_Type"); +cosnt metadataOption = { + majorRevision: 1234567; + enableRecordTs: true; + enableRecordUserId: true; +}; + +try{ + await deleteChannelMetadata([item1,item2],metadataOption); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +None + +> Caution:This operation will always excute regardless of the existing of metadata items + +#### Get channel metadata + + + +get all metadata items of the channel. + +**Method** + +```javascript +getChannelMetadata(): Promise; +``` + +**Basic Use** + +```javascript +try{ + const channelMetadata = await getChannelMetadata("my_channel"); + console.log(channelMetadata); +}catch(status){ + if (status){ + const {code,message} = status; + console.log(code,message); + } +} +``` + +**Response** + +Returns a type `RtmMetadata` for the specific `channel` which contains the following properties: + +| Property Name | Type | Description | +| --------------- | -------------------------- | ----------------------------------------------------------------------------------- | +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel | +| `majorRevision` | number | The major revision for this channel metadata | + +The `RtmMetadataItem` is a basic unit item of a `ChannelMetadata`, it contains the following properties: + +| Property Name | Type | Description | +| ------------------------------------- | -------- | ------------------------------------------------------------------- | +| `setKey(key: string): void` | function | Set key for the current `RtmMetadataItem` | +| `getKey(): string` | function | Get key for the current `RtmMetadataItem` | +| `setValue(value: string\|null): void` | function | Set value for the current `RtmMetadataItem` | +| `getValue(): string\|null` | function | Get the value for the current `RtmMetadataItem` | +| `setRevision(revision: number): void` | function | Set revision for the current `RtmMetadataItem` | +| `getRevision(): number` | function | Get revision for the current `RtmMetadataItem` | +| `getUpdateTs(): number` | function | Get updated time for the current `RtmMetadataItem` | +| `getAuthorUserId(): string` | function | Get the uid of who update this record for the current `RtmMetadataItem` | + +> **Caution**: If the specific `channel` have not set any user metadata yet, this operation will return a empty {}. + +#### Listen channel metadata update event + +When you join channel ,you will automatically Listen the channel metadata update event + +#### Channel metadata event + + + +it will occur when channel's metadata are updated, You need to complete this procedure yourself, and then you can handle this event when you are in the channel + +**Method** + +```javascript +ChannelMetaDataUpdated: (data: RtmMetadata) => void; +``` + +**Basic Use** + +```javascript +channel.on('ChannelMetaDataUpdated', (data) => { + console.log(data); // +}); +``` + +**Response** + +When this event occurs, you can recieve a type `RtmMetadata` for the specific `channel` which contains the following properties: + +| Property Name | Type | Description | +| --------------- | -------------------------- | ----------------------------------------------------------------------------------- | +| `items` | Array( `RtmMetadataItem` ) | `RtmMetadataItem` type array which contains a single key-value metadata item for a channel | +| `majorRevision` | number | The major revision for this channel metadata | + +The `RtmMetadataItem` is a basic unit item of a `ChannelMetadata`, it contains the following properties: + +| Property Name | Type | Description | +| ------------------------------------- | -------- | ------------------------------------------------------------------- | +| `setKey(key: string): void` | function | Set key for the current `RtmMetadataItem` | +| `getKey(): string` | function | Get key for the current `RtmMetadataItem` | +| `setValue(value: string\|null): void` | function | Set value for the current `RtmMetadataItem` | +| `getValue(): string\|null` | function | Get the value for the current `RtmMetadataItem` | +| `setRevision(revision: number): void` | function | Set revision for the current `RtmMetadataItem` | +| `getRevision(): number` | function | Get revision for the current `RtmMetadataItem` | +| `getUpdateTs(): number` | function | Get updated time for the current `RtmMetadataItem` | +| `getAuthorUserId(): string` | function | Get the uid of who update this record for the current `RtmMetadataItem` | + +> **Caution**: It should be noted that the returned data contains the full amount of data of the current channel, `Add`/`Set`/`Clear`/`Update`/`Delete` operation all will trigger this event, and you cannot distinguish which operation caused the current event. Need more features, you can use our new version 2.1. + + diff --git a/shared/signaling/metadata-sdk/windows.mdx b/shared/signaling/metadata-sdk/windows.mdx new file mode 100644 index 000000000..2cc5e94ae --- /dev/null +++ b/shared/signaling/metadata-sdk/windows.mdx @@ -0,0 +1,4 @@ + + + Metadata SDK is not currently available for this platform. + diff --git a/shared/signaling/prerequisites.mdx b/shared/signaling/prerequisites.mdx new file mode 100644 index 000000000..02e6c4231 --- /dev/null +++ b/shared/signaling/prerequisites.mdx @@ -0,0 +1,17 @@ +import PlatformPrerequisites from '@docs/shared/common/prerequities.mdx'; + + + +- Enabled in [ Console](https://console.agora.io/v2). To do so: + 1. Go to **Subscriptions** > **Signaling** + 1. Subscribe to a plan. + + ![signaling-pricing-page](/images/signaling/signaling-pricing-plans.png) + + Once subscribed, you will be able to unsubscribe from the same page. + +- [Raised a support ticket](https://agora-ticket.agora.io/) to activate the Stream Channel, if necessary. + + The support team confirms activation through a ticket update. + +Signaling 2.x is an enhanced version compared to 1.x with a wide range of new features. It follows a new pricing structure. Please visit the [Pricing](../overview/pricing) page for details. diff --git a/shared/signaling/presence/_presence.mdx b/shared/signaling/presence/_presence.mdx new file mode 100644 index 000000000..36ed2d68d --- /dev/null +++ b/shared/signaling/presence/_presence.mdx @@ -0,0 +1,53 @@ +import * as data from '@site/data/variables'; +import ProjectImplement from '@docs/shared/signaling/presence/project-implementation/index.mdx'; +import ProjectTest from '@docs/shared/signaling/presence/project-test/index.mdx'; +import Reference from '@docs/shared/signaling/presence/reference/index.mdx'; + +In real-time messaging solutions, it is often important to know whether a user is currently online or offline. For example, in instant messaging, chat applications, and online collaboration tools, users need to see the availability of their contacts. This information is typically displayed as a status message or icon next to a user's name. Presence features in enable you to monitor join, leave, and status change notifications for users in a channel. Using Presence, you can: + +- Get a list of users currently in a channel and their temporary status data. +- Get a list of channels a specified user has joined or is subscribed to. +- Read, set, or remove user status. +- Receive real-time event notifications when users join or leave specified channels. +- Receive user status change event notifications in real time. + + +**The implementation is coming soon.** + + + + +## Understand the tech + +Presence provides real-time information about the availability, and the current status of users, for effective communication and collaboration. It enables you to retrieve a list of users in a channel, or to query the list of channels for a specific user. The following figure illustrates how you integrate presence features into your . + +![](/images/signaling/presence-workflow.svg) + + +## Prerequisites + +To follow this page, you must have: + +- Set up the [ reference app](/en/signaling/get-started/get-started-sdk#project-setup). + + +## Implement presence + +To implement presence, + + + +## Test presence + +This section explains how to run the reference app and test presence features. To run the project, take the following steps: + + + +## Reference + +This section contains additional information that either supplements the content on this page or directs you to documentation that covers other aspects of this product. + + + + + diff --git a/shared/signaling/presence/project-implementation/index.mdx b/shared/signaling/presence/project-implementation/index.mdx new file mode 100644 index 000000000..a614f0b56 --- /dev/null +++ b/shared/signaling/presence/project-implementation/index.mdx @@ -0,0 +1,3 @@ +import Web from './web.mdx' + + diff --git a/shared/signaling/presence/project-implementation/web.mdx b/shared/signaling/presence/project-implementation/web.mdx new file mode 100644 index 000000000..0843f4dcb --- /dev/null +++ b/shared/signaling/presence/project-implementation/web.mdx @@ -0,0 +1,90 @@ + + +### Add the presence event listener + + ```js + signalingEngine.addEventListener("presence", eventArgs => { + eventsCallback("presence", eventArgs); + if (eventArgs.eventType === "SNAPSHOT") { + messageCallback( + `User ${eventArgs.snapshot[0].userId} joined channel ${eventArgs.channelName}` + ); + } else { + messageCallback( + "Presence event: " + + eventArgs.eventType + + ", User: " + + eventArgs.publisher + ); + } + }); + ``` + +### Enable presence notifications when you subscribe to a channel + + ```js + const subscribe = async (channelName) => { + channelName = channelName || config.channelName; + try { + const subscribeOptions = { + withMessage: true, + withPresence: true, // Enable presence notifications + withMetadata: true, + withLock: true, + }; + await signalingEngine.subscribe(channelName, subscribeOptions); + } catch (error) { + console.log(error); + } + }; + ``` + +### Obtain a list of users in the channel + + To get a list of users in a channel, call `getOnlineUsers()`: + + ```js + const getOnlineMembersInChannel = async (channelName, channelType) => { + const result = await getSignalingEngine().presence.getOnlineUsers( + channelName, + channelType + ); + return result.occupants; + }; + ``` + +### Set local user status + + To set the local user status, call `setState`. + + ```js + var state = {"mood":"pumped", "isTyping": "false"}; + + const setUserState = async (channelName, channelType, state) => { + try { + const result = await getSignalingEngine().presence.setState( + channelName, channelType, state); + console.log(result); + } catch (error) { + console.log(error); + } + }; + ``` + +### Get the status of a remote user + + To read the status of a remote user, call `getState`. + + ```js + const getUserState = async (userId, channelName, channelType) => { + try { + const result = await getSignalingEngine().presence.getState(userId, + channelName, channelType); + console.log(result); + } catch (error) { + console.log(error); + } + }; + ``` + + \ No newline at end of file diff --git a/shared/signaling/presence/project-test/index.mdx b/shared/signaling/presence/project-test/index.mdx new file mode 100644 index 000000000..4bad50030 --- /dev/null +++ b/shared/signaling/presence/project-test/index.mdx @@ -0,0 +1,12 @@ +import Web from './web.mdx' + +In , each authentication token you create is specific for a user ID. You create a token for each +user in the channel, each user must log in from different instance of your . +To test , you run 2 or more instances of your . When you call `login` using , ensure that the UID is the same as you used to create the token. + +For each user in your tests: + +1. **[Generate a temporary token](../reference/manage-agora-account#generate-a-temporary-token)**. + + diff --git a/shared/signaling/presence/project-test/web.mdx b/shared/signaling/presence/project-test/web.mdx new file mode 100644 index 000000000..83f03d9f1 --- /dev/null +++ b/shared/signaling/presence/project-test/web.mdx @@ -0,0 +1,34 @@ + +2. **Configure the project**: + + In `/src/signaling_manager/config.json`: + + 1. Replace the value for `token` with the token. + + 1. Replace the value for `appId` with the value from . + + 1. Replace the value for UID with the the same value you used to generate the token. + + 1. Ensure that the `channelName` is filled in. The channel name can be any string. + +1. **Run the reference app**: + + Open Terminal in the project folder, then run the following command: + + ``` bash + pnpm dev + ``` + + Use the URL displayed in Terminal to open the app in your browser. + +1. **Test presence functionality**: + + 1. Choose **SDK quickstart**, then log in to . + 1. Open the **Token authentication** example in multiple tabs. + 1. Log in to from each tab using a different user ID. + 1. Subscribe to the same channel from all the tabs. + You see a list of all users in the channel in the **SDK quickstart** tab. + 1. Unsubscribe from the channel in another tab. + You see that the corresponding user ID disappears from the user list. + + diff --git a/shared/signaling/presence/reference/index.mdx b/shared/signaling/presence/reference/index.mdx new file mode 100644 index 000000000..a614f0b56 --- /dev/null +++ b/shared/signaling/presence/reference/index.mdx @@ -0,0 +1,3 @@ +import Web from './web.mdx' + + diff --git a/shared/signaling/presence/reference/web.mdx b/shared/signaling/presence/reference/web.mdx new file mode 100644 index 000000000..49f5ae810 --- /dev/null +++ b/shared/signaling/presence/reference/web.mdx @@ -0,0 +1,10 @@ + + +### API reference + +* [Presence](../reference/api#presence) +* [Event listeners](../reference/api#event-listeners) +* [Presence Event Types](../reference/api#presence-event-types) + + + \ No newline at end of file diff --git a/shared/signaling/reference/_pricing.mdx b/shared/signaling/reference/_pricing.mdx new file mode 100644 index 000000000..d73132dab --- /dev/null +++ b/shared/signaling/reference/_pricing.mdx @@ -0,0 +1,68 @@ + + +## Pricing concepts + + is priced based on the total number of messages, peak connections, and storage usage of your account in a calendar month. + +### Number of messages + +The measurement rules for the number of messages sent and received are as follows: + +* Any 1 message published in the Message Channel counts as 1 message +* Any 1 message received in the Message Channel counts as 1 message. + +For example, if a client sends 1 message to a Message Channel, and the channel is subscribed by 10 people, it is counted as 1 sent message and 10 received messages, for a total of 11 messages. + +* Any 1 message published in a Topic in the Stream Channel counts as 1 message. +* Any 1 message received in a Topic in the Stream Channel counts as 1 message. + +For example, if a client sends a message to a Topic in the Stream Channel, and this Topic is subscribed by 10 people, it is counted as 1 sent message and 10 received messages, for a total of 11 messages. + +Even if message filtering is enabled on the client, it does not have any impact on message metering. The client-side message filtering function is only for the convenience of developers, and the messages are actually delivered. +The asynchronous callback generated by publishing a message in the Message Channel or Stream Channel is not counted in the number of messages. +Messages sent using the RESTful API are also counted as messages. +If a client does not subscribe to a channel or topic, it does not receive any messages. + +### Presence +Each Presence event notification published is counted as one message, such as the client’s entry into the channel, leaving the channel, timeout notification, and status change notification. +Each Presence event notification received in the channel counts as one message. For example, if a client enters a channel, and 10 other clients subscribe to the channel and listen to the Presence event notifications in the channel, then this counts as 1 sent Presence event notification, and the remaining 10 clients receive a total of 10 presence event notifications. That is a total of 11 messages. + +The client message filtering function has no impact on the presence event notification count. +If a client does not want to send the Presence event when joining the Stream Channel or subscribing to the Message Channel, setting `withPresence` to `false` does not affect the calculation of the number of messages. +If a client does not join a Stream Channel or subscribe to a Message Channel, it does not receive the Presence event notification of the channel. + +### Storage +Setting, querying, updating, and deleting any piece of Channel Metadata in the Message Channel or Stream Channel is counted as 1 message. +Any 1 Channel Metadata change event notification received in a Message Channel or Stream Channel is counted as 1 message. For example, if a client sets 1 Channel Metadata on a channel, the channel is subscribed by 10 people, and these users listen to the Channel Metadata change notification, it is deemed that 1 message has been published and 10 messages have been received, for a total of 11 messages. + +Setting, querying, updating, and deleting any piece of User Metadata is counted as 1 message. +Receiving 1 change notification of User Metadata is counted as 1 message. For example, if the client sets 1 User Metadata for a user, and the User Metadata is subscribed by 10 people, it is deemed that 1 message has been published and 10 messages have been received, for a total of 11 messages. + +Client message filtering has no impact on Channel Metadata or User Metadata change notification counts. The client message filtering settings are as follows: + +* Set `withMetadata` to `false` if the client does not want to receive Channel Metadata or User Metadata change notifications when joining a Stream Channel or subscribing to a Message Channel. +* If a client does not join the Stream Channel or subscribe to a Message Channel, it does not receive the Channel Metadata change notification of the channel. +* If the client does not subscribe to other users’ User Metadata, it will not receive other users’ User Metadata change notifications. + +### Locks +Any operations such as lock setting, query, release, deprivation, and deletion are counted as 1 message. +Any 1 lock change event notification received in a Message Channel or Stream Channel is counted as one message. For example, if the client sets a lock on a channel, and the channel is subscribed by 10 people, and these users listen to the lock change notification, it is regarded as publishing 1 message and receiving 10 messages, for a total of 11 messages. + +In , a message is calculated in 1 KB. Therefore, if you send a message package with a size of 10 KB to a channel or Topic subscribed by 100 people, it will be counted as 10 inbound messages and 1,000 outbound messages to give a total of 1,010 messages. + +### Storage occupancy + +Storage in generates cloud storage occupancy. measures the total storage occupancy, and bills the amount for the month by sampling the customer's actual cloud storage occupancy at 1-hour intervals in a natural month and then accumulating them. The calculation formula is as follows: + +_Storage fees = number of days in the month * 24 hours * storage usage per hour * sampling rate_ + +For example, if you have 100 GB of storage and you are using a sampling rate of 10%, then your storage fees for a 30-day month would be: + +_Storage fees = 30 days * 24 hours * 100 GB/hour * 10% = 72,000 GB_ + +This would be equivalent to 72 TB, which is a common unit of measurement for storage capacity. +It is important to note that this formula is just a general guideline. The actual storage fees you are charged may vary depending on your provider and your specific contract. + +### Peak connections + +The number of peak connections is the maximum number of real-time clients simultaneously connected to at any point in a calendar month. For example, if you have 10,000 customers, and a maximum of 500 clients connect to simultaneously in a given month, the PCU value is 500. This means you only pay for 500 peak connections. The total number of clients or devices connected to in a month does not affect billing. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_channel-en.javascript.mdx b/shared/signaling/reference/api-ref/_channel-en.javascript.mdx new file mode 100644 index 000000000..b6345b43f --- /dev/null +++ b/shared/signaling/reference/api-ref/_channel-en.javascript.mdx @@ -0,0 +1,275 @@ +import * as config from './shared/_configuration.mdx' +import * as topic from './shared/_topic.mdx' +import * as channel from './shared/_channel.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' + +Signaling provides a highly efficient channel management mechanism for data transmission. Any user who subscribes or joins a channel can receive messages and events transmitted within 100 milliseconds. Signaling allows clients to subscribe to hundreds or even thousands of channels. Most Signaling APIs perform actions such as sending, receiving, and encrypting based on channels. + +Based on capabilities of Agora, Signaling channels are divided into two types to match different application scenarios: + +- Message Channel: Follows the industry-standard Pub/Sub (publish/subscribe) mode. You can send and receive messages within the channel by subscribing to a channel, and do not need to create the channel in advance. There is no limit to the number of publishers and subscribers in a channel. + +- Stream Channel: Follows a concept similar to the observer pattern in the industry, where users need to create and join a channel before sending and receiving messages. You can create different topics in the channel, and messages are organized and managed through topics. + +### {channel.subscribe[props.ag_platform]} + +#### Description + +Signaling provides event notification capabilities for messages and states. By setting up event listeners, you can receive messages and events within subscribed channels. For information on how to add and set up event listeners, see Event Listener. + +By calling the {channel.subscribe[props.ag_platform]} method, the client can subscribe to a message channel and start receiving messages and event notifications within the channel. After successfully calling this method, users who subscribe to the channel and enable the presence event listener can receive a {config.onpresenceevent[props.ag_platform]} event with the {enumv.remotejoinchannel[props.ag_platform]} type. + +This method only applies to the message channel. + +#### Method + +You can call the {channel.subscribe[props.ag_platform]} method in the following way: + +```javascript +rtm.subscribe( + channelName: string, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :-----: | :----------------------: | +| `channelName` | string | Yes | - | The channel name. | +| `options` | object | Optional | - | Options for subscribing a channel. | + +The options object includes the following properties: + +| Property | Type | Required | Default | Description | +| :------------: | :-----: | :------: | :-----: | :----------------------------------------------------------: | +| `withMessage` | boolean | Optional | `true` | Whether to subscribe to message event notifications in the channel. | +| `withPresence` | boolean | Optional | `true` | Whether to subscribe to presence event notifications in the channel. | +| `withMetadata` | boolean | Optional | `false` | Whether to subscribe to storage event notifications in the channel. | +| `withLock` | boolean | Optional | `false` | Whether to subscribe to lock event notifications in the channel. | + +#### Basic usage + +```javascript +const options ={ + withMessage : true, + withPresence : true, + withMetadata : false, + withLock : false +}; +try { + const result = await rtm.subscribe("chat_room", options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the {channel.subscriberesulttype[props.ag_platform]} response as follows is returned: + +```js +type SubscribeResponse = { + timeToken : number // Reserved property, indicating the timestamp of the successful operation. + channelName : string // Channel name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + +### {channel.unsubscribe[props.ag_platform]} + +#### Description + +To cancel your subscription, call the {channel.unsubscribe[props.ag_platform]} method. After successfully unsubscribing from the channel, other users who subscribe to the channel and enable event listeners can receive a {config.onpresenceevent[props.ag_platform]} event notification with the {enumv.remoteleavechannel[props.ag_platform]} type. For details, see Event Listener. + +This method only applies to the message channel. + +#### Method + +You can call the {channel.unsubscribe[props.ag_platform]} method in the following way: + +```javascript +rtm.unsubscribe( + channelName: string +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :-----: | :----------------------: | +| `channelName` | string | Yes | - | The channel name. | + +#### Basic usage + +```javascript +try { + const result = await rtm.unsubscribe("chat_room"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the {channel.unsubscriberesulttype[props.ag_platform]} response as follows is returned: + +```js +type UnsubscribeResponse = { + timeToken : number // Reserved property, indicating the timestamp of the successful operation. + channelName : string // Channel name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + +### {channel.create[props.ag_platform]} + +#### Description + +Before using a stream channel, you need to call the {channel.create[props.ag_platform]} method to create an {channel.istreamchannel[props.ag_platform]} instance. After successfully creating the instance, you can call its relevant methods to implement functions, such as joining the channel, leaving the channel, sending messages in a topic, and subscribing to messages in a topic. + +This method only applies to the stream channel. + +#### Method + +You can call the {channel.create[props.ag_platform]} method in the following way: + +```javascript +rtm.createStreamChannel(chanelName: string): RTMStreamChannel; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :-----: | :----------------------: | +| `channelName` | string | Yes | - | The channel name. | + + +#### Basic usage + +```javascript +try{ + const Loc_stChannel = await rtm.createStreamChannel( "Location"); + console.log("Create Stream Channel success!: "); +} catch (status){ + console.log(status); +} +``` + +#### Return value + +An {channel.istreamchannel[props.ag_platform]} instance. + + + +### {channel.join[props.ag_platform]} + +#### Description + +After successfully creating a stream channel, you can call the {channel.join[props.ag_platform]} method to join the stream channel. Once you join the channel, you can implement channel-related functions. At this point, users who subscribe to the channel and add event listeners can receive the following event notifications: + +- Local users: + - {config.onpresenceevent[props.ag_platform]} event notification with the {enumv.presencetypesnap[props.ag_platform]} type. + - {config.ontopicevent[props.ag_platform]}event notification with the {enumv.topictypesnap[props.ag_platform]} type. +- Remote users: {config.onpresenceevent[props.ag_platform]} event notification with the {enumv.remotejoinchannel[props.ag_platform]} type. + +This method only applies to the stream channel. + +#### Method + +You can call the {channel.join[props.ag_platform]} method in the following way: + +```javascript +join(options?: { + token?: string; + withPresence?: boolean; + withMetadata?: boolean; + withLock?: boolean; +}): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :-----: | :----------------------: | +| `options` | object | Optional | - | Options for joining a channel. | + +The options object includes the following properties: + +| Property | Type | Required | Default | Description | +| :------------: | :-----: | :------: | :-----: | :----------------------------------------------------------: | +| `token` | string | Optional | - | The token used for joining a stream channel, which is currently the same as the RTC token. | +| `withMetadata` | boolean | Optional | `false` | Whether to subscribe to storage event notifications in the channel. | +| `withPresence` | boolean | Optional | `true` | Whether to subscribe to presence event notifications in the channel. | +| `withLock` | boolean | Optional | `false` | Whether to subscribe to lock event notifications in the channel. | + +#### Basic usage + +```js +const options ={ + token : "yourToken", + withPresence : true, + withMetadata : false, + withLock : false +}; +try { + const result = await stChannel.join(options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + + +#### Return value + +If the method call succeeds, the {channel.joinresulttype[props.ag_platform]} response as follows is returned: + +```js +type JoinChannelResponse = { + timeToken : number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string // Channel name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + + +### {channel.leave[props.ag_platform]} + +#### Description + +Call the {channel.leave[props.ag_platform]} method to leave the channel. After leaving the channel, you can no longer receive any messages, states, or event notifications from this channel. At the same time, you can no longer be the topic publisher or subscriber of all topics. To restore your previous publisher role and subscribing relationship, call {channel.join[props.ag_platform]}, {topic.join[props.ag_platform]} and {topic.subscribe[props.ag_platform]} methods in order. + +After successfully leaving the channel, remote users in the channel can receive a {config.onpresenceevent[props.ag_platform]} event notification with the {enumv.remoteleavechannel[props.ag_platform]} type. For details, see Event Listener. + +This method only applies to the stream channel. + +#### Method + +You can call the {channel.leave[props.ag_platform]} method in the following way: + +```javascript +leave(): Promise; +``` + +#### Basic usage + +```javascript +try{ + const result = await rtm.leave(); + console.log(result); +} catch (status){ + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the {channel.leaveresulttype[props.ag_platform]} response as follows is returned: + +```js +type LeaveChannelResponse = { + timeToken : number // Reserved property, indicating the timestamp of the successful operation. + channelName : string // Channel name. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_configuration-en.javascript.mdx b/shared/signaling/reference/api-ref/_configuration-en.javascript.mdx new file mode 100644 index 000000000..bf0532569 --- /dev/null +++ b/shared/signaling/reference/api-ref/_configuration-en.javascript.mdx @@ -0,0 +1,271 @@ +import * as config from './shared/_configuration.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' + +Before initializing a Signaling client instance, you need to import the Signaling Javascript SDK into your project: + +```js + +``` + +### Initialization + +#### Description + +Initialization in Signaling refers to creating and initializing a Signaling client instance. When initializing the instance, you need to pass in parameters including `appId` and `userId`. You can create a project and get the App ID on the Agora console. + +
    • The initialization step needs to be completed before calling the other Signaling APIs.
    • In order to identify users and devices, you need to ensure that userId is globally unique and remains constant throughout the lifecycle of the user or device.
    + +#### Method + +You can create and initialize an instance in the following way: + +```javascript +class RTM( + constructor( + appId: string, + userId: string, + rtmConfig?: { + token: string, + encryptionMode: string, + cipherKey: string, + salt: Uint8Array, + useStringUserId: boolean, + presenceTimeout: number, + logUpload: boolean, + logLevel: string, + cloudProxy: boolean + } + ); +) +``` + +| Parameter | Type | Required | Default | Description | +| :---------: | :------------------------------------------------: | :------: | :----: | ------------------------------------------------------------------------------- | +| `appId` | string | Required | - | The App ID of your Agora project on the Agora Console. | +| `userId` | string | Required | - | The unique ID to identify a user or device. | +| `rtmConfig` | {config.rtm[props.ag_platform]} | Optional | - | The configuration parameters for initialization, see {config.rtm[props.ag_platform]}. | + +#### Basic usage + +```javascript +const { RTM } = AgoraRTM; +const rtm = new RTM( + appId : "myAppId", + userId : "Tony" +); +``` + + +#### Return Value + +A Signaling client instance. Now you can call other Signaling APIs. + +### {config.rtm[props.ag_platform]} + +#### Description + +{config.rtm[props.ag_platform]} is used to configure additional properties when you initialize a Signaling client instance. These configuration properties take effect throughout the lifecycle of the Signaling client and affect the behaviors of the Signaling client. + +#### Method + +You can create a {config.rtm[props.ag_platform]} instance in the following way: + +```js +const { RTMConfig } = AgoraRTM; +``` + +| Property | Type | Required | Default | 描述 | +| :---------------: | :--------: | :------: | :-----: | ---------------------------------------- | +| `token` | string | Optional | - | A dynamic key, usually generated by a token server. | +| `encryptionMode` | string | Optional | - | Encryption mode for end-to-end messages. To disable end-to-end encryption, set this property to {enumv.encryptionmodenone[props.ag_platform]}. For details, see [Encryption Modes](#end-to-end-encryption-modes). | +| `cipherKey` | string | Optional | - | The key used for encryption and decryption. Set this property to enable message encryption. | +| `salt` | Uint8Array | Optional | - | The salt required for encryption. The value must be a 32-byte binary array. | +| `useStringUserId` | boolean | Optional | `true` | Whether to use string-type user IDs:
    • true: Use string-type user IDs.
    • false: Use number-type user IDs. When set the property as false, SDK automatically converts string-type user IDs to number-type ones. In this case, the `userId` parameter must be a numeric string (for example, "123456"), otherwise initialization fails.
    | +| `presenceTimeout` | number | optional | `300` | Presence timeout in seconds, and the value range is [10,300]. | +| `logUpload` | boolean | Optional | `false` | Whether to upload logs to the server:
    • true: Enable log upload
    • false: Disable log upload.
    | +| `logLevel` | string | Optional | - | Set the output level of SDK log. For details, see log output level. | +| `cloudProxy` | boolean | Optional | `false` | Whether to enable the cloud proxy:
    • true: Enable.
    • false: Disable.
    | + +#### Basic usage + +```js +const { RTM, EncryptionMode } = AgoraRTM; +const rtmConfig = { + token : "yourToken", + encryptionMode : EncryptionMode.AES_256_GCM, + slat : yourSalt, + cipherKey : "yourCipherKey", + presenceTimeout : 300, + logUpload : true, + logLevel : 'debug', + cloudProxy : false, + useStringUserId : false +}; +const rtm = new RTM( "myAppId", "Tony", rtmConfig); +``` + +### Event Listeners + +#### Description + +In Signaling there are seven types of events as follows: + +| Event Type | Description | +|:----------------------------:| ------------------------- | +| {config.onmessageevent[props.ag_platform]} | Receive message event notifications in subscribed message channels and subscribed topics. | +| {config.onpresenceevent[props.ag_platform]} | Receive presence event notifications in subscribed message channels and joined stream channels. | +| {config.ontopicevent[props.ag_platform]} | Receive all topic event notifications in joined stream channels. | +| {config.onstorageevent[props.ag_platform]} | Receive channel metadata event notifications in subscribed message channels and joined stream channels, and the user metadata event notification of the subscribed users. | +| {config.onlockevent[props.ag_platform]} | Receive lock event notifications in subscribed message channels and joined stream channels. | +| {config.onconnection[props.ag_platform]} | Receive event notifications when client connection status changes. | +| {config.ontokenwillexpire[props.ag_platform]} | Receive event notifications when the client tokens are about to expire. | + +#### Add event listeners + +You can add event listeners in the following way: + +```javascript +// Add message event listeners +// Message +rtm.addEventListener("message", event => { + const channelType = event.channelType; // Which channel type it is, Should be "STREAM" or "MESSAGE" . + const channelName = event.channelName; // Which channel does this message come from + const topic = event.topicName; // Which Topic does this message come from, it is valid when the channelType is "STREAM". + const messageType = event.messageType; // Which message type it is, Should be "sting" or "binary" . + const customType = event.customType; // User defined type + const publisher = event.publisher; // Message publisher + const message = event.message; // Message payload + const pubTime = event.publishTime; // Message publisher timestamp +}); +// Presence +rtm.addEventListener("presence", event => { + const action = event.eventType; // Which action it is ,should be one of 'SNAPSHOT'、'INTERVAL'、'JOIN'、'LEAVE'、'TIMEOUT、'STATE_CHANGED'、'OUT_OF_SERVICE'. + const channelType = event.channelType; // Which channel type it is, Should be "STREAM" or "MESSAGE" . + const channelName = event.channelName; // Which channel does this event come from + const publisher = event.publisher; // Who trigger this event + const states = event.stateChanged; // User state payload + const interval = event.interval; // Interval payload + const snapshot = event.snapshot; // Snapshot payload +}); +// Topic +rtm.addEventListener("topic", event => { + const action = event.evenType; // Which action it is ,should be one of 'SNAPSHOT'、'JOIN'、'LEAVE'. + const channelName = event.channelName; // Which channel does this event come from + const publisher = event.userId; // Who trigger this event + const topicInfos = event.topicInfos; // Topic information payload + const totalTopics = event.totalTopics; // How many topics +}); +// Storage +rtm.addEventListener("storage", event => { + const channelType = event.channelType; // Which channel type it is, Should be "STREAM" or "MESSAGE" . + const channelName = event.channelName; // Which channel does this event come from + const publisher = event.publisher; // Who trigger this event + const storageType = event.storageType; // Which category the event is, should be 'USER'、'CHANNEL' + const action = event.eventType; // Which action it is ,should be one of "SNAPSHOT"、"SET"、"REMOVE"、"UPDATE" or "NONE" + const data = event.data; // 'USER_METADATA' or 'CHANNEL_METADATA' payload +}); +// Lock +rtm.addEventListener("lock", event => { + const channelType = event.channelType; // Which channel type it is, Should be "STREAM" or "MESSAGE" . + const channelName = event.channelName; // Which channel does this event come from + const publisher = event.publisher; // Who trigger this event + const action = event.evenType; // Which action it is ,should be one of 'SET'、'REMOVED'、'ACQUIRED'、'RELEASED'、'EXPIRED'、'SNAPSHOT' + const lockName = event.lockName; // Which lock it effect + const ttl = event.ttl; // The ttl of this lock + const snapshot = event.snapshot; // Snapshot payload +}); +// Connection State Change +rtm.addEventListener("status", event => { + const currentState = event.state; // Which connection state right now + const changeReason = event.reason; // Why trigger this event +}); +// Token Privilege Will Expire +rtm.addEventListener("tokenPrivilegeWillExpire", (channelName) => { + const channelName = channelName; // Which Channel Token Will Expire +}); +``` + +#### Remove event listeners + +You can call the {config. removedelegate[props.ag_platform]} method to remove a specified event listener. + +```javascript +rtm.removeEventListener('status', statusHandler); +``` + +### {config.login[props.ag_platform]} + +#### Description + +After creating and initializing a Signaling client instance, you need to perform the {config.login[props.ag_platform]} operation to log in to the Signaling service. With successful login, the client establishes a long link to the Signaling server and allows the client to access Signaling resources. + +#### Method + +You can call the {config.login[props.ag_platform]} method in the following way: + +```javascript +rtm.login(): Promise; +``` + +#### Basic usage + +```javascript +try{ + const result = await rtm.login(); + console.log(result); +} catch (status){ + console.log(status); +} +``` + + +#### Return Value + +If the method call succeeds, the {config.loginresulttype[props.ag_platform]} response as follows is returned: + +```js +type LoginResponse = { + timeToken: number // Reserved property, indicating the timestamp of the successful operation +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {config.logout[props.ag_platform]} + +#### Description + +Log out of the Signaling. + +#### Method + +You can call the {config.logout[props.ag_platform]} method in the following way: + +```javascript +rtm.logout(): Promise; +``` + +#### Basic usage + +```js +try{ + const result = await rtm.logout(); + console.log(result); +} catch (status){ + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {config.logoutresulttype[props.ag_platform]} response as follows is returned: + +```js +type LoginResponse = { + timeToken: number // Reserved property, indicating the timestamp of the successful operation +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_enumv-en.mdx b/shared/signaling/reference/api-ref/_enumv-en.mdx new file mode 100644 index 000000000..9e7c6c624 --- /dev/null +++ b/shared/signaling/reference/api-ref/_enumv-en.mdx @@ -0,0 +1,101 @@ +import * as config from './shared/_configuration.mdx' +import * as enumv from './shared/_enumv.mdx' + +### Channel Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.channeltypemessage[props.ag_platform]} | Message channel. | +| {enumv.channeltypestream[props.ag_platform]} | Stream channel. | + + +### Reasons for the SDK Connection State Change + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.reasonconnecting[props.ag_platform]} | The SDK is connecting with the Signaling system. | +| {enumv.reasonloginsuccess[props.ag_platform]} | The SDK logged in the Signaling system successfully. | +| {enumv.reasonrejected[props.ag_platform]} | The SDK is rejected by the server. | +| {enumv.reasonlost[props.ag_platform]} | The SDK lost the connection with the Signaling system. | +| {enumv.reasoninterrupt[props.ag_platform]} | The connection was interrupted. | +| {enumv.reasonlogout[props.ag_platform]} | The SDK logged out of the Signaling system. | +| {enumv.reasonban[props.ag_platform]} | The SDK is banned by the server. | +| {enumv.reasonsameuid[props.ag_platform]} | The same user ID was used to join the same channel on different devices. | +| {enumv.reasontokenexpired[props.ag_platform]} | The used token expired. You need to request a new token from your server. | + + +### SDK Connection States + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.sdkdisconnect[props.ag_platform]} | The SDK has disconnected with the server. | +| {enumv.sdkconnecting[props.ag_platform]} | The SDK disconnected with the server. | +| {enumv.sdkconnected[props.ag_platform]} | The SDK has connected with the server. | +| {enumv.sdkreconnect[props.ag_platform]} | The connection is lost. The SDK is reconnecting with the server. | +| {enumv.sdkfailed[props.ag_platform]} | The SDK failed to connect with the server. | + + +### End-to-End Encryption Modes + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.encryptionmodenone[props.ag_platform]} | No encryption. | +| {enumv.aesonetwoeight[props.ag_platform]} | AES-128-GCM mode. | +| {enumv.aestwofivesix[props.ag_platform]} | AES-256-GCM mode. | + + +### Lock Event Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.locktypesnap[props.ag_platform]} | The snapshot of the lock when the user joined the channel. | +| {enumv.locktypeset[props.ag_platform]} | The lock is set. | +| {enumv.locktyperemoved[props.ag_platform]} | he lock is removed. | +| {enumv.locktypeacquired[props.ag_platform]} | The lock is acquired. | +| {enumv.locktypereleased[props.ag_platform]} | The lock is released. | +| {enumv.locktypeexpired[props.ag_platform]} | The lock expired. | + + +### Log Output Levels + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.loglevelnone[props.ag_platform]} | No log. | +| {enumv.loglevelinfo[props.ag_platform]} | Output the log at the `error`, `warn`, or `info` level. Agora recommends you set to this value. | +| {enumv.loglevelwarn[props.ag_platform]} | Output the log at the `error` or `warn` level. | +| {enumv.loglevelerror[props.ag_platform]} | Output the log at the `error` level. | +| {enumv.logleveldebug[props.ag_platform]} | Output the log at all levels. | + +### Message Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.binarymessage[props.ag_platform]} | Binary type. | +| {enumv.stringmessage[props.ag_platform]} | String type. | + +### Presence Event Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.presencetypesnap[props.ag_platform]} | When users joined a channel for the first time, they received a snapshot of the channel pushed by the server. | +| {enumv.presencetypeint[props.ag_platform]} | When users in the channel reach the limit, the event notifications are sent at intervals rather than in real time. | +| {enumv.presencetypejoin[props.ag_platform]} | A remote user joined the channel. | +| {enumv.presencetypeleave[props.ag_platform]} | A remote user left the channel. | +| {enumv.presencetypetimeout[props.ag_platform]} | A remote user's connection timed out. | +| {enumv.presencetypechange[props.ag_platform]} | A remote user's temporary state changed. | +| {enumv.presencetypeout[props.ag_platform]} | The user did not enable presence when joining the channel. | + +### Storage Event Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.storagetypeuser[props.ag_platform]} | User metadata event. | +| {enumv.storagetypechannel[props.ag_platform]} | Channel metadata event. | + +### Topic Event Types + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| {enumv.topictypesnap[props.ag_platform]} | The snapshot of the topic when the user joined the channel. | +| {enumv.topictypejoin[props.ag_platform]} | A remote user joined the channel. | +| {enumv.topictypeleave[props.ag_platform]} | A remote user left the channel. | \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_lock-en.javascript.mdx b/shared/signaling/reference/api-ref/_lock-en.javascript.mdx new file mode 100644 index 000000000..66a6e0021 --- /dev/null +++ b/shared/signaling/reference/api-ref/_lock-en.javascript.mdx @@ -0,0 +1,357 @@ +import * as lock from './shared/_lock.mdx' +import * as config from './shared/_configuration.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' + + +A critical resource can only be used by one process at a time. If a critical resource is shared between different processes, each process needs to adopt a mutually exclusive method to prevent mutual interference. Signaling provides a full set of lock solutions. By controlling different processes in a distributed system, you can solve the competition problem when users access shared resources. + +The client is able to set, remove, and revoke locks. We recommend that you control the permissions of the these operations on the client side based on your business needs. + +### {lock.set[props.ag_platform]} + +#### Description + +You need to configure the lock name, time to live (TTL) and other parameters by calling the {lock.set[props.ag_platform]} method. If the configuration succeeds, all users in the channel receives the {config.onlockevent[props.ag_platform]} event notifications of the {enumv.locktypeset[props.ag_platform]} type. For details, see [Event Listeners](#event-listeners). + +#### Method + +You can call the {lock.set[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.setLock( + channelName: string, + channelType: string, + lockName: string, + options?: { + ttl?: number; + } +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `lockName` | string | Required | - | Lock name. | +| `options` | object | Optional | - | Options for setting locks. | + +`options` contains the following properties: + +| Property | Type | Required | Default| Description | +| :---: | :----: | :------: | :----: | :----------------------------------------------------------------------------------------------- | +| `ttl` | number | Optional | `10` | Time to live in seconds of the lock, and the value range is [10,300]. When the user who owns the lock goes offline, if the user returns to the channel within the time they can still use the lock; otherwise, the lock is released and the users who listen for the {config.onlockevent[props.ag_platform]} event receives the {enumv.locktypereleased[props.ag_platform]} event. | + +#### Basic Usage + +```javascript +try{ + const result = await rtm.Lock.setLock( + channel:"my_channel", + channelType:"STREAM", + lockName: "my_lock", + { ttl: 30 } + ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.setlockresulttype[props.ag_platform]} response as follows is returned: + +```js +type SetLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + lockName : string // Lock name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {lock.acquire[props.ag_platform]} + +#### Description + +After setting a lock, you can call the {lock.acquire[props.ag_platform]} method on the client to acquire the right to own the lock. When you acquire the lock, other users in the channel receives the {config.onlockevent[props.ag_platform]} event of the {enumv.locktypeacquired[props.ag_platform]} type. For details, see Event Listener. + +#### Method + +You can call the {lock.acquire[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.acquireLock( + channelName: string, + channelType: string, + lockName: string, + options?: { retry?: boolean } +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `lockName` | string | Required | - | Lock name. | +| `options` | object | Optional | - | Options for setting locks. | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-----: | :-----: | :------: | :-----: | :---------------------------------------------------------- | +| `retry` | boolean | Optional | `false` | If the lock acquisition fails, whether to retry until the acquisition succeeds or the user leaves the channel. | + +#### Basic Usage + +```javascript +try{ + const result = await rtm.Lock.acquireLock( + "chat_room", + "STREAM", + "my_lock", + {retry:false} + ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.acquirelockresulttype[props.ag_platform]} response as follows is returned: + +```js +type AcquireLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + lockName : string // Lock name. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {lock.release[props.ag_platform]} + +#### Description + +When a user no longer needs to own a lock, the user can call the {lock.release[props.ag_platform]} method on the client side to release the lock. When the lock is released, other users in the channel receives the {config.onlockevent[props.ag_platform]} event of {enumv.locktypereleased[props.ag_platform]} type. For details, see Event Listeners. + +At this time, if other users want to acquire the lock, they can call the {lock.acquire[props.ag_platform]} method on the client side to compete. New users acquiring locks have the same contention priority as the users who set the `retry` property to automatically retry to acquire locks. + +#### Method + +You can call the {lock.acquire[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.releaseLock( + channelName: string, + channelType: string, + lockName: string +): Promise; +``` + +| Property | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :------------------------------------------------------------------------------------------------------------ | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `lockName` | string | Required | - | Lock name. | + + +#### Basic Usage + +```javascript +try{ + const result = await rtm.lock.releaseLock( + "chat_room", + "STREAM", "my_lock" + ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.releaselockresulttype[props.ag_platform]} response as follows is returned: + +```js +type ReleaseLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + lockName : string // Lock name. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {lock.revoke[props.ag_platform]} + +#### Description + +You may need to take back a lock owned by another user and allow the other users to acquire the lock. You can call the {lock.revoke[props.ag_platform]} method to revoke the lock. When the lock is revoked, all users in the channel receives the {config.onlockevent[props.ag_platform]} event of the {enumv.locktypereleased[props.ag_platform]} type. For details, see Event Listeners. + +At this time, if other users want to acquire the lock, they can call the {lock.acquire[props.ag_platform]} method on the client side to compete. New users acquiring locks have the same contention priority as the users who set the `retry` property to automatically retry to acquire locks. + +#### Method + +You can call the {lock.revoke[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.revokeLock( + channelName: string, + channelType: string, + lockName: string, + owner: string +): Promise; +``` + +| Property | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `lockName` | string | Required | - | Lock name. | +| `owner` | string | Required | - | User ID of the lock owner. | + + +#### Basic Usage + +```javascript +try{ + const result = await rtm.lock.revokeLockLock( + "chat_room", + "STREAM", + "my_lock", + "Tony" + ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.revokelockresulttype[props.ag_platform]} response as follows is returned: + +```js +type RevokeLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + lockName : string // Lock name. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {lock.get[props.ag_platform]} + +#### Description + +To query the lock information such as total number of locks, lock name, and lock user, time to live, call the {lock.get[props.ag_platform]} method on the client. + +#### Method + +You can call the {lock.get[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.getLock( + channelName: string, + channelType: string +): Promise; +``` + +| Property | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :------------------------------------------------------------------------------------------------------------ | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | + + +#### Basic Usage + +```javascript +try{ + const result = await rtm.lock.getLock("chat_room","STREAM"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.getlockresulttype[props.ag_platform]} response as follows is returned: + +```js +type GetLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + totalLocks : string, // Total lock number. + lockDetails : [{ + lockName: string, // Lock name. + owner: string, // Lock owner. + ttl: number // Time to live in seconds of the lock. + }] +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {lock.remove[props.ag_platform]} + +#### Description + +Remove the lock by calling the {lock.remove[props.ag_platform]} method. When the lock is successfully removed, all the users in the channel receives the {config.onlockevent[props.ag_platform]} event notification in the {enumv.locktyperemoved[props.ag_platform]} type. For details, see Event Handlers. + +#### Method + +You can call the {lock.remove[props.ag_platform]} method in the following way: + +```javascript +rtm.lock.removeLock( + channelName: string, + channelType: string, + lockName: string +): Promise; +``` + +| Property | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `lockName` | string | Required | - | Lock name. | + +#### Basic Usage + +```javascript +try{ + const result = await rtm.Lock.removeLockLock("chat_room","STREAM", "my_lock"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {lock.removelockresulttype[props.ag_platform]} response as follows is returned: + +```js +type RemoveLockResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + lockName : string, // Lock name. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_message-en.javascript.mdx b/shared/signaling/reference/api-ref/_message-en.javascript.mdx new file mode 100644 index 000000000..6a6864bdb --- /dev/null +++ b/shared/signaling/reference/api-ref/_message-en.javascript.mdx @@ -0,0 +1,104 @@ +import * as enumv from './shared/_enumv.mdx' +import * as config from './shared/_configuration.mdx' +import * as channel from './shared/_channel.mdx' +import * as message from './shared/_message.mdx' +import * as topic from './shared/_topic.mdx' +import Status from './shared/_rtmstatus.mdx' +import PublishOptions from './shared/_publishoptions.mdx'; + +Sending and receiving messages is the most basic function of the Signaling service. Any message sent by the Signaling server can be delivered to any online subscribing user within 100 ms. Depending on your business requirements, you can send messages to one user only or broadcast messages to multiple users. + +Signaling offers two types of channels: message channels and stream channels. These channel types have the following differences in how messages are transmitted and methods are called: + +- Message Channel: The real-time channel. Messages are transmitted through the channel, and the channel is highly scalable. Local users can call the {message.publish[props.ag_platform]} method to send messages in the channel, and remote users can call the {channel.subscribe[props.ag_platform]} method to subscribe to the channel and receive messages. +- Stream Channel: The streaming transmission channel. Messages are transmitted through the topic. Users need to join a channel first, and then join a topic. Local users can call the {topic.publish[props.ag_platform]} method to send messages in the topic, and remote users can call the {topic.subscribe[props.ag_platform]} method to subscribe to the topic and receive messages. + +This page introduces how to send and receive messages in a Message Channel. + +### {message.publish[props.ag_platform]} + +#### Description + +You can directly call the {message.publish[props.ag_platform]} method to send messages to all online users who subscribe to the channel. Even if you do not subscribe to a channel, you can still send messages in the channel. + +The following practices can effectively improve the reliability of message transmission:
    • The message payload should be within 32 KB; otherwise, the sending will fail.
    • The upper limit of the rate at which messages are sent to a single channel is 30 QPS. If the sending rate exceeds the limit, some messages will be discarded. A lower rate is better, as long as the requirements are met.
    • Signaling does not guarantee that the order in which all subscribers receive messages is the same as the order in which the sender sends messages. To ensure that messages are strictly ordered, Agora suggests that you customize the message sequence number in the message payload.
    + +After successfully calling this method, the SDK triggers a {config.onmessageevent[props.ag_platform]} event notification. Users who subscribe to the channel and enabled the event listener can receive this event notification. For details, see Event Listener. + +#### Method + +You can call the {message.publish[props.ag_platform]} method in the following way: + +```javascript +rtm.publish( + channelName: string, + message: string | Uint8Array, + options?: {customType?: string;} +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :---------------: | :------: | :-----: | :----------------------------------------------------------- | +| `message` | string \| Uint8Array | Required | - | The message payload. Supports string or Uint8Array type. | +| `channelName` | string | Required | - | The channel name. You can only send messages to one channel at a time. | +| `options` | object | Optional | - | The message options. | + +The `options` object includes the following property: + +| Property | Type | Required | Default | Description | +| :----------: | :----: | :------: | :-----: | :----------------------------------------------- | +| `customType` | string | Optional | - | A user-defined field. Only supports string type. | + +#### Basic usage + +Example 1: Send string messages to a specified channel. + +```javascript +try { + const result = await rtm.publish( 'my_channel', "Hello world" ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +Example 2: Send Uint8Array messages to a specified channel. + +```javascript +const str2ab = function(str) { + var buf = new ArrayBuffer(str.length * 2); // Each character occupies 2 bytes. + var bufView = new Uint16Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +}; +var Message=str2ab('hello world'); +try { + const result = await rtm.publish('my_channel', Message ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +After successfully calling this method, the SDK triggers a {config.onmessageevent[props.ag_platform]} event notification. Users who subscribe to the channel and enable event listener can receive this event notification. For details, see Event Listener. + +#### Return value + +If the method call succeeds, the {message.publishresulttype[props.ag_platform]} response as follows is returned: + +```js +type PublishResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + chanelName : string // Channel name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + +### Receive + +Signaling provides event notifications for messages, states, and event changes. By setting event listeners, you can receive messages and events in subscribed channels. + +For information on how to add and set event listeners, see Event Listener. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_presence-en.javascript.mdx b/shared/signaling/reference/api-ref/_presence-en.javascript.mdx new file mode 100644 index 000000000..2b4faf0bc --- /dev/null +++ b/shared/signaling/reference/api-ref/_presence-en.javascript.mdx @@ -0,0 +1,272 @@ +import * as presence from './shared/_presence.mdx' +import * as storage from './shared/_storage.mdx' +import * as config from './shared/_configuration.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' +import Stateitem from './shared/_stateitem.mdx' + + +The presence feature provides the ability to monitor user online, offline, and user historical state change. With the Presence feature, you can get real-time access to the following information: + +- Real-time event notification when a user joins or leaves a specified channel. +- Real-time event notification when the custom temporary user state changes. +- Query which channels a specified user has joined or subscribed to. +- Query which users have joined a specified channel and their temporary user state data. + + + +**Presence** applies to both message channels and stream channels. + + + +### {presence.whonow[props.ag_platform]} + +#### Description + +Call the {presence.whonow[props.ag_platform]} method to query user information in real time such as the number of online users, the list of online users and their temporary user status in the specified channel. + +#### Method + +You can call the {presence.whonow[props.ag_platform]} method in the following way: + +```javascript +rtm.presence.getOnlineUsers( + channelName: string, + channelType: string, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `options` | object | Optional | - | Query options. | + +options contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------------: | :-----: | :------: | :-----: | ------------------------------------------------------------------------------------- | +| `includedUserId` | boolean | Optional | `true` | Whether the returned result contains the user ID of online users. | +| `includedState` | boolean | Optional | `false` | Whether the returned result contains the temporary user state of online users. | +| `page` | string | Optional | - | Page number of the returned result. If you do not provide this property, the SDK returns the first page by default. You can check whether there is next page in the `nextPage` property of the returned result. | + +#### Basic Usage + +```javascript +const options = { + includeUserId : true , + includeState : true, + page : "yourBookMark" +} +try{ + const result = await rtm.presence.getOnlineUsers( "chat_room", 'MESSAGE', options ); + console.log(result); +} catch(status){ + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {presence.whonowresulttype[props.ag_platform]} response as follows is returned: + +```js +type getOnlineUsersResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + totalOccupancy : number , // Number of the online users in the channel. + occupants : Array , // List of the online users in the channel and their temporary user state. + nextPage : string // Page number of the next page. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + + +### {presence.wherenow[props.ag_platform]} + +#### Description + +In scenarios such as statistic analytics and debugging, you may need to know all the channels that a specified user has subscribed to or joined. Call the {presence.wherenow[props.ag_platform]} method to get the list of channels where the specified user is in real time. + +#### Method + +You can call the {presence.wherenow[props.ag_platform]} method in the following way: + +```js +rtm.presence.getUserChannels(userId: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :------: | :----: | :------: | :-----------------: | :-------- | +| `userId` | string | Required | - | User ID. | + +#### Basic Usage + +```js +try{ + const result = await rtm.presence.whereNow( "Tony" ); + console.log(result); +} catch(status){ + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {presence.wherenowresulttype[props.ag_platform]} response as follows is returned: + +```js +type GetUserChannelsResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + totalChannel : number , // Number of the channels that the user has joined or subscribed to. + channels : Array // List of the channels including channel name and channel type. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {presence.setstate[props.ag_platform]} + +#### Description + + +To meet different requirements in different business scenarios for setting user states, Signaling provides the {presence.setstate[props.ag_platform]} method to customize the temporary user state. Users can add custom statuses such as scores, game status, location, mood, and hosting status for themselves. + +The {presence.setstate[props.ag_platform]} method sets temporary user state. It means these user states remains in the channel as long as the user stays subscribed to the channel and stays online, and they disappear when the user leaves the channel or disconnects from Signaling. To restore user states when rejoining a channel or reconnecting, cache the data locally in real time. To permanently save user states, Agora recommends you use the {storage.setuser[props.ag_platform]} method of the storage function instead. + +If a user modifies the temporary user status, Signaling triggers the {config.onpresenceevent[props.ag_platform]} event notification of the {enumv.presencetypechange[props.ag_platform]} type in real time . You can receive the event by subscribing to the channel and configuring the corresponding property. + +#### Method + +Set the temporary user state in the following way: + +```javascript +rtm.presence.setState( + channelName: string, + channelType: string, + state: object +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `state` | object | Required | - | A JSON object that consists of key-value pairs. The key must be string type. | + +#### Basic Usage + +```js +var newState = { "mood":"pumped", "isTyping":false}; + +try{ + const result = await rtm.Presence.setState("chat_room", "MESSAGE", newState); + console.log(result); +} catch(status){ + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {presence.setstateresulttype[props.ag_platform]} response as follows is returned: + +```js +type SetStateResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + +### {presence.getstate[props.ag_platform]} + +#### Description + +To get the temporary user state of a specified user in the channel, you can use the {presence.getstate[props.ag_platform]} method. + +#### Method + +Get the temporary user state in the following way: + +```js +rtm.presence.getState( + userId: string, + channelName: string, + channelType: string, +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------ | +| `userId` | string | Required | - | User ID. | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | + +#### Basic Usage + +```js +try{ + const result = await rtm.presence.getState("Tony", "chat_room", "MESSAGE" ); + const.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {presence.getstateresulttype[props.ag_platform]} response as follows is returned: + +```js +type GetStateResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. + states : object , // Key-value pairs of the user states. + statesCount : number // Numbers of the user states. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {presence.removestate[props.ag_platform]} + +#### Description + +When a temporary user state is no longer needed, you can call the {presence.removestate[props.ag_platform]} method to remove it. When the user state is removed, the user who has subscribed to the channel and enabled the presence event monitoring receives the {config.onpresenceevent[props.ag_platform]} notification in the {enumv.presencetypechange[props.ag_platform]} type. + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------ | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel types](#channel-types) | +| `options` | object | Optional | - | The list of keys of the user states that you want to remove. If you do not provide this parameter, all the user states are removed. | + + +#### Basic Usage + +```js +const options = { + states:["mode","Typing"] +} +try{ + const result = await rtm.Presence.removeState("chat_room", "MESSAGE" , options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return Value + +If the method call succeeds, the {presence.removestateresulttype[props.ag_platform]} response as follows is returned: + +```js +type RemoveStateResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_storage-en.javascript.mdx b/shared/signaling/reference/api-ref/_storage-en.javascript.mdx new file mode 100644 index 000000000..c083edd23 --- /dev/null +++ b/shared/signaling/reference/api-ref/_storage-en.javascript.mdx @@ -0,0 +1,745 @@ +import * as storage from './shared/_storage.mdx' +import * as config from './shared/_configuration.mdx' +import * as lock from './shared/_lock.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' + +The storage feature provides a dynamic database mechanism that allows developers to dynamically set, store, update, and delete data such as channel metadata and user metadata. + +### {storage.setchannel[props.ag_platform]} + +#### Description + +The {storage.setchannel[props.ag_platform]} method sets metadata for a message channel or stream channel. A channel can only have one set of metadata, but each set of metadata can have one or more metadata items. If you call this method multiple times, the SDK retrieves the `key` of the metadata items in turn and apply settings according to the following rules: + +- If you set metadata with different `key`, the SDK adds each set of metadata in sequence according to the order of the method calls. +- If you set metadata with the same `key`, the `value` of the last setting overwrites the previous one. + +After successfully setting channel metadata, users who subscribe to the channel and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypechannel[props.ag_platform]} type. For details, see Event Listener. + +Channel metadata also introduces the version control logic CAS (Compare And Set). This method provides two independent version control fields, and you can set one or more of them according to your actual business scenario: + +- Enable version number verification for the entire set of channel metadata by setting the `majorRevision` property in the `options` parameter. +- Enable version number verification for a single metadata item by setting the `revision` property in the `data` parameter. + +When setting channel metadata or metadata items, you can control whether to enable version number verification by specifying the revision property: + +- The default value of the revision property is `-1`, indicating that no CAS verification is performed for this method call. If the channel metadata or metadata item already exists, the latest value overwrites the previous one. If the channel metadata or metadata item does not exist, the SDK creates it. +- If the revision property is a positive integer, CAS verification is performed for this method call. If the channel metadata or metadata item already exists, the SDK updates the corresponding value after the version number verification succeeds. If the channel metadata or metadata item does not exist, the SDK returns the error code. + +#### Method + +You can call the {storage.setchannel[props.ag_platform]} method in the following way: + + +```js +rtm.storage.setChannelMetadata( + channelName: string, + channelType: string, + data: Array, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `options` | object | Optional | - | Options for setting metadata. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +#### Basic usage + + +```js +const data = [ + { + key : "Apple", + value : "100" + revision : 174298200 + }, + { + key : "Banana", + value : "200", + revision : 174298100 + } +]; +const options = { + majorRevision : 174298270, + lockName: "lockName", + addTimeStamp : ture, + addUserId : true +}; +try { + const result = await rtm.storage.setChannelMetadata( "channel_name", "MESSAGE", data, options ); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the SetChannelMetadataResponse response as follows is returned: + +```js +type SetChannelMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + totalCount : number // Number of metadata items. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.getchannel[props.ag_platform]} + +#### Description + +The {storage.getchannel[props.ag_platform]} method obtains the metadata of the specified channel. + +#### Method + +You can call the {storage.getchannel[props.ag_platform]} method in the following way: + +```js +rtm.storage.getChannelMetadata( + channelName: string, + channelType: string +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | + +#### Basic usage + + +```js +try { + const result = await rtm.storage.getChannelMetadata("channel_name", "MESSAGE"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the GetChannelMetadataResponse response as follows is returned: + +```js +type GetChannelMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + totalCount : number , // Number of metadata items. + majorRevision : number , // Version of metadata. + metadata : Record // JSON object containing metadata item. +} +``` + +`MetaDataDetail` contains the following properties: + +```js +type MetaDataDetail = { + value: string , // Value of a metadata item. + revision : number , // Version of a metadata item. + updated : string , // Timestamp of the last update. + authorUid : string , // User ID of the last editor. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.removechannel[props.ag_platform]} + +#### Description + +Call the {storage.removechannel[props.ag_platform]} method to remove channel metadata or metadata items. + +When removing channel metadata or metadata items, you can control whether to enable version number verification by specifying the revision property: + +- The default value of the revision property is `-1`, indicating that no CAS verification is performed for this method call. If the channel metadata or metadata item already exists, the SDK removes it. If the channel metadata or metadata item does not exist, the SDK returns the error code. +- If the revision property is a positive integer, CAS verification is performed for this method call. If the channel metadata or metadata item already exists, the SDK removes the corresponding value after the version number verification succeeds. If the channel metadata or metadata item does not exist, the SDK returns the error code. + +After successfully removing channel metadata or metadata items, users who subscribe to the channel and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypechannel[props.ag_platform]} type. For details, see Event Listener. + +#### Method + +You can call the {storage.removechannel[props.ag_platform]} method in the following way: + + +```js +rtm.storage.removeChannelMetadata( + channelName: string, + channelType: string, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `options` | object | Optional | - | Options for setting metadata. | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +#### Basic usage + + +```js +const data = [ + { + key : "Apple", + revision : 174298200 + } +]; +const options = { + data : data, + majorRevision : 174298270, +}; +try { + const result = await rtm.storage.removeChannelMetadata("channel_name", "MESSAGE", options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value +If the method call succeeds, the RemoveChannelMetadataResponse response as follows is returned: + +```js +type RemoveChannelMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + totalCount : number // Number of metadata items. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.updatechannel[props.ag_platform]} + +#### Description + +The {storage.updatechannel[props.ag_platform]} method can update existing channel metadata. Each time you call this method, you can update one channel metadata or an array of channel metadata items. + +After successfully updating, users who subscribe to the channel and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypechannel[props.ag_platform]} type. For details, see Event Listener. + +You cannot use this method to update metadata items which do not exist. + +#### Method + +You can call the {storage.updatechannel[props.ag_platform]} method in the following way: + +```js +rtm.storage.updateChannelMetadata( + channelName: string, + channelType: string, + data: Array, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `channelName` | string | Required | - | Channel name. | +| `channelType` | string | Required | - | Channel type. For details, see [Channel Types](#channel-types). | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `options` | object | Optional | - | Options for setting metadata. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +#### Basic usage + +```js +const data = [ + { + key : "Apple", + value : "120" + revision : 174298200 + }, + { + key : "Banana", + value : "220", + revision : 174298100 + } +]; +const options = { + majorRevision : 174298270, + addTimeStamp : ture, + addUserId : true +}; +try { + const result = await rtm.storage.updateChannelMetadata("channel_name", "MESSAGE", data, options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value +If the method call succeeds, the UpdateChannelMetadataResponse response as follows is returned: + +```js +type UpdateChannelMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + channelName : string , // Channel name. + channelType : string , // Channel type. + totalCount : number // Number of metadata items. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.setuser[props.ag_platform]} + +#### Description + +The {storage.setuser[props.ag_platform]} method sets metadata for a user. A user can only have one set of metadata, but each set of metadata can have one or more metadata items. If you call this method multiple times, the SDK retrieves the `key` of the metadata items in turn and apply settings according to the following rules: + +- If you set metadata with different `key`, the SDK adds each set of metadata in sequence according to the order of the method calls. +- If you set metadata with the same `key`, the `value` of the last setting overwrites the previous one. + +After successfully setting user metadata, users who subscribe to the user metadata and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypeuser[props.ag_platform]} type. For details, see Event Listener. + +User metadata also introduces the version control logic CAS (Compare And Set). This method provides two independent version control fields, and you can set one or more of them according to your actual business scenario: + +- Enable version number verification for the entire set of user metadata by setting the `majorRevision` property in the `options` parameter. +- Enable version number verification for a single metadata item by setting the `revision` property in the `data` parameter. + +When setting user metadata or metadata items, you can control whether to enable version number verification by specifying the revision property: + +- The default value of the revision property is `-1`, indicating that no CAS verification is performed for this method call. If the user metadata or metadata item already exists, the latest value overwrites the previous one. If the user metadata or metadata item does not exist, the SDK creates it. +- If the revision property is a positive integer, CAS verification is performed for this method call. If the user metadata or metadata item already exists, the SDK updates the corresponding value after the version number verification succeeds. If the user metadata or metadata item does not exist, the SDK returns the error code. + +#### Method + +You can call the {storage.setuser[props.ag_platform]} method in the following way: + +```js +rtm.storage.setUserMetadata( + data: Array, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `options` | object | Optional | - | Options for setting metadata. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +#### Basic usage + + +```js +const data = [ + { + key : "Name", + value : "Tony" + revision : 174298200 + }, + { + key : "Mute", + value : "true", + revision : 174298100 + } +]; +const options = { + userId : 'Tony', + majorRevision : 174298270, + addTimeStamp : ture, + addUserId : true +}; +try { + const result = await rtm.storage.setUserMetadata(data, options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the SetUserMetadataResponse response as follows is returned: + +```js +type SetUserMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. + totalCount : number // Number of metadata items. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.getuser[props.ag_platform]} + +#### Description + +The {storage.getuser[props.ag_platform]} method obtains the metadata of the specified user. + +#### Method + +You can call the {storage.getuser[props.ag_platform]} method in the following way: + +```js +getUserMetadata(userId?: string): Promise; +``` +| Parameter | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | + +#### Basic usage + +```js +try { + const result = await rtm.storage.getUserMetadata(); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the GetChannelMetadataResponse response as follows is returned: + +```js +type GetChannelMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. + totalCount : number , // Number of metadata items. + majorRevision : number , // Version of metadata. + metadata : Record // JSON object containing metadata item. +} +``` + +`MetaDataDetail` contains the following properties: + +```js +type MetaDataDetail = { + value: string , // Value of a metadata item. + revision : number , // Version of a metadata item. + updated : string , // Timestamp of the last update. + authorUid : string , // User ID of the last editor. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.removeuser[props.ag_platform]} + +#### Description + +Call the {storage.removeuser[props.ag_platform]} method to remove user metadata or metadata items. + +After successfully removing user metadata or metadata items, users who subscribe to the user metadata and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypeuser[props.ag_platform]} type. For details, see Event Listener. + +#### Method + +You can call the {storage.removeuser[props.ag_platform]} method in the following way: + + +```js +rtm.storage.removeUserMetadata( + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `options` | object | Optional | - | Options for setting metadata. | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +#### Basic usage + + +```js +const data = [ + { + key : "Mute", + revision : 174298100 + } +]; +const options = { + userId: "Tony", + data : data, + majorRevision : 174298270 +}; +try { + const result = await rtm.storage.removeUserMetadata(options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value +If the method call succeeds, the RemoveUserMetadataResponse response as follows is returned: + +```js +type RemoveUserMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. + totalCount : number // Number of metadata items. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.updateuser[props.ag_platform]} + +#### Description + +The {storage.updateuser[props.ag_platform]} method can update existing user metadata. Each time you call this method, you can update one user metadata or an array of user metadata items. + +After successfully updating, users who subscribe to the user metadata and enable event listeners can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypeuser[props.ag_platform]} type. For details, see Event Listener. + +You cannot use this method to update metadata items which do not exist. + +#### Method + +You can call the {storage.updateuser[props.ag_platform]} method in the following way: + +```js +rtm.storage.updateUserMetadata( + data: Array, + options?: object +): Promise; +``` + +| Parameter | Type | Required | Default| Description | +| :-----------: | :----: | :------: | :----: | :-------------------------------- | +| `data` | Array\ | Required | - | An array of metadata items. A metadata item is a JSON object that includes predefined properties. You cannot set properties other than predefined ones in this object. | +| `options` | object | Optional | - | Options for setting metadata. | + +`data` contains the following properties: + +| Property | Type | Required | Default | Description | +| :--------: | :----: | :------: | :---------------: | :----------------------------------------------------------- | +| `key` | string | Required | - | The `key` of the metadata item. | +| `value` | string | Optional | Empty string `''` | The `value` of the metadata item. | +| `revision` | number | Optional | `-1` |
  • Returns the real version number in read operations.
  • Serves as a version control switch in write operations:
    • `-1`: Disable the version verification.
    • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
    | + +`options` contains the following properties: + +| Property | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | +| `majorRevision` | number | Optional | `-1` | A version control switch:
  • `-1`: Disable the version verification.
  • > `0`: Enable the version verification. Only operations that match the target version number can be performed.
  • | +| `lockName` | string | Optional | Empty string `''` | The name of the lock. If set, only users who call the {lock.acquire[props.ag_platform]} method to acquire the lock can perform operations. | +| `addTimeStamp` | boolean | Optional | `false` | Whether to record the timestamp of the edit. | +| `addUserId` | boolean | Optional | `false` | Whether to record the ID of the editor. | + +#### Basic usage + + +```js +const data = [ + { + key : "Mute", + value : "false", + revision : 174298100 + } +]; +const options = { + userId : 'Tony', + majorRevision : 174298270, + addTimeStamp : ture, + addUserId : true +}; +try { + const result = await rtm.storage.updateUserMetadata(data, options); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the UpdateUserMetadataResponse response as follows is returned: + +```js +type UpdateUserMetadataResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. + totalCount : number // Number of metadata items. +} +``` +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {storage.subscribeuser[props.ag_platform]} + +#### Description + +The {storage.subscribeuser[props.ag_platform]} method can subscribe to metadata for a specified user. After successfully subscribing and enabling event listeners, you can receive the {config.onstorageevent[props.ag_platform]} event notification with the {enumv.storagetypeuser[props.ag_platform]} type when the metadata for that user changes. For details, see Event Listener. + +#### Method + +You can call the {storage.subscribeuser[props.ag_platform]} method in the following way: + +```js +subscribeUserMetadata(userId: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | + +#### Basic usage + + +```js +try { + const result = await rtm.storage.subscribeUserMetadata("Tony"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + +#### Return value +If the method call succeeds, the SubscribeUserMetaResponse response as follows is returned: + +```js +type SubscribeUserMetaResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. +} +``` + +### {storage.unsubscribeuser[props.ag_platform]} + +#### Description + +To stop receiving notifications of changes to a user metadata, call the {storage.unsubscribeuser[props.ag_platform]} method to unsubscribe. + +#### Method + +You can call the {storage.unsubscribeuser[props.ag_platform]} method in the following way: + +```js +rtm.storage.unsubscribeUserMetadata(userId: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-------------: | :-----: | :------: | :---------------: | :----------------------------------------------------------- | +| `userId` | string | Optional | The `userId` of the current user. | The user ID. | + +#### Basic usage + +```js +try { + const result = await rtm.storage.unsubscribeUserMetadata("Tony"); + console.log("result"); +} catch (status) { + console.log(status); +} +``` +#### Return value + +If the method call succeeds, the UnsubscribeUserMetaResponse response as follows is returned: + +```js +type UnsubscribeUserMetaResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + userId : string , // User ID. +} +``` \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/_topic-en.javascript.mdx b/shared/signaling/reference/api-ref/_topic-en.javascript.mdx new file mode 100644 index 000000000..fee4a6908 --- /dev/null +++ b/shared/signaling/reference/api-ref/_topic-en.javascript.mdx @@ -0,0 +1,344 @@ +import * as channel from './shared/_channel.mdx' +import * as topic from './shared/_topic.mdx' +import * as config from './shared/_configuration.mdx' +import * as enumv from './shared/_enumv.mdx' +import Status from './shared/_rtmstatus.mdx' + +Topic is a data stream management mechanism in stream channels. Users use topics to subscribe to and distribute data streams, as well as notify events in data streams in stream channels. + +Topics only exist in stream channels. Therefore, before using relevant features, users need to create an {channel.istreamchannel[props.ag_platform]} instance. + + +### {topic.join[props.ag_platform]} + +#### Description + +The purpose of joining a topic is to register as one of the message publishers for the topic, so that the user can send messages in the topic. This operation does not affect whether or not the user becomes a subscriber to the topic. + +Currently, Signaling supports a single client joining up to 8 topics in the same stream channel at a time. + +Before joining a topic, a user need to create an {channel.istreamchannel[props.ag_platform]} instance and call the {channel.join[props.ag_platform]} method to join the stream channel. For details, see Channels. + +After successfully joining a topic, users who subscribe to that topic and add event listeners can receive the {config.ontopicevent[props.ag_platform]} event notification with the {enumv.topictypejoin[props.ag_platform]} type. For details, see Event Listener. + +#### Method + +You can call the {topic.join[props.ag_platform]} method in the following way: + +```javascript +joinTopic( + topicName: string, + options?: { meta?: any } +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :----: | :------: | :-----: | :----------------------: | +| `topicName` | string | Yes | - | The topic name. | +| `options` | object | Optional | - | The reserved property. | + +#### Basic usage + +```js +try{ + const result = await stChannel.joinTopic( "gesture", options); + console.log( result); +} catch (status) { + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the JoinTopicResponse response as follows is returned: + +```js +type JoinTopicResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + topicName: string // Topic name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + + + +### {topic.publish[props.ag_platform]} + +#### Description + +Call the {topic.publish[props.ag_platform]} method to send messages to a topic. Users who subscribe to this topic and the message publisher in the channel can receive the message within 100 ms. Before calling the {topic.publish[props.ag_platform]} method, users need to join the stream channel, and then register as a message publisher for that topic by calling the {topic.join[props.ag_platform]} method. + +The messages sent by users are encrypted with TLS during transmission, and data link encryption is enabled by default and cannot be disabled. To achieve a higher level of data security, users can also enable client encryption during initialization. For details, see Setup. + +#### Method + +You can call the {topic.publish[props.ag_platform]} method in the following way: + +```javascript +publishTopicMessage( + topicName: string, + message: string | Uint8Array, + options?: {customType?: string;} +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :---------------: | :------: | :-----: | :----------------------------------------------------------- | +| `topicName` | string | Required | - | The topic name. | +| `message` | string \| Uint8Array | Required | - | The message payload. Supports string or Uint8Array type. | +| `options` | object | Optional | - | The message options. | + +The `options` object includes the following property: + +| Property | Type | Required | Default | Description | +| :----------: | :----: | :------: | :-----: | :----------------------------------------------- | +| `customType` | string | Optional | - | A user-defined field. Only supports string type. | + +#### Basic usage + +Example 1: Send string messages to a specified channel. + +```javascript +try{ + const result = await stChannel.publishTopicMessage( "Gesture", JSON.stringify({such: 'object'}) ); + console.log(result); +} catch (status){ + console.log(status); +} +``` + +Example 2: Send Uint8Array messages to a specified channel. + +```javascript +const str2ab = function(str) { + var buf = new ArrayBuffer(str.length * 2); // Each character occupies 2 bytes. + var bufView = new Uint16Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} +var Message=str2ab('hello world') +try{ + const result = await stChannel.publishTopicMessage( "Gesture",Message); + console.log(result); +} catch (status){ + console.log(status); +} +``` + +#### Return value + + +If the method call succeeds, the {topic.publishresulttype[props.ag_platform]} response as follows is returned: + +```js +type PublishTopicMessageResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + topicName: string // Topic name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + + + +### {topic.leave[props.ag_platform]} + +#### Description + +To release resources when you no longer need to publish messages to a topic, you can call the {topic.leave[props.ag_platform]} method to unregister as a message publisher for that topic. This method does not affect whether or not you subscribe to that topic or any other operations performed by other users on that topic. + +After successfully calling this method, users who subscribe to the channel and enable event listeners can receive the {config.ontopicevent[props.ag_platform]} event notification with the {enumv.topictypeleave[props.ag_platform]} type. For details, see Event Listener. + +#### Method + +You can call the {topic.leave[props.ag_platform]} method in the following way: + +```javascript +leaveTopic(topicName: string): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :---------------: | :------: | :-----: | :----------------------------------------------------------- | +| `topicName` | string | Required | - | The topic name. | + +#### Basic usage + +```js +try{ + const result = await stChannel.leaveTopic("gesture"); + console.log(result); +} catch (status) { + console.log(status); +} +``` + + + + +#### Return value + +If the method call succeeds, the {topic.leaveresulttype[props.ag_platform]} response as follows is returned: + +```js +type LeaveTopicResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. + topicName: string // Topic name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + + + +### {topic.subscribe[props.ag_platform]} + +#### Description + +After joining a channel, you can call the {topic.subscribe[props.ag_platform]} method to subscribe to message publishers of topics in the channel. + +{topic.subscribe[props.ag_platform]} is an incremental method. For example, if you call this method for the first time with a subscribing list of [UserA, UserB], and then call it again with a subscribing list of [UserB, UserC], the final successful subscribing result is [UserA, UserB, UserC]. + +There is no limit to the number of message publishers that can be registered for a single topic in a channel, but a user can only subscribe to a maximum of 50 topics at the same time in the same channel, and a maximum of 64 message publishers in each topic. For more details, see API Usage Limits. + +#### Method + +You can call the {topic.subscribe[props.ag_platform]} method in the following way: + +```javascript +subscribeTopic( + topicName: string, + options?: { + users?: string[]; + } +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :---------------: | :------: | :-----: | :----------------------------------------------------------- | +| `topicName` | string | Required | - | The topic name. | +| `options` | object | Optional | - | The subscribing options. | + +The `options` object includes the following property: + +| Property | Type | Required | Default | Description | +| :----------: | :----: | :------: | :-----: | :----------------------------------------------- | +| `users` | string[] | Optional | - | A list of user IDs of message publishers that you want to subscribe to. If you do not set this property, you can randomly subscribe to up to 64 users by default. | + +#### Basic usage + +Example 1: Subscribe to a specified message publisher in a topic. + +```javascript +var UIDs = ["zhangsan","lisi","wangwu"] +try{ + const result = await rtm.subscribeTopic( "Gesture", { users:UIDs } ); + console.log(result); +} catch (status){ + console.log( status); +} +``` + +Example 2: Randomly subscribe to 64 message publisher in a topic. + +```javascript +try{ + const result = await stChannel.subscribeTopic("Gesture"); + console.log(result); +}catch(status){ + console.log(status); +} +``` + +#### Return value + +If the method call succeeds, the {topic.subscriberesulttype[props.ag_platform]} response as follows is returned: + +```js +type SubscribeTopicResponse = { + succeedUsers : string[] , // A list of users who successfully subscribe to the topic. + failedUsers : string[], // A list of users who fail to subscribe to the topic. + failedDetails : [ // A list of reasons for subscription failure. + { + user : string , // User ID. + errorCode : number , // Error code. + reason : string // Reason for the error. + }, + ], + timeToken : number, // Reserved property, indicating the timestamp of the successful operation. + topiclName : string // Topic name. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. + + +### {topic.unsubscribe[props.ag_platform]} + +#### Description + +Call the {topic.unsubscribe[props.ag_platform]} method to unsubscribe from the topic or unsubscribe from specific message publishers in the topic. + +#### Method + +You can call the {topic.unsubscribe[props.ag_platform]} method in the following way: + + +```javascript +unsubscribeTopic( + topicName: string, + options?: { users?: string[] } +): Promise; +``` + +| Parameter | Type | Required | Default | Description | +| :-----------: | :---------------: | :------: | :-----: | :----------------------------------------------------------- | +| `topicName` | string | Required | - | The topic name. | +| `options` | object | Optional | - | The unsubscribing options. | + +The `options` object includes the following property: + +| Property | Type | Required | Default | Description | +| :----------: | :----: | :------: | :-----: | :----------------------------------------------- | +| `users` | string[] | Optional | - | A list of user IDs of message publishers that you want to unsubscribe from. To unsubscribe from the entire topic, do not set this property. | + +#### Basic usage + +Example 1: Unsubscribe from a specified message publisher in a topic. + +```javascript +try{ + const result = await rtm.unsubscribeTopic( "Gesture", { users:["Tony","Bo"] }); + console.log("unsubscribe Topic success: ", result); +} catch (status) { + console.log("unsubscribe Topic failed: ", result); +} +``` + +Example 2: Randomly unsubscribe from 64 message publisher in a topic. + +```javascript +try{ + const result = await rtm.unsubscribeTopic("Gesture"); + console.log("unsubscribe topic success: ", result); +} catch (status) { + console.log("unsubscribe topic failed: ", result); +} +``` + +#### Return value + +If the method call succeeds, the {topic.unsubscriberesulttype[props.ag_platform]} response as follows is returned: + +```js +type UnsubscribeTopicResponse = { + timeToken: number , // Reserved property, indicating the timestamp of the successful operation. +} +``` + +If the method call fails, an [`ErrorInfo`](#errorinfo) response is returned. \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/index.mdx b/shared/signaling/reference/api-ref/index.mdx new file mode 100644 index 000000000..0e8c2a870 --- /dev/null +++ b/shared/signaling/reference/api-ref/index.mdx @@ -0,0 +1,3 @@ +import Web from './web.mdx'; + + \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_channel.mdx b/shared/signaling/reference/api-ref/shared/_channel.mdx new file mode 100644 index 000000000..d65bdafdd --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_channel.mdx @@ -0,0 +1,149 @@ +export const subscribe = { + android: "subscribe", + ios: "subscribeWithChannel", + javascript: "subscribe", + linux: "subscribe", + unity: "SubscribeAsync", +}; +export const unsubscribe = { + android: "unsubscribe", + ios: "unsubscribeWithChannel", + javascript: "unsubscribe", + linux: "unsubscribe", + unity: "UnsubscribeAsync", +}; +export const create = { + android: "createStreamChannel", + ios: "createStreamChannel", + javascript: "createStreamChannel", + linux: "createStreamChannel", + unity: "CreateStreamChannel", +}; +export const join = { + android: "join", + ios: "joinWithOption", + javascript: "join", + linux: "join", + unity: "JoinAsync", +}; +export const leave = { + android: "leave", + ios: "leave", + javascript: "leave", + linux: "leave", + unity: "LeaveAsync", +}; +export const release = { + android: "release", + ios: "destroy", + javascript: "/", + linux: "releaseChannel", + unity: "Dispose", +}; +// Parameters +export const uid = { + android: "userId", + ios: "userId", + javascript: "uid", + linux: "uid", + unity: "userId", +}; +export const options = { + android: "SubscribeOptions", + ios: "AgoraRtmSubscribeOptions", + javascript: "SubscribeOptions", + linux: "SubscribeOptions", + unity: "SubscribeOptions", +}; +export const joinchanneloptions = { + android: "JoinChannelOptions", + ios: "AgoraRtmJoinChannelOption", + javascript: "JoinChannelOptions", + linux: "JoinChannelOptions", + unity: "JoinChannelOptions", +}; +export const subscribeoptions = { + android: "SubscribeOptions", + ios: "AgoraRtmSubscribeOptions", + javascript: "SubscribeOptions", + linux: "SubscribeOptions", + unity: "SubscribeOptions", +}; +// Class +export const irtmclient = { + android: "RtmClient", + ios: "AgoraRtmClientKit", + javascript: "rtm", + linux: "IRtmClient", + unity: "IRtmClient", +}; +export const istreamchannel = { + android: "StreamChannel", + ios: "AgoraRtmStreamChannel", + javascript: "RTMStreamChannel", + linux: "IStreamChannel", + unity: "IStreamChannel", +}; +export const rtmstatus = { + android: "/", + ios: "/", + javascript: "/", + linux: "/", + unity: "RtmStatus", +}; +export const subscriberesulttype = { + android: "/", + ios: "/", + javascript: "SubscribeResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const subscriberesult = { + android: "/", + ios: "/", + javascript: "SubscribeResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "SubscribeResult", +}; +export const unsubscriberesulttype = { + android: "/", + ios: "/", + javascript: "UnsubscribeResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const unsubscriberesult = { + android: "/", + ios: "/", + javascript: "UnsubscribeResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "UnsubscribeResult", +}; +export const joinresulttype = { + android: "/", + ios: "/", + javascript: "JoinChannelResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const joinresult = { + android: "/", + ios: "/", + javascript: "JoinChannelResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "JoinResult", +}; +export const leaveresulttype = { + android: "/", + ios: "/", + javascript: "LeaveChannelResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const leaveresult = { + android: "/", + ios: "/", + javascript: "LeaveChannelResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "LeaveResult", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_configuration.mdx b/shared/signaling/reference/api-ref/shared/_configuration.mdx new file mode 100644 index 000000000..d26633beb --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_configuration.mdx @@ -0,0 +1,206 @@ +export const create = { + android: "create", + ios: "initWithConfig", + javascript: "createAgoraRtmClient", + linux: "createAgoraRtmClient", + unity: "CreateAgoraRtmClient", +}; +export const release = { + android: "release", + ios: "destroy", + javascript: "/", + linux: "release", + unity: "Dispose", +}; +export const login = { + android: "login", + ios: "loginByToken", + javascript: "login", + linux: "login", + unity: "LoginAsync", +}; +export const logout = { + android: "logout", + ios: "logout", + javascript: "logout", + linux: "logout", + unity: "LogoutAsync", +}; +export const adddelegate = { + android: "addEventListener", + ios: "addDelegate", + javascript: "addEventListener", + linux: "", + unity: "", +}; +export const removedelegate = { + android: "removeEventListener", + ios: "removeDelegate", + javascript: "removeEventListener", + linux: "", + unity: "", +}; +//callbacks +export const onpresenceevent = { + android: "onPresenceEvent", + ios: "didReceivePresenceEvent", + javascript: "presence", + linux: "OnPresenceEvent", + unity: "OnPresenceEvent", +}; +export const onmessageevent = { + android: "onMessageEvent", + ios: "didReceiveMessageEvent", + javascript: "message", + linux: "OnMessageEvent", + unity: "OnMessageEvent", +}; +export const ontopicevent = { + android: "onTopicEvent", + ios: "didReceiveTopicEvent", + javascript: "topic", + linux: "OnTopicEvent", + unity: "OnTopicEvent", +}; +export const onstorageevent = { + android: "onStorageEvent", + ios: "didReceiveStorageEvent", + javascript: "storage", + linux: "OnStorageEvent", + unity: "OnStorageEvent", +}; +export const onlockevent = { + android: "onLockEvent", + ios: "didReceiveLockEvent", + javascript: "lock", + linux: "OnLockEvent", + unity: "OnLockEvent", +}; +export const onconnection = { + android: "onConnectionStateChanged", + ios: "connectionChangedToState", + javascript: "status", + linux: "OnConnectionStateChange", + unity: "OnConnectionStateChange", +}; +export const ontokenwillexpire = { + android: "onTokenPrivilegeWillExpire", + ios: "tokenPrivilegeWillExpire", + javascript: "tokenPrivilegeWillExpire", + linux: "OnTokenPrivilegeWillExpire", + unity: "OnTokenPrivilegeWillExpire", +}; +// Class +export const rtmstatus = { + android: "/", + ios: "/", + javascript: "Status", + linux: "IRtmClient", + unity: "RtmStatus", +}; +export const errorinfo = { + android: "ErrorInfo", + ios: "AgoraRtmErrorInfo", + javascript: "ErrorInfo", + linux: "/", + unity: "/", +}; +export const loginresulttype = { + android: "ResultCallback", + ios: "/", + javascript: "LoginResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const loginresult = { + android: "ResultCallback", + ios: "/", + javascript: "LoginResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "LoginResult", +}; +export const logoutresulttype = { + android: "ResultCallback", + ios: "/", + javascript: "LogoutResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const logoutresult = { + android: "ResultCallback", + ios: "/", + javascript: "LogoutResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "LogoutResult", +}; +export const rtm = { + android: "RtmConfig", + ios: "AgoraRtmClientConfig", + javascript: "rtmConfig", + linux: "release", + unity: "RtmConfig", +}; +export const log = { + android: "RtmLogConfig", + ios: "AgoraRtmLogConfig", + javascript: "LogConfig", + linux: "release", + unity: "RtmLogConfig", +}; +export const proxy = { + android: "RtmProxyConfig", + ios: "AgoraRtmProxyConfig", + javascript: "RtmProxyConfig", + linux: "release", + unity: "RtmProxyConfig", +}; +export const encryption = { + android: "RtmEncryptionConfig", + ios: "AgoraRtmEncryptionConfig", + javascript: "RtmEncryptionConfig", + linux: "release", + unity: "RtmEncryptionConfig", +}; +export const messageevent = { + android: "MessageEvent", + ios: "AgoraRtmMessageEvent", + javascript: "MessageEvent", + linux: "MessageEvent", + unity: "MessageEvent", +}; +export const presenceevent = { + android: "PresenceEvent", + ios: "AgoraRtmPresenceEvent", + javascript: "PresenceEvent", + linux: "PresenceEvent", + unity: "PresenceEvent", +}; +export const topicevent = { + android: "TopicEvent", + ios: "AgoraRtmTopicEvent", + javascript: "TopicEvent", + linux: "TopicEvent", + unity: "TopicEvent", +}; +export const storageevent = { + android: "StorageEvent", + ios: "AgoraRtmStorageEvent", + javascript: "StorageEvent", + linux: "StorageEvent", + unity: "StorageEvent", +}; +export const lockevent = { + android: "LockEvent", + ios: "AgoraRtmLockEvent", + javascript: "lock", + linux: "LockEvent", + unity: "LockEvent", +}; +// param +export const rtmmessage = { + android: "RtmMessage", + ios: "AgoraRtmMessage", + javascript: "/", + linux: "/", + unity: "/", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_enumv.mdx b/shared/signaling/reference/api-ref/shared/_enumv.mdx new file mode 100644 index 000000000..d6fda03b3 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_enumv.mdx @@ -0,0 +1,905 @@ +export const channeltype = { + android: "RtmChannelType", + ios: "AgoraRtmChannelType", + javascript: "channelType", + linux: "RTM_CHANNEL_TYPE", + unity: "RTM_CHANNEL_TYPE", +}; +export const channeltypenone = { + android: "NONE", + ios: "AgoraRtmChannelTypeNone", + javascript: "NONE", + linux: "/", + unity: "/", +}; +export const channeltypemessage = { + android: "MESSAGE", + ios: "AgoraRtmChannelTypeMessage", + javascript: "MESSAGE", + linux: "RTM_CHANNEL_TYPE_MESSAGE", + unity: "MESSAGE", +}; +export const channeltypestream = { + android: "STREAM", + ios: "AgoraRtmChannelTypeStream", + javascript: "STREAM", + linux: "RTM_CHANNEL_TYPE_STREAM", + unity: "STREAM", +}; +export const channelerrorcode = { + android: "", + ios: "", + javascript: "", + linux: "", + unity: "RTM_CHANNEL_ERROR_CODE", +}; +export const operationerrorcode = { + android: "REMOTE_JOIN", + ios: "REMOTE_JOIN", + javascript: "/", + linux: "REMOTE_JOIN", + unity: "OPERATION_ERROR_CODE", +}; +export const remotejoinchannel = { + android: "REMOTE_JOIN", + ios: "REMOTE_JOIN", + javascript: "REMOTE_JOIN", + linux: "REMOTE_JOIN", + unity: "REMOTE_JOIN", +}; +export const remoteleavechannel = { + android: "REMOTE_LEAVE", + ios: "REMOTE_LEAVE", + javascript: "REMOTE_LEAVE", + linux: "REMOTE_LEAVE", + unity: "REMOTE_LEAVE", +}; +export const areacode = { + android: "RtmAreaCode", + ios: "AgoraRtmAreaCode", + javascript: "areaCodes", + linux: "REMOTE_JOIN", + unity: "RTM_AREA_CODE", +}; +export const areacodeglob = { + android: "GLOB", + ios: "AgoraRtmAreaCodeGLOB", + javascript: "GLOBAL", + linux: "AREA_CODE_GLOB", + unity: "GLOB", +}; +export const areacodein = { + android: "IN", + ios: "AgoraRtmAreaCodeIN", + javascript: "INDIA", + linux: "AREA_CODE_GLOB", + unity: "IN", +}; +export const areacodejp = { + android: "JP", + ios: "AgoraRtmAreaCodeJP", + javascript: "JAPAN", + linux: "AREA_CODE_GLOB", + unity: "JP", +}; +export const areacodeeu = { + android: "EU", + ios: "AgoraRtmAreaCodeEU", + javascript: "EUROPE", + linux: "AREA_CODE_GLOB", + unity: "EU", +}; +export const areacodena = { + android: "NA", + ios: "AgoraRtmAreaCodeNA", + javascript: "NORTH_AMERICA", + linux: "AREA_CODE_GLOB", + unity: "NA", +}; +export const areacodecn = { + android: "CN", + ios: "AgoraRtmAreaCodeCN", + javascript: "CHINA", + linux: "AREA_CODE_GLOB", + unity: "CN", +}; +export const areacodeas = { + android: "AS", + ios: "AgoraRtmAreaCodeAS", + javascript: "ASIA", + linux: "AREA_CODE_GLOB", + unity: "AS", +}; +export const areacodeoc = { + android: "/", + ios: "/", + javascript: "ios", + linux: "/", + unity: "/", +}; +export const areacodesa = { + android: "/", + ios: "/", + javascript: "SA", + linux: "/", + unity: "/", +}; +export const areacodeaf = { + android: "/", + ios: "/", + javascript: "AF", + linux: "/", + unity: "/", +}; +export const areacodekr = { + android: "/", + ios: "/", + javascript: "KR", + linux: "/", + unity: "/", +}; +export const areacodehkmc = { + android: "/", + ios: "/", + javascript: "HKMC", + linux: "/", + unity: "/", +}; +export const areacodeus = { + android: "/", + ios: "/", + javascript: "US", + linux: "/", + unity: "/", +}; +export const areacodeovs = { + android: "/", + ios: "/", + javascript: "OVS", + linux: "/", + unity: "/", +}; +export const loglevel = { + android: "RtmLogLevel", + ios: "AgoraRtmLogLevel", + javascript: "logLevel", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "RTM_LOG_LEVEL", +}; +export const loglevelnone = { + android: "NONE", + ios: "AgoraRtmLogLevelNone", + javascript: "none", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "NONE", +}; +export const loglevelinfo = { + android: "INFO", + ios: "AgoraRtmLogLevelInfo", + javascript: "info", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "INFO", +}; +export const loglevelwarn = { + android: "WARN", + ios: "AgoraRtmLogLevelWarn", + javascript: "warn", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "WARN", +}; +export const loglevelerror = { + android: "ERROR", + ios: "AgoraRtmLogLevelError", + javascript: "error", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "ERROR", +}; +export const loglevelfatal = { + android: "FATAL", + ios: "AgoraRtmLogLevelFatal", + javascript: "/", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "FATAL", +}; +export const logleveltrack = { + android: "/", + ios: "/", + javascript: "track", + linux: "/", + unity: "/", +}; +export const logleveldebug = { + android: "/", + ios: "/", + javascript: "debug", + linux: "/", + unity: "/", +}; +export const proxytype = { + android: "RtmProxyType", + ios: "AgoraRtmProxyType", + javascript: "/", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "RTM_PROXY_TYPE", +}; +export const proxytypenone = { + android: "NONE", + ios: "AgoraRtmProxyTypeNone", + javascript: "/", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "NONE", +}; +export const proxytypehttp = { + android: "HTTP", + ios: "AgoraRtmProxyTypeHttp", + javascript: "/", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "HTTP", +}; +export const encryptionmode = { + android: "RtmEncryptionMode", + ios: "AgoraRtmEncryptionMode", + javascript: "encryptionMode", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "RTM_ENCRYPTION_MODE", +}; +export const encryptionmodenone = { + android: "NONE", + ios: "AgoraRtmEncryptionNone", + javascript: "NONE", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "NONE", +}; +export const aesonetwoeight = { + android: "AES_128_GCM", + ios: "AgoraRtmEncryptionAES128GCM", + javascript: "AES_128_GCM", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "AES_128_GCM", +}; +export const aestwofivesix = { + android: "AES_256_GCM", + ios: "AgoraRtmEncryptionAES256GCM", + javascript: "AES_256_GCM", + linux: "AREA_CODE.AREA_CODE_GLOB", + unity: "AES_256_GCM", +}; +export const presencetype = { + android: "RtmPresenceEventType", + ios: "AgoraRtmPresenceEventType", + javascript: "eventType", + linux: "RTM_PRESENCE_EVENT_TYPE", + unity: "RTM_PRESENCE_EVENT_TYPE", +}; +export const presencetypenone = { + android: "NONE", + ios: "AgoraRtmPresenceEventTypeNone", + javascript: "NONE", + linux: "/", + unity: "NONE", +}; +export const presencetypesnap = { + android: "SNAPSHOT", + ios: "AgoraRtmPresenceEventTypeSnapshot", + javascript: "SNAPSHOT", + linux: "RTM_PRESENCE_EVENT_TYPE_SNAPSHOT", + unity: "SNAPSHOT", +}; +export const presencetypeint = { + android: "INTERVAL", + ios: "AgoraRtmPresenceEventTypeInterval", + javascript: "INTERVAL", + linux: "RTM_PRESENCE_EVENT_TYPE_INTERVAL", + unity: "INTERVAL", +}; +export const presencetypejoin = { + android: "REMOTE_JOIN", + ios: "AgoraRtmPresenceEventTypeRemoteJoinChannel", + javascript: "REMOTE_JOIN", + linux: "RTM_PRESENCE_EVENT_TYPE_REMOTE_JOIN_CHANNEL", + unity: "REMOTE_JOIN", +}; +export const presencetypeleave = { + android: "REMOTE_LEAVE", + ios: "AgoraRtmPresenceEventTypeRemoteLeaveChannel", + javascript: "REMOTE_LEAVE", + linux: "RTM_PRESENCE_EVENT_TYPE_REMOTE_LEAVE_CHANNEL", + unity: "REMOTE_LEAVE", +}; +export const presencetypetimeout = { + android: "REMOTE_TIMEOUT", + ios: "AgoraRtmPresenceEventTypeRemoteConnectionTimeout", + javascript: "REMOTE_TIMEOUT", + linux: "RTM_PRESENCE_EVENT_TYPE_REMOTE_CONNECTION_TIMEOUT", + unity: "REMOTE_TIMEOUT", +}; +export const presencetypechange = { + android: "REMOTE_STATE_CHANGED", + ios: "AgoraRtmPresenceEventTypeRemoteStateChanged", + javascript: "REMOTE_STATE_CHANGED", + linux: "RTM_PRESENCE_EVENT_TYPE_REMOTE_STATE_CHANGED", + unity: "REMOTE_STATE_CHANGED", +}; +export const presencetypeout = { + android: "ERROR_OUT_OF_SERVICE", + ios: "AgoraRtmPresenceEventTypeErrorOutOfService", + javascript: "ERROR_OUT_OF_SERVICE", + linux: "RTM_PRESENCE_EVENT_TYPE_REMOTE_STATE_CHANGED", + unity: "ERROR_OUT_OF_SERVICE", +}; +export const presenceselfjoin = { + android: "", + ios: "AgoraRtmPresenceTypeSelfJoinChannel", + javascript: "", + linux: "", + unity: "", +}; +export const topictype = { + android: "RtmTopicEventType", + ios: "AgoraRtmTopicEventType", + javascript: "eventType", + linux: "RTM_TOPIC_EVENT_TYPE", + unity: "RTM_TOPIC_EVENT_TYPE", +}; +export const topictypenone = { + android: "NONE", + ios: "AgoraRtmTopicEventTypeNone", + javascript: "NONE", + linux: "/", + unity: "NONE", +}; +export const topictypesnap = { + android: "SNAPSHOT", + ios: "AgoraRtmTopicEventTypeSnapshot", + javascript: "SNAPSHOT", + linux: "RTM_TOPIC_EVENT_TYPE_SNAPSHOT", + unity: "SNAPSHOT", +}; +export const topictypejoin = { + android: "REMOTE_JOIN", + ios: "AgoraRtmTopicEventTypeRemoteJoinTopic", + javascript: "REMOTE_JOIN", + linux: "RTM_TOPIC_EVENT_TYPE_REMOTE_JOIN_TOPIC", + unity: "REMOTE_JOIN", +}; +export const topictypeleave = { + android: "REMOTE_LEAVE", + ios: "AgoraRtmTopicEventTypeRemoteLeaveTopic", + javascript: "REMOTE_LEAVE", + linux: "RTM_TOPIC_EVENT_TYPE_REMOTE_LEAVE_TOPIC", + unity: "REMOTE_LEAVE", +}; +export const storagetype = { + android: "RtmStorageType", + ios: "AgoraRtmStorageType", + javascript: "storageType", + linux: "RTM_STORAGE_TYPE", + unity: "RTM_STORAGE_TYPE", +}; +export const storagetypenone = { + android: "NONE", + ios: "AgoraRtmStorageTypeNone", + javascript: "NONE", + linux: "/", + unity: "NONE", +}; +export const storagetypeuser = { + android: "USER", + ios: "AgoraRtmStorageTypeUser", + javascript: "USER", + linux: "RTM_STORAGE_TYPE_USER", + unity: "USER", +}; +export const storagetypechannel = { + android: "CHANNEL", + ios: "AgoraRtmStorageTypeChannel", + javascript: "CHANNEL", + linux: "RTM_STORAGE_TYPE_CHANNEL", + unity: "CHANNEL", +}; +export const storageeventtype = { + android: "RtmStorageEventType", + ios: "AgoraRtmStorageEventType", + javascript: "eventType", + linux: "/", + unity: "RTM_STORAGE_EVENT_TYPE", +}; +export const storageeventtypenone = { + android: "NONE", + ios: "AgoraRtmStorageEventTypeNone", + javascript: "NONE", + linux: "none", + unity: "NONE", +}; +export const storageeventtypeset = { + android: "SET", + ios: "AgoraRtmStorageEventTypeSet", + javascript: "SET", + linux: "none", + unity: "SET", +}; +export const storageeventtypesnap = { + android: "SNAPSHOT", + ios: "AgoraRtmStorageEventTypeSnapshot", + javascript: "SNAPSHOT", + linux: "none", + unity: "SNAPSHOT", +}; +export const storageeventtyperemove = { + android: "REMOVE", + ios: "AgoraRtmStorageEventTypeRemove", + javascript: "REMOVE", + linux: "none", + unity: "REMOVE", +}; +export const storageeventtypeupdate = { + android: "UPDATE", + ios: "AgoraRtmStorageEventTypeUpdate", + javascript: "UPDATE", + linux: "none", + unity: "UPDATE", +}; + +export const locktype = { + android: "RtmLockEventType", + ios: "AgoraRtmLockEventType", + javascript: "eventType", + linux: "RTM_LOCK_EVENT_TYPE", + unity: "RTM_LOCK_EVENT_TYPE", +}; +export const locktypenone = { + android: "NONE", + ios: "AgoraRtmLockEventTypeNone", + javascript: "NONE", + linux: "/", + unity: "NONE", +}; +export const locktypesnap = { + android: "SNAPSHOT", + ios: "AgoraRtmLockEventTypeSnapshot", + javascript: "SNAPSHOT", + linux: "RTM_LOCK_EVENT_TYPE_SNAPSHOT", + unity: "SNAPSHOT", +}; +export const locktypeset = { + android: "SET", + ios: "AgoraRtmLockEventTypeLockSet", + javascript: "SET", + linux: "RTM_LOCK_EVENT_TYPE_LOCK_SET", + unity: "SET", +}; +export const locktyperemoved = { + android: "REMOVED", + ios: "AgoraRtmLockEventTypeLockRemoved", + javascript: "REMOVED", + linux: "RTM_LOCK_EVENT_TYPE_LOCK_REMOVED", + unity: "REMOVED", +}; +export const locktypeacquired = { + android: "ACQUIRED", + ios: "AgoraRtmLockEventTypeLockAcquired", + javascript: "ACQUIRED", + linux: "RTM_LOCK_EVENT_TYPE_LOCK_ACQUIRED", + unity: "ACQUIRED", +}; +export const locktypereleased = { + android: "RELEASED", + ios: "AgoraRtmLockEventTypeLockReleased", + javascript: "RELEASED", + linux: "RTM_LOCK_EVENT_TYPE_LOCK_RELEASED", + unity: "RELEASED", +}; +export const locktypeexpired = { + android: "EXPIRED", + ios: "AgoraRtmLockEventTypeLockExpired", + javascript: "EXPIRED", + linux: "RTM_LOCK_EVENT_TYPE_LOCK_REVOKED", + unity: "EXPIRED", +}; +export const locktyperevoked = { + android: "", + ios: "", + javascript: "", + linux: "", + unity: "", +}; +export const connectionstate = { + android: "RtmConnectionState", + ios: "AgoraRtmClientConnectionState", + javascript: "state", + linux: "RTM_CONNECTION_STATE", + unity: "RTM_CONNECTION_STATE", +}; +export const sdkdisconnect = { + android: "DISCONNECTED", + ios: "AgoraRtmClientConnectionStateDisconnected", + javascript: "DISCONNECTED", + linux: "RTM_CONNECTION_STATE_DISCONNECTED", + unity: "DISCONNECTED", +}; +export const sdkconnecting = { + android: "CONNECTING", + ios: "AgoraRtmClientConnectionStateConnecting", + javascript: "CONNECTING", + linux: "RTM_CONNECTION_STATE_CONNECTING", + unity: "CONNECTING", +}; +export const sdkconnected = { + android: "CONNECTED", + ios: "AgoraRtmClientConnectionStateConnected", + javascript: "CONNECTED", + linux: "RTM_CONNECTION_STATE_CONNECTED", + unity: "CONNECTED", +}; +export const sdkreconnect = { + android: "RECONNECTING", + ios: "AgoraRtmClientConnectionStateReconnecting", + javascript: "RECONNECTING", + linux: "RTM_CONNECTION_STATE_RECONNECTING", + unity: "RECONNECTING", +}; +export const sdkfailed = { + android: "FAILED", + ios: "AgoraRtmClientConnectionStateFailed", + javascript: "FAILED", + linux: "RTM_CONNECTION_STATE_FAILED", + unity: "FAILED", +}; +export const connectionreason = { + android: "RtmConnectionChangeReason", + ios: "AgoraRtmClientConnectionChangeReason", + javascript: "reason", + linux: "RTM_CONNECTION_CHANGE_REASON", + unity: "RTM_CONNECTION_CHANGE_REASON", +}; +export const reasonconnecting = { + android: "CONNECTING", + ios: "AgoraRtmClientConnectionChangedConnecting", + javascript: "CONNECTING", + linux: "RTM_CONNECTION_CHANGE_CONNECTING", + unity: "CONNECTING", +}; +export const reasonjoinsuccess = { + android: "JOIN_SUCCESS", + ios: "AgoraRtmClientConnectionChangedJoinSuccess", + javascript: "none", + linux: "RTM_CONNECTION_CHANGE_JOIN_SUCCESS", + unity: "JOIN_SUCCESS", +}; +export const reasonloginsuccess = { + android: "LOGIN_SUCCESS", + ios: "AgoraRtmClientConnectionChangedLoginSuccess", + javascript: "LOGIN_SUCCESS", + linux: "/", + unity: "/", +}; +export const reasoninterrupt = { + android: "INTERRUPTED", + ios: "AgoraRtmClientConnectionChangedInterrupted", + javascript: "INTERRUPTED'", + linux: "RTM_CONNECTION_CHANGE_INTERRUPTED", + unity: "INTERRUPTED", +}; +export const reasonban = { + android: "BANNED_BY_SERVER", + ios: "AgoraRtmClientConnectionChangedBannedByServer", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_BANNED_BY_SERVER", + unity: "BANNED_BY_SERVER", +}; +export const reasonjoinfail = { + android: "JOIN_FAILED", + ios: "AgoraRtmClientConnectionChangedJoinFailed", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_JOIN_FAILED", + unity: "JOIN_FAILED", +}; +export const reasonleave = { + android: "LEAVE_CHANNEL", + ios: "AgoraRtmClientConnectionChangedLeaveChannel", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_LEAVE_CHANNEL", + unity: "LEAVE_CHANNEL", +}; +export const reasonlogout = { + android: "LOGOUT", + ios: "AgoraRtmClientConnectionChangedLogout", + javascript: "LOGOUT", + linux: "/", + unity: "LOGOUT", +}; +export const reasoninvalidid = { + android: "INVALID_APP_ID", + ios: "AgoraRtmClientConnectionChangedInvalidAppId", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_INVALID_APP_ID", + unity: "INVALID_APP_ID", +}; +export const reasoninvalidchannel = { + android: "INVALID_CHANNEL_NAME", + ios: "AgoraRtmClientConnectionChangedInvalidChannelName", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_INVALID_CHANNEL_NAME", + unity: "INVALID_CHANNEL_NAME", +}; +export const reasoninvalidtoken = { + android: "INVALID_TOKEN", + ios: "AgoraRtmClientConnectionChangedInvalidToken", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_INVALID_TOKEN", + unity: "INVALID_TOKEN", +}; +export const reasontokenexpired = { + android: "TOKEN_EXPIRED", + ios: "AgoraRtmClientConnectionChangedTokenExpired", + javascript: "TOKEN_EXPIRED", + linux: "RTM_CONNECTION_CHANGE_TOKEN_EXPIRED", + unity: "TOKEN_EXPIRED", +}; +export const reasonrejected = { + android: "REJECTED_BY_SERVER", + ios: "AgoraRtmClientConnectionChangedRejectedByServer", + javascript: "REJECTED_BY_SERVER", + linux: "RTM_CONNECTION_CHANGE_REJECTED_BY_SERVER", + unity: "REJECTED_BY_SERVER", +}; +export const reasonproxychange = { + android: "SETTING_PROXY_SERVER", + ios: "AgoraRtmClientConnectionChangedSettingProxyServer", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_SETTING_PROXY_SERVER", + unity: "SETTING_PROXY_SERVER", +}; +export const reasonrenewtoken = { + android: "RENEW_TOKEN", + ios: "AgoraRtmClientConnectionChangedRenewToken", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_RENEW_TOKEN", + unity: "RENEW_TOKEN", +}; +export const reasonipchange = { + android: "CLIENT_IP_ADDRESS_CHANGED", + ios: "AgoraRtmClientConnectionChangedClientIpAddressChanged", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_CLIENT_IP_ADDRESS_CHANGED", + unity: "CLIENT_IP_ADDRESS_CHANGED", +}; +export const reasonlivetimeout = { + android: "KEEP_ALIVE_TIMEOUT", + ios: "AgoraRtmClientConnectionChangedKeepAliveTimeout", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_KEEP_ALIVE_TIMEOUT", + unity: "KEEP_ALIVE_TIMEOUT", +}; +export const reasonrejoin = { + android: "REJOIN_SUCCESS", + ios: "AgoraRtmClientConnectionChangedRejoinSuccess", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_REJOIN_SUCCESS", + unity: "REJOIN_SUCCESS", +}; +export const reasonlost = { + android: "LOST", + ios: "AgoraRtmClientConnectionChangedChangedLost", + javascript: "LOST", + linux: "RTM_CONNECTION_CHANGE_LOST", + unity: "LOST", +}; +export const reasonecho = { + android: "ECHO_TEST", + ios: "AgoraRtmClientConnectionChangedEchoTest", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_ECHO_TEST", + unity: "ECHO_TEST", +}; +export const reasonuserchangeip = { + android: "CLIENT_IP_ADDRESS_CHANGED_BY_USER", + ios: "AgoraRtmClientConnectionChangedClientIpAddressChangedByUser", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_CLIENT_IP_ADDRESS_CHANGED_BY_USER", + unity: "CLIENT_IP_ADDRESS_CHANGED_BY_USER", +}; +export const reasonsameuid = { + android: "SAME_UID_LOGIN", + ios: "AgoraRtmClientConnectionChangedSameUidLogin", + javascript: "SAME_UID_LOGIN", + linux: "RTM_CONNECTION_CHANGE_SAME_UID_LOGIN", + unity: "SAME_UID_LOGIN", +}; +export const reasonmanyhosts = { + android: "TOO_MANY_BROADCASTERS", + ios: "AgoraRtmClientConnectionChangedTooManyBroadcasters", + javascript: "/", + linux: "RTM_CONNECTION_CHANGE_TOO_MANY_BROADCASTERS", + unity: "TOO_MANY_BROADCASTERS", +}; +export const reasonlicense = { + android: "LICENSE_VALIDATION_FAILURE", + ios: "/", + javascript: "/", + linux: "/", + unity: "/", +}; +export const reasonstreamchannel = { + android: "STREAM_CHANNEL_NOT_AVAILABLE", + ios: "AgoraRtmClientConnectionChangedStreamChannelNotAvailable", + javascript: "/", + linux: "/", + unity: "/", +}; +export const reasoninconsistentappid = { + android: "INCONSISTENT_APPID", + ios: "/", + javascript: "/", + linux: "/", + unity: "INCONSISTENT_APPID", +}; +export const reasonpresence = { + android: "PRESENCE_NOT_READY", + ios: "AgoraRtmClientConnectionChangedPresenceNotReady", + javascript: "/", + linux: "/", + unity: "PRESENCE_NOT_READY", +}; +export const loginerror = { + android: "/", + ios: "", + javascript: "/", + linux: "RTM_LOGIN_ERROR_CODE", + unity: "RTM_LOGIN_ERROR_CODE", +}; +// message +export const messagetype = { + android: "RtmMessageType", + ios: "", + javascript: "MessageType", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RTM_MESSAGE_TYPE", +}; +export const binarymessage = { + android: "BINARY", + ios: "AgoraRtmMessageTypeBinary", + javascript: "BINARY", + linux: "REMOTE_JOIN_CHANNEL", + unity: "BINARY", +}; +export const stringmessage = { + android: "STRING", + ios: "AgoraRtmMessageTypeString", + javascript: "STRING", + linux: "REMOTE_JOIN_CHANNEL", + unity: "STRING", +}; +export const messageqos = { + android: "RtmMessageQos", + ios: "AgoraRtmMessageQos", + javascript: "/", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RTM_MESSAGE_QOS", +}; +export const unordered = { + android: "UNORDERED", + ios: "AgoraRtmMessageQosUnordered", + javascript: "/", + linux: "REMOTE_JOIN_CHANNEL", + unity: "UNORDERED", +}; +export const ordered = { + android: "ORDERED", + ios: "AgoraRtmMessageQosOrdered", + javascript: "/", + linux: "REMOTE_JOIN_CHANNEL", + unity: "ORDERED", +}; +export const priority = { + android: "RtmMessagePriority", + ios: "AgoraRtmMessagePriority", + javascript: "/", + linux: "/", + unity: "RTM_MESSAGE_PRIORITY", +}; +export const highest = { + android: "HIGHEST", + ios: "AgoraRtmMessagePriorityHighest", + javascript: "/", + linux: "/", + unity: "HIGHEST", +}; +export const high = { + android: "HIGH", + ios: "AgoraRtmMessagePriorityHigh", + javascript: "/", + linux: "/", + unity: "HIGH", +}; +export const normal = { + android: "NORMAL", + ios: "AgoraRtmMessagePriorityNormal", + javascript: "/", + linux: "/", + unity: "NORMAL", +}; +export const low = { + android: "LOW", + ios: "AgoraRtmMessagePriorityLow", + javascript: "/", + linux: "/", + unity: "LOW", +}; +export const subscribechannelfeature = { + android: "", + ios: "AgoraRtmSubscribeChannelFeature", + javascript: "", + linux: "", + unity: "", +}; +export const subscribechannelfeaturenone = { + android: "", + ios: "AgoraRtmSubscribeChannelFeatureNone", + javascript: "", + linux: "", + unity: "", +}; +export const subscribechannelfeaturepresence = { + android: "", + ios: "AgoraRtmSubscribeChannelFeaturePresence", + javascript: "", + linux: "", + unity: "", +}; +export const subscribechannelfeaturemetadata = { + android: "", + ios: "AgoraRtmSubscribeChannelFeatureMetadata", + javascript: "", + linux: "", + unity: "", +}; +export const subscribechannelfeaturemessage = { + android: "", + ios: "AgoraRtmSubscribeChannelFeatureMessage", + javascript: "", + linux: "", + unity: "", +}; +export const subscribechannelfeaturelock = { + android: "", + ios: "AgoraRtmSubscribeChannelFeatureLock", + javascript: "", + linux: "", + unity: "", +}; +export const joinchannelfeature = { + android: "", + ios: "AgoraRtmJoinChannelFeature", + javascript: "", + linux: "", + unity: "", +}; +export const joinchannelfeaturenone = { + android: "", + ios: "AgoraRtmJoinChannelFeatureNone", + javascript: "", + linux: "", + unity: "", +}; +export const joinchannelfeaturepresence = { + android: "", + ios: "AgoraRtmJoinChannelFeaturePresence", + javascript: "", + linux: "", + unity: "", +}; +export const joinchannelfeaturemetadata = { + android: "", + ios: "AgoraRtmJoinChannelFeatureMetadata", + javascript: "", + linux: "", + unity: "", +}; +export const joinchannelfeaturelock = { + android: "", + ios: "AgoraRtmJoinChannelFeatureLock", + javascript: "", + linux: "", + unity: "", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_error-codes.mdx b/shared/signaling/reference/api-ref/shared/_error-codes.mdx new file mode 100644 index 000000000..3d408a057 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_error-codes.mdx @@ -0,0 +1,700 @@ +export const errorcode = { + android: "RtmErrorCode", + ios: "AgoraRtmErrorCode", + javascript: "RTMErrorCode", + linux: "/", + unity: "RTM_ERROR_CODE", +}; +export const ok = { + android: "OK", + ios: "AgoraRtmErrorOk", + javascript: "RTM_ERROR_OK", + linux: "/", + unity: "OK", +}; +export const invalidarg = { + android: "", + ios: "", + javascript: "RTM_ERROR_INVALID_ARGUMENT", + linux: "/", + unity: "", +}; +export const toooften = { + android: "", + ios: "", + javascript: "RTM_ERROR_TOO_OFTEN", + linux: "/", + unity: "", +}; +export const notinit = { + android: "NOT_INITIALIZED", + ios: "AgoraRtmErrorNotInitialized", + javascript: "RTM_ERROR_NOT_INITIALIZED", + linux: "/", + unity: "NOT_INITIALIZED", +}; +export const notlogin = { + android: "NOT_LOGIN", + ios: "AgoraRtmErrorNotLogin", + javascript: "RTM_ERROR_NOT_LOGIN", + linux: "/", + unity: "NOT_LOGIN", +}; +export const invalidapp = { + android: "INVALID_APP_ID", + ios: "AgoraRtmErrorInvalidAppId", + javascript: "RTM_ERROR_INVALID_APP_ID", + linux: "/", + unity: "INVALID_APP_ID", +}; +export const invalidhandler = { + android: "INVALID_EVENT_HANDLER", + ios: "AgoraRtmErrorInvalidEventHandler", + javascript: "RTM_ERROR_INVALID_EVENT_HANDLER", + linux: "/", + unity: "INVALID_EVENT_HANDLER", +}; +export const invalidtoken = { + android: "INVALID_TOKEN", + ios: "AgoraRtmErrorInvalidToken", + javascript: "RTM_ERROR_INVALID_TOKEN", + linux: "/", + unity: "INVALID_TOKEN", +}; +export const invaliduser = { + android: "INVALID_USER_ID", + ios: "AgoraRtmErrorInvalidUserId", + javascript: "RTM_ERROR_INVALID_USER_ID", + linux: "/", + unity: "INVALID_USER_ID", +}; +export const invalidchanel = { + android: "INVALID_CHANNEL_NAME", + ios: "AgoraRtmErrorInvalidChannelName", + javascript: "RTM_ERROR_INVALID_CHANNEL_NAME", + linux: "/", + unity: "INVALID_CHANNEL_NAME", +}; +export const initservicefailed = { + android: "INIT_SERVICE_FAILED", + ios: "AgoraRtmErrorInitServiceFailed", + javascript: "", + linux: "", + unity: "INIT_SERVICE_FAILED", +}; +export const tokenexpired = { + android: "TOKEN_EXPIRED", + ios: "AgoraRtmErrorTokenExpired", + javascript: "RTM_ERROR_TOKEN_EXPIRED", + linux: "/", + unity: "TOKEN_EXPIRED", +}; +export const loginnoserverresources = { + android: "LOGIN_NO_SERVER_RESOURCES", + ios: "AgoraRtmErrorLoginNoServerResources", + javascript: "RTM_ERROR_LOGIN_NO_SERVER_RESOURCES", + linux: "", + unity: "LOGIN_NO_SERVER_RESOURCES", +}; +export const logintimeout = { + android: "LOGIN_TIMEOUT", + ios: "AgoraRtmErrorLoginTimeout", + javascript: "RTM_ERROR_LOGIN_TIMEOUT", + linux: "/", + unity: "LOGIN_TIMEOUT", +}; +export const loginrejected = { + android: "LOGIN_REJECTED", + ios: "AgoraRtmErrorLoginRejected", + javascript: "RTM_ERROR_LOGIN_REJECTED", + linux: "/", + unity: "LOGIN_REJECTED", +}; +export const loginaborted = { + android: "LOGIN_ABORTED", + ios: "AgoraRtmErrorLoginAborted", + javascript: "RTM_ERROR_LOGIN_ABORTED", + linux: "/", + unity: "LOGIN_ABORTED", +}; +export const invalidparameter = { + android: "INVALID_PARAMETER", + ios: "AgoraRtmErrorInvalidParameter", + javascript: "", + linux: "", + unity: "INVALID_PARAMETER", +}; +export const loginnotauthorized = { + android: "LOGIN_NOT_AUTHORIZED", + ios: "AgoraRtmErrorLoginNotAuthorized", + javascript: "RTM_ERROR_LOGIN_NOT_AUTHORIZED", + linux: "", + unity: "LOGIN_NOT_AUTHORIZED", +}; +export const logininconsistentappid = { + android: "INCONSISTENT_APPID", + ios: "AgoraRtmErrorLoginInconsistentAppId", + javascript: "RTM_ERROR_INCONSISTENT_APPID", + linux: "", + unity: "INCONSISTENT_APPID", +}; +export const duplicateoperation = { + android: "DUPLICATE_OPERATION", + ios: "AgoraRtmErrorDuplicateOperation", + javascript: "", + linux: "", + unity: "DUPLICATE_OPERATION", +}; +export const instancealreadyreleased = { + android: "INSTANCE_ALREADY_RELEASED", + ios: "AgoraRtmErrorInstanceAlreadyReleased", + javascript: "RTM_ERROR_INSTANCE_ALREADY_RELEASED", + linux: "", + unity: "", +}; +export const invalidchanneltype = { + android: "", + ios: "", + javascript: "RTM_ERROR_INVALID_CHANNEL_TYPE", + linux: "", + unity: "", +}; +export const invalidencryptionparameter = { + android: "", + ios: "", + javascript: "RTM_ERROR_INVALID_ENCRYPTION_PARAMETER", + linux: "", + unity: "", +}; +export const operationrateexceedlimitation = { + android: "", + ios: "", + javascript: "RTM_ERROR_OPERATION_RATE_EXCEED_LIMITATION", + linux: "", + unity: "INSTANCE_ALREADY_RELEASED", +}; +export const channelnotjoined = { + android: "CHANNEL_NOT_JOINED", + ios: "AgoraRtmErrorChannelNotJoined", + javascript: "RTM_ERROR_CHANNEL_NOT_JOINED", + linux: "/", + unity: "CHANNEL_NOT_JOINED", +}; +export const channelnotsub = { + android: "CHANNEL_NOT_SUBSCRIBED", + ios: "AgoraRtmErrorChannelNotSubscribed", + javascript: "RTM_ERROR_CHANNEL_NOT_SUBSCRIBED", + linux: "/", + unity: "CHANNEL_NOT_SUBSCRIBED", +}; +export const channeluserexceed = { + android: "CHANNEL_EXCEED_TOPIC_USER_LIMITATION", + ios: "AgoraRtmErrorChannelExceedTopicUserLimitation", + javascript: "RTM_ERROR_CHANNEL_EXCEED_TOPIC_USER_LIMITATION", + linux: "/", + unity: "CHANNEL_EXCEED_TOPIC_USER_LIMITATION", +}; +export const inresue = { + android: "CHANNEL_IN_REUSE", + ios: "AgoraRtmErrorChannelReused", + javascript: "RTM_ERROR_CHANNEL_IN_REUSE", + linux: "/", + unity: "CHANNEL_IN_REUSE", +}; +export const instanceexceed = { + android: "CHANNEL_INSTANCE_EXCEED_LIMITATION", + ios: "AgoraRtmErrorChannelInstanceExceedLimitation", + javascript: "RTM_ERROR_CHANNEL_INSTANCE_EXCEED_LIMITATION", + linux: "/", + unity: "CHANNEL_INSTANCE_EXCEED_LIMITATION", +}; +export const inerror = { + android: "CHANNEL_IN_ERROR_STATE", + ios: "AgoraRtmErrorChannelInErrorState", + javascript: "RTM_ERROR_CHANNEL_IN_ERROR_STATE", + linux: "/", + unity: "CHANNEL_IN_ERROR_STATE", +}; +export const channeljoinfailed = { + android: "CHANNEL_JOIN_FAILED", + ios: "AgoraRtmErrorChannelJoinFailed", + javascript: "RTM_ERROR_CHANNEL_JOIN_FAILED", + linux: "/", + unity: "CHANNEL_JOIN_FAILED", +}; +export const invalidtopic = { + android: "CHANNEL_INVALID_TOPIC_NAME", + ios: "AgoraRtmErrorChannelInvalidTopicName", + javascript: "RTM_ERROR_CHANNEL_INVALID_TOPIC_NAME", + linux: "/", + unity: "CHANNEL_INVALID_TOPIC_NAME", +}; +export const invalidmessage = { + android: "CHANNEL_INVALID_MESSAGE", + ios: "AgoraRtmErrorChannelInvalidMessage", + javascript: "RTM_ERROR_CHANNEL_INVALID_MESSAGE", + linux: "/", + unity: "CHANNEL_INVALID_MESSAGE", +}; +export const lengthexceed = { + android: "CHANNEL_MESSAGE_LENGTH_EXCEED_LIMITATION", + ios: "AgoraRtmErrorChannelMessageLengthExceedLimitation", + javascript: "RTM_ERROR_CHANNEL_MESSAGE_LENGTH_EXCEED_LIMITATION", + linux: "/", + unity: "CHANNEL_MESSAGE_LENGTH_EXCEED_LIMITATION", +}; +export const invalidlist = { + android: "CHANNEL_INVALID_USER_LIST", + ios: "AgoraRtmErrorChannelInvalidUserList", + javascript: "RTM_ERROR_CHANNEL_INVALID_USER_LIST", + linux: "/", + unity: "CHANNEL_INVALID_USER_LIST", +}; +export const channelnotavailable = { + android: "RTM_ERROR_CHANNEL_NOT_AVAILABLE", + ios: "AgoraRtmErrorChannelNotAvailable", + javascript: "RTM_ERROR_CHANNEL_NOT_AVAILABLE", + linux: "/", + unity: "CHANNEL_NOT_AVAILABLE", +}; +export const topicnotsub = { + android: "CHANNEL_TOPIC_NOT_SUBSCRIBED", + ios: "AgoraRtmErrorChannelTopicNotSubscribed", + javascript: "RTM_ERROR_CHANNEL_TOPIC_NOT_SUBSCRIBED", + linux: "/", + unity: "CHANNEL_TOPIC_NOT_SUBSCRIBED", +}; +export const topicexceed = { + android: "CHANNEL_EXCEED_TOPIC_LIMITATION", + ios: "AgoraRtmErrorChannelExceedTopicLimitation", + javascript: "RTM_ERROR_CHANNEL_EXCEED_TOPIC_LIMITATION", + linux: "/", + unity: "CHANNEL_EXCEED_TOPIC_LIMITATION", +}; +export const topicjoinfailed = { + android: "CHANNEL_JOIN_TOPIC_FAILED", + ios: "AgoraRtmErrorChannelJoinTopicFailed", + javascript: "RTM_ERROR_CHANNEL_JOIN_TOPIC_FAILED", + linux: "/", + unity: "CHANNEL_JOIN_TOPIC_FAILED", +}; +export const topicnotjoined = { + android: "CHANNEL_TOPIC_NOT_JOINED", + ios: "AgoraRtmErrorChannelTopicNotJoined", + javascript: "RTM_ERROR_CHANNEL_TOPIC_NOT_JOINED", + linux: "/", + unity: "CHANNEL_TOPIC_NOT_JOINED", +}; +export const topicnotexist = { + android: "CHANNEL_TOPIC_NOT_EXIST", + ios: "AgoraRtmErrorChannelTopicNotExist", + javascript: "RTM_ERROR_CHANNEL_TOPIC_NOT_EXIST", + linux: "/", + unity: "CHANNEL_TOPIC_NOT_EXIST", +}; +export const invalidtopicmeta = { + android: "CHANNEL_INVALID_TOPIC_META", + ios: "AgoraRtmErrorChannelInvalidTopicMeta", + javascript: "RTM_ERROR_CHANNEL_INVALID_TOPIC_META", + linux: "/", + unity: "CHANNEL_INVALID_TOPIC_META", +}; +export const subtimeout = { + android: "CHANNEL_SUBSCRIBE_TIMEOUT", + ios: "AgoraRtmErrorChannelSubscribeTimeout", + javascript: "RTM_ERROR_CHANNEL_SUBSCRIBE_TIMEOUT", + linux: "/", + unity: "CHANNEL_SUBSCRIBE_TIMEOUT", +}; +export const subfrequent = { + android: "CHANNEL_SUBSCRIBE_TOO_FREQUENT", + ios: "AgoraRtmErrorChannelSubscribeTooFrequent", + javascript: "RTM_ERROR_CHANNEL_SUBSCRIBE_TOO_FREQUENT", + linux: "/", + unity: "CHANNEL_SUBSCRIBE_TOO_FREQUENT", +}; +export const subfailed = { + android: "CHANNEL_SUBSCRIBE_FAILED", + ios: "AgoraRtmErrorChannelSubscribeFailed", + javascript: "RTM_ERROR_CHANNEL_SUBSCRIBE_FAILED", + linux: "/", + unity: "CHANNEL_SUBSCRIBE_FAILED", +}; +export const unsubfailed = { + android: "CHANNEL_UNSUBSCRIBE_FAILED", + ios: "AgoraRtmErrorChannelUnsubscribeFailed", + javascript: "RTM_ERROR_CHANNEL_UNSUBSCRIBE_FAILED", + linux: "/", + unity: "CHANNEL_UNSUBSCRIBE_FAILED", +}; +export const encryptfailed = { + android: "CHANNEL_ENCRYPT_MESSAGE_FAILED", + ios: "AgoraRtmErrorChannelEncryptMessageFailed", + javascript: "RTM_ERROR_CHANNEL_ENCRYPT_MESSAGE_FAILED", + linux: "/", + unity: "CHANNEL_ENCRYPT_MESSAGE_FAILED", +}; +export const publishfailed = { + android: "CHANNEL_PUBLISH_MESSAGE_FAILED", + ios: "AgoraRtmErrorChannelPublishMessageFailed", + javascript: "RTM_ERROR_CHANNEL_PUBLISH_MESSAGE_FAILED", + linux: "/", + unity: "CHANNEL_PUBLISH_MESSAGE_FAILED", +}; +export const publishfrequent = { + android: "CHANNEL_PUBLISH_MESSAGE_TOO_FREQUENT", + ios: "AgoraRtmErrorChannelPublishMessageTooFrequent", + javascript: "RTM_ERROR_CHANNEL_PUBLISH_MESSAGE_TOO_FREQUENT", + linux: "/", + unity: "CHANNEL_PUBLISH_MESSAGE_TOO_FREQUENT", +}; +export const publishtimeout = { + android: "CHANNEL_PUBLISH_MESSAGE_TIMEOUT", + ios: "AgoraRtmErrorChannelPublishMessageTimeout", + javascript: "RTM_ERROR_CHANNEL_PUBLISH_MESSAGE_TIMEOUT", + linux: "/", + unity: "CHANNEL_PUBLISH_MESSAGE_TIMEOUT", +}; +export const channelnotconnected = { + android: "CHANNEL_NOT_CONNECTED", + ios: "AgoraRtmErrorChannelNotConnected", + javascript: "RTM_ERROR_CHANNEL_NOT_CONNECTED", + linux: "/", + unity: "CHANNEL_NOT_CONNECTED", +}; +export const channelleavefailed = { + android: "CHANNEL_LEAVE_FAILED", + ios: "AgoraRtmErrorChannelLeaveFailed", + javascript: "RTM_ERROR_CHANNEL_LEAVE_FAILED", + linux: "/", + unity: "CHANNEL_LEAVE_FAILED", +}; +export const customoverflow = { + android: "CHANNEL_CUSTOM_TYPE_LENGTH_OVERFLOW", + ios: "AgoraRtmErrorChannelCustomTypeLengthOverflow", + javascript: "RTM_ERROR_CHANNEL_CUSTOM_TYPE_LENGTH_OVERFLOW", + linux: "/", + unity: "CHANNEL_CUSTOM_TYPE_LENGTH_OVERFLOW", +}; +export const custominvalid = { + android: "CHANNEL_INVALID_CUSTOM_TYPE", + ios: "AgoraRtmErrorChannelInvalidCustomType", + javascript: "RTM_ERROR_CHANNEL_INVALID_CUSTOM_TYPE", + linux: "/", + unity: "CHANNEL_INVALID_CUSTOM_TYPE", +}; +export const unsupportedmessagetype = { + android: "CHANNEL_UNSUPPORTED_MESSAGE_TYPE", + ios: "AgoraRtmErrorChannelUnsupportedMessageType", + javascript: "", + linux: "", + unity: "CHANNEL_UNSUPPORTED_MESSAGE_TYPE", +}; +export const presencenotready = { + android: "CHANNEL_PRESENCE_NOT_READY", + ios: "AgoraRtmErrorChannelPresenceNotReady", + javascript: "", + linux: "", + unity: "CHANNEL_PRESENCE_NOT_READY", +}; +export const storagefailed = { + android: "STORAGE_OPERATION_FAILED", + ios: "AgoraRtmErrorStorageOperationFailed", + javascript: "RTM_ERROR_STORAGE_OPERATION_FAILED", + linux: "/", + unity: "STORAGE_OPERATION_FAILED", +}; +export const storageinvalidname = { + android: "", + ios: "", + javascript: "RTM_ERROR_STORAGE_INVALID_NAME", + linux: "/", + unity: "", +}; +export const metadataexceed = { + android: "STORAGE_METADATA_ITEM_EXCEED_LIMITATION", + ios: "AgoraRtmErrorStorageMetadataItemExceedLimitation", + javascript: "RTM_ERROR_STORAGE_METADATA_ITEM_EXCEED_LIMITATION", + linux: "/", + unity: "STORAGE_METADATA_ITEM_EXCEED_LIMITATION", +}; +export const invalidmetadata = { + android: "STORAGE_INVALID_METADATA_ITEM", + ios: "AgoraRtmErrorStorageInvalidMetadataItem", + javascript: "RTM_ERROR_STORAGE_INVALID_METADATA_ITEM", + linux: "/", + unity: "STORAGE_INVALID_METADATA_ITEM", +}; +export const storageinvalidarg = { + android: "STORAGE_INVALID_ARGUMENT", + ios: "AgoraRtmErrorStorageInvalidArgument", + javascript: "RTM_ERROR_STORAGE_INVALID_ARGUMENT", + linux: "/", + unity: "STORAGE_INVALID_ARGUMENT", +}; +export const invalidrevision = { + android: "STORAGE_INVALID_REVISION", + ios: "AgoraRtmErrorStorageInvalidRevision", + javascript: "RTM_ERROR_STORAGE_INVALID_REVISION", + linux: "/", + unity: "STORAGE_INVALID_REVISION", +}; +export const storageoverflow = { + android: "STORAGE_METADATA_LENGTH_OVERFLOW", + ios: "AgoraRtmErrorStorageMetadataLengthOverflow", + javascript: "RTM_ERROR_STORAGE_METADATA_LENGTH_OVERFLOW", + linux: "/", + unity: "STORAGE_METADATA_LENGTH_OVERFLOW", +}; +export const invalidlock = { + android: "STORAGE_INVALID_LOCK_NAME", + ios: "AgoraRtmErrorStorageInvalidLockName", + javascript: "RTM_ERROR_STORAGE_INVALID_LOCK_NAME", + linux: "/", + unity: "STORAGE_INVALID_LOCK_NAME", +}; +export const storagelocknotacquired = { + android: "STORAGE_LOCK_NOT_ACQUIRED", + ios: "AgoraRtmErrorStorageLockNotAcquired", + javascript: "RTM_ERROR_STORAGE_LOCK_NOT_ACQUIRED", + linux: "/", + unity: "STORAGE_LOCK_NOT_ACQUIRED", +}; +export const storageinvalidkey = { + android: "STORAGE_INVALID_KEY", + ios: "AgoraRtmErrorStorageInvalidKey", + javascript: "RTM_ERROR_STORAGE_INVALID_KEY", + linux: "/", + unity: "STORAGE_INVALID_KEY", +}; +export const storageinvalidvalue = { + android: "STORAGE_INVALID_VALUE", + ios: "AgoraRtmErrorStorageInvalidValue", + javascript: "RTM_ERROR_STORAGE_INVALID_VALUE", + linux: "/", + unity: "STORAGE_INVALID_VALUE", +}; +export const storagekeyoverflow = { + android: "STORAGE_KEY_LENGTH_OVERFLOW", + ios: "AgoraRtmErrorStorageKeyLengthOverflow", + javascript: "RTM_ERROR_STORAGE_KEY_LENGTH_OVERFLOW", + linux: "/", + unity: "STORAGE_KEY_LENGTH_OVERFLOW", +}; +export const storagevalueoverflow = { + android: "STORAGE_VALUE_LENGTH_OVERFLOW", + ios: "AgoraRtmErrorStorageValueLengthOverflow", + javascript: "RTM_ERROR_STORAGE_VALUE_LENGTH_OVERFLOW", + linux: "/", + unity: "STORAGE_VALUE_LENGTH_OVERFLOW", +}; +export const storageduplicatekey = { + android: "STORAGE_DUPLICATE_KEY", + ios: "AgoraRtmErrorStorageDuplicateKey", + javascript: "RTM_ERROR_STORAGE_DUPLICATE_KEY", + linux: "/", + unity: "STORAGE_DUPLICATE_KEY", +}; +export const outdatedrevision = { + android: "STORAGE_OUTDATED_REVISION", + ios: "AgoraRtmErrorStorageOutdatedRevision", + javascript: "RTM_ERROR_STORAGE_OUTDATED_REVISION", + linux: "/", + unity: "STORAGE_OUTDATED_REVISION", +}; +export const storagenotsub = { + android: "STORAGE_NOT_SUBSCRIBE", + ios: "AgoraRtmErrorStorageNotSubscribe", + javascript: "RTM_ERROR_STORAGE_NOT_SUBSCRIBE", + linux: "/", + unity: "STORAGE_NOT_SUBSCRIBE", +}; +export const storageinvalidmetadata = { + android: "STORAGE_INVALID_METADATA_INSTANCE", + ios: "AgoraRtmErrorStorageInvalidMetadataInstance", + javascript: "", + linux: "", + unity: "STORAGE_INVALID_METADATA_INSTANCE", +}; +export const storagesubexceed = { + android: "STORAGE_SUBSCRIBE_USER_EXCEED_LIMITATION", + ios: "AgoraRtmErrorStorageSubscribeUserExceedLimitation", + javascript: "RTM_ERROR_STORAGE_SUBSCRIBE_USER_EXCEED_LIMITATION", + linux: "/", + unity: "STORAGE_SUBSCRIBE_USER_EXCEED_LIMITATION", +}; +export const storagetimeout = { + android: "STORAGE_OPERATION_TIMEOUT", + ios: "AgoraRtmErrorStorageOperationTimeout", + javascript: "RTM_ERROR_STORAGE_OPERATION_TIMEOUT", + linux: "/", + unity: "STORAGE_OPERATION_TIMEOUT", +}; +export const storagenotavailable = { + android: "STORAGE_NOT_AVAILABLE", + ios: "AgoraRtmErrorStorageNotAvailable", + javascript: "RTM_ERROR_STORAGE_NOT_AVAILABLE", + linux: "/", + unity: "STORAGE_NOT_AVAILABLE", +}; +export const presencenotconnected = { + android: "PRESENCE_NOT_CONNECTED", + ios: "AgoraRtmErrorPresenceNotConnected", + javascript: "RTM_ERROR_PRESENCE_NOT_CONNECTED", + linux: "/", + unity: "PRESENCE_NOT_CONNECTED", +}; +export const notwritable = { + android: "PRESENCE_NOT_WRITABLE", + ios: "AgoraRtmErrorPresenceNotWritable", + javascript: "RTM_ERROR_PRESENCE_NOT_WRITABLE", + linux: "/", + unity: "PRESENCE_NOT_WRITABLE", +}; +export const presenceinvalidarg = { + android: "PRESENCE_INVALID_ARGUMENT", + ios: "AgoraRtmErrorPresenceInvalidArgument", + javascript: "RTM_ERROR_PRESENCE_INVALID_ARGUMENT", + linux: "/", + unity: "PRESENCE_INVALID_ARGUMENT", +}; +export const cachestates = { + android: "PRESENCE_CACHED_TOO_MANY_STATES", + ios: "AgoraRtmErrorPresenceCacheTooManyStates", + javascript: "RTM_ERROR_PRESENCE_CACHED_TOO_MANY_STATES", + linux: "/", + unity: "PRESENCE_CACHED_TOO_MANY_STATES", +}; +export const stateoverflow = { + android: "PRESENCE_STATE_COUNT_OVERFLOW", + ios: "AgoraRtmErrorPresenceStateCountOverflow", + javascript: "RTM_ERROR_PRESENCE_STATE_COUNT_OVERFLOW", + linux: "/", + unity: "PRESENCE_STATE_COUNT_OVERFLOW", +}; +export const invalidstatekey = { + android: "PRESENCE_INVALID_STATE_KEY", + ios: "AgoraRtmErrorPresenceInvalidStateKey", + javascript: "RTM_ERROR_PRESENCE_INVALID_STATE_KEY", + linux: "/", + unity: "PRESENCE_INVALID_STATE_KEY", +}; +export const invalidstatevalue = { + android: "PRESENCE_INVALID_STATE_VALUE", + ios: "AgoraRtmErrorPresenceInvalidStateValue", + javascript: "TM_ERROR_PRESENCE_INVALID_STATE_VALUE", + linux: "/", + unity: "PRESENCE_INVALID_STATE_VALUE", +}; +export const presencekeyoverflow = { + android: "PRESENCE_STATE_KEY_SIZE_OVERFLOW", + ios: "AgoraRtmErrorPresenceStateKeySizeOverflow", + javascript: "RTM_ERROR_PRESENCE_STATE_KEY_SIZE_OVERFLOW", + linux: "/", + unity: "PRESENCE_STATE_KEY_SIZE_OVERFLOW", +}; +export const presencevalueoverflow = { + android: "PRESENCE_STATE_VALUE_SIZE_OVERFLOW", + ios: "AgoraRtmErrorPresenceStateValueSizeOverflow", + javascript: "RTM_ERROR_PRESENCE_STATE_VALUE_SIZE_OVERFLOW", + linux: "/", + unity: "PRESENCE_STATE_VALUE_SIZE_OVERFLOW", +}; +export const presenceduplicatekey = { + android: "PRESENCE_STATE_DUPLICATE_KEY", + ios: "AgoraRtmErrorPresenceStateDuplicateKey", + javascript: "RTM_ERROR_PRESENCE_STATE_DUPLICATE_KEY", + linux: "/", + unity: "PRESENCE_STATE_DUPLICATE_KEY", +}; +export const usernotexist = { + android: "PRESENCE_USER_NOT_EXIST", + ios: "AgoraRtmErrorPresenceUserNotExist", + javascript: "RTM_ERROR_PRESENCE_USER_NOT_EXIST", + linux: "/", + unity: "PRESENCE_USER_NOT_EXIST", +}; +export const presencetimeout = { + android: "PRESENCE_OPERATION_TIMEOUT", + ios: "AgoraRtmErrorPresenceOperationTimeout", + javascript: "RTM_ERROR_PRESENCE_OPERATION_TIMEOUT", + linux: "/", + unity: "PRESENCE_OPERATION_TIMEOUT", +}; +export const presencefailed = { + android: "PRESENCE_OPERATION_FAILED", + ios: "AgoraRtmErrorPresenceOperationFailed", + javascript: "RTM_ERROR_PRESENCE_OPERATION_FAILED", + linux: "/", + unity: "PRESENCE_OPERATION_FAILED", +}; +export const lockfailed = { + android: "LOCK_OPERATION_FAILED", + ios: "AgoraRtmErrorLockOperationFailed", + javascript: "RTM_ERROR_LOCK_OPERATION_FAILED", + linux: "/", + unity: "LOCK_OPERATION_FAILED", +}; +export const locktimeout = { + android: "LOCK_OPERATION_TIMEOUT", + ios: "AgoraRtmErrorLockOperationTimeout", + javascript: "RTM_ERROR_LOCK_OPERATION_TIMEOUT", + linux: "/", + unity: "LOCK_OPERATION_TIMEOUT", +}; +export const performing = { + android: "LOCK_OPERATION_PERFORMING", + ios: "AgoraRtmErrorLockOperationPerforming", + javascript: "RTM_ERROR_LOCK_OPERATION_PERFORMING", + linux: "/", + unity: "LOCK_OPERATION_PERFORMING", +}; +export const lockexist = { + android: "LOCK_ALREADY_EXIST", + ios: "AgoraRtmErrorLockAlreadyExist", + javascript: "RTM_ERROR_LOCK_ALREADY_EXIST", + linux: "/", + unity: "LOCK_ALREADY_EXIST", +}; +export const lockinvalidname = { + android: "LOCK_INVALID_NAME", + ios: "AgoraRtmErrorLockInvalidName", + javascript: "RTM_ERROR_LOCK_INVALID_NAME", + linux: "/", + unity: "LOCK_INVALID_NAME", +}; +export const locknotacquired = { + android: "LOCK_NOT_ACQUIRED", + ios: "AgoraRtmErrorLockNotAcquired", + javascript: "RTM_ERROR_LOCK_NOT_ACQUIRED", + linux: "/", + unity: "LOCK_NOT_ACQUIRED", +}; +export const lockacquirefailed = { + android: "LOCK_ACQUIRE_FAILED", + ios: "AgoraRtmErrorLockAcquireFailed", + javascript: "RTM_ERROR_LOCK_ACQUIRE_FAILED", + linux: "/", + unity: "LOCK_ACQUIRE_FAILED", +}; +export const locknotexist = { + android: "LOCK_NOT_EXIST", + ios: "AgoraRtmErrorLockNotExist", + javascript: "RTM_ERROR_LOCK_NOT_EXIST", + linux: "", + unity: "LOCK_NOT_EXIST", +}; +export const invalidttl = { + android: "", + ios: "", + javascript: "RTM_ERROR_LOCK_INVALID_TTL", + linux: "", + unity: "", +}; +export const locknotavailable = { + android: "LOCK_NOT_AVAILABLE", + ios: "AgoraRtmErrorLockNotAvailable", + javascript: "RTM_ERROR_LOCK_NOT_AVAILABLE", + linux: "/", + unity: "LOCK_NOT_AVAILABLE", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_lock.mdx b/shared/signaling/reference/api-ref/shared/_lock.mdx new file mode 100644 index 000000000..07169ba5c --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_lock.mdx @@ -0,0 +1,133 @@ +export const set ={ + android: "setLock", + ios: "setLock", + javascript: "setLock", + linux: "setLock", + unity: "SetLockAsync", +}; +export const acquire ={ + android: "acquireLock", + ios: "acquireLock", + javascript: "acquireLock", + linux: "acquireLock", + unity: "AcquireLockAsync", +}; +export const release ={ + android: "releaseLock", + ios: "releaseLock", + javascript: "releaseLock", + linux: "releaseLock", + unity: "ReleaseLockAsync", +}; +export const revoke ={ + android: "revokeLock", + ios: "revokeLock", + javascript: "revokeLock", + linux: "revokeLock", + unity: "RevokeLockAsync", +}; +export const get ={ + android: "getLocks", + ios: "getLocks", + javascript: "getLock", + linux: "getLock", + unity: "GetLocksAsync", +}; +export const remove ={ + android: "removeLock", + ios: "removeLock", + javascript: "removeLock", + linux: "removeLock", + unity: "RemoveLockAsync", +}; +export const setlockresulttype = { + android: "/", + ios: "/", + javascript: "SetLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const setlockresult = { + android: "/", + ios: "/", + javascript: "SetLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "SetLockResult", +}; +export const acquirelockresulttype = { + android: "/", + ios: "/", + javascript: "AcquireLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const acquirelockresult = { + android: "/", + ios: "/", + javascript: "AcquireLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "AcquireLockResult", +}; +export const releaselockresulttype = { + android: "/", + ios: "/", + javascript: "ReleaseLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const releaselockresult = { + android: "/", + ios: "/", + javascript: "ReleaseLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "ReleaseLockResult", +}; +export const revokelockresulttype = { + android: "/", + ios: "/", + javascript: "RevokeLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const revokelockresult = { + android: "/", + ios: "/", + javascript: "RevokeLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RevokeLockResult", +}; +export const getlockresulttype = { + android: "/", + ios: "/", + javascript: "GetLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const getlockresult = { + android: "/", + ios: "/", + javascript: "GetLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "GetLockResult", +}; +export const removelockresulttype = { + android: "/", + ios: "/", + javascript: "RemoveLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const removelockresult = { + android: "/", + ios: "/", + javascript: "RemoveLockResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RemoveLockResult", +}; +export const detail = { + android: "LockDetail", + ios: "AgoraRtmLockDetail", + javascript: "LockDetail", + linux: "REMOTE_JOIN_CHANNEL", + unity: "LockDetail", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_message.mdx b/shared/signaling/reference/api-ref/shared/_message.mdx new file mode 100644 index 000000000..026c1df43 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_message.mdx @@ -0,0 +1,28 @@ +export const publish = { + android: "publish", + ios: "publish", + javascript: "publish", + linux: "publish", + unity: "PublishAsync", +}; +export const publishresulttype = { + android: "/", + ios: "/", + javascript: "PublishResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const publishresult = { + android: "/", + ios: "/", + javascript: "PublishResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "PublishResult", +}; +export const publishoptions = { + android: "PublishOptions", + ios: "AgoraRtmPublishOptions", + javascript: "PublishOptions", + linux: "publishoptions", + unity: "PublishOptions", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_presence.mdx b/shared/signaling/reference/api-ref/shared/_presence.mdx new file mode 100644 index 000000000..a5f4769c7 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_presence.mdx @@ -0,0 +1,169 @@ +export const whonow = { + android: "whoNow", + ios: "whoNow", + javascript: "getOnlineUsers", + linux: "whoNow", + unity: "WhoNowAsync", +}; +export const wherenow = { + android: "whereNow", + ios: "whereNow", + javascript: "getUserChannels", + linux: "whereNow", + unity: "WhereNowAsync", +}; +export const setstate = { + android: "setState", + ios: "setState", + javascript: "setState", + linux: "setState", + unity: "SetStateAsync", +}; +export const getstate = { + android: "getState", + ios: "getState", + javascript: "getState", + linux: "getState", + unity: "GetStateAsync", +}; +export const removestate = { + android: "removeState", + ios: "removeState", + javascript: "removeState", + linux: "removeState", + unity: "RemoveStateAsync", +}; +export const options = { + android: "PresenceOptions", + ios: "AgoraRtmPresenceOptions", + javascript: "options", + linux: "", + unity: "PresenceOptions", +}; +export const userstate = { + android: "UserState", + ios: "AgoraRtmUserState", + javascript: "OccupancyDetail", + linux: "removeState", + unity: "UserState", +}; +export const whonowresulttype = { + android: "/", + ios: "/", + javascript: "GetOnlineUsersResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const whonowresult = { + android: "WhoNowResult", + ios: "/", + javascript: "GetOnlineUsersResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "WhoNowResult", +}; +export const wherenowresulttype = { + android: "/", + ios: "/", + javascript: "GetUserChannelsResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const wherenowresult = { + android: "ArrayList", + ios: "/", + javascript: "GetUserChannelsResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "WhereNowResult", +}; +export const setstateresulttype = { + android: "/", + ios: "/", + javascript: "SetStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const setstateresult = { + android: "/", + ios: "/", + javascript: "SetStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "SetStateResult", +}; +export const getstateresulttype = { + android: "/", + ios: "/", + javascript: "GetStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const getstateresult = { + android: "/", + ios: "/", + javascript: "GetStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "GetStateResult", +}; +export const removestateresulttype = { + android: "/", + ios: "/", + javascript: "RemoveStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const removestateresult = { + android: "/", + ios: "/", + javascript: "RemoveStateResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RemoveStateResult", +}; +export const channelinfo = { + android: "ChannelInfo", + ios: "AgoraRtmChannelInfo", + javascript: "ChannelDetail", + linux: "removeState", + unity: "ChannelInfo", +}; +// Parameter +export const nextpage = { + android: "NextPage", + ios: "nextPage", + javascript: "nextPage", + linux: "", + unity: "NextPage", +}; +export const nextpageresult = { + android: "result.NextPage", + ios: "response.nextPage", + javascript: "result.nextPage", + linux: "", + unity: "response.NextPage", +}; +export const result = { + android: "result", + ios: "response", + javascript: "result", + linux: "", + unity: "response", +}; +export const withstate = { + android: "includeState", + ios: "includeState", + javascript: "includedState", + linux: "", + unity: "withState", +}; +export const withuserid = { + android: "includeUserId", + ios: "includeUserId", + javascript: "includedUserId", + linux: "", + unity: "withUserId", +}; +export const count = { + android: "totalOccupancy", + ios: "totalOccupancy", + javascript: "totalOccupancy", + linux: "", + unity: "totalOccupancy", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_publishoptions.mdx b/shared/signaling/reference/api-ref/shared/_publishoptions.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/shared/signaling/reference/api-ref/shared/_rtm-channel-type.mdx b/shared/signaling/reference/api-ref/shared/_rtm-channel-type.mdx new file mode 100644 index 000000000..2893ad34a --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_rtm-channel-type.mdx @@ -0,0 +1,6 @@ +频道类型。 + +| Value | Description | +| :----------: | ---------------------------------------------------------- | +| `RTM_CHANNEL_TYPE_MESSAGE` | 0: Message Channel | +| `RTM_CHANNEL_TYPE_STREAM` | 1: Stream Channel | \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_rtmstatus-en.mdx b/shared/signaling/reference/api-ref/shared/_rtmstatus-en.mdx new file mode 100644 index 000000000..02c648515 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_rtmstatus-en.mdx @@ -0,0 +1,48 @@ + +| Property | Type | Description | +| :------------------: | :--------------------: | ------------------------------------- | +| `Error` | bool | Whether this operation is an error. | +| `ErrorCode` | string | Error code for this operation. | +| `Operation` | string | Operation type for this operation. | +| `Reason` | string | Error reason for this operation. | + +To find out the cause of the error and get the corresponding solution, using the `errorCode` field with the error code. + + + + + +```javascript +type ErrorInfo = { + error: boolean; // Whether there is an error in this operation + operation: string; // The API name of this operation + errorCode: number; // Error code. + reason: string; // Error reason +} +``` + + + + + +| Properties | Type | Description | +| :------------------: | :--------------------: | ------------------------------------- | +| `errorCode` | `RtmErrorCode` | Error code for this operation. | +| `reason` | String | Error reason for this operation. | +| `operation` | String | Operation type. | + +To find out the cause of the error and get the corresponding solution, using the `errorCode` field with the error code. + + + + + +| Properties | Type | Description | +| :------------------ | :--------------------: | ------------------------------------- | +| `errorCode` | `AgoraRtmErrorCode` | Error code for this operation. | +| `reason` | NSString | Error reason for this operation. | +| `operation` | NSString | Operation type. | + +To find out the cause of the error and get the corresponding solution, using the `errorCode` field with the error code. + + \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_rtmstatus.mdx b/shared/signaling/reference/api-ref/shared/_rtmstatus.mdx new file mode 100644 index 000000000..5d4ed7c9d --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_rtmstatus.mdx @@ -0,0 +1,22 @@ + +| Property | Type | Description | +| :------------------ | :--------------------: | :------------------------------------- | +| `Error` | bool | Whether an error occurs. | +| `ErrorCode` | int | Error code. | +| `Operation` | string | Operation type of this call. | +| `Reason` | string | Reason for the error. | + + + + +```JavaScript +type ErrorInfo = { + error: boolean; // Whether an error occurs. + operation: string; // Operation type of this method call. + errorCode: number; // Error code. + reason: string; // Reason for the error. +} +``` + +For details, see [Error Codes](#error-codes-table). + \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_stateitem-en.mdx b/shared/signaling/reference/api-ref/shared/_stateitem-en.mdx new file mode 100644 index 000000000..100f3353b --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_stateitem-en.mdx @@ -0,0 +1,21 @@ + + +`StateItem` data type contains the following properties: + +| Properties | Type | Description | +| :------------------ | :--------------------: | :------------------------------------- | +| `key` | string | Key of the user state. If the specified key already exists, the SDK overwrites the value; if the specified key does not exist, the SDK creates the key-value pair. | +| `value` | string | Value of the user state. | + + + + + +`AgoraRtmStateItem` data type contains the following properties: + +| Properties | Type | Description | +| :------------------ | :--------------------: | :------------------------------------- | +| `key` | NSString | Key of the user state. If the specified key already exists, the SDK overwrites the value; if the specified key does not exist, the SDK creates the key-value pair. | +| `value` | NSString | Value of the user state. | + + \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_stateitem.mdx b/shared/signaling/reference/api-ref/shared/_stateitem.mdx new file mode 100644 index 000000000..220f0bba9 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_stateitem.mdx @@ -0,0 +1,6 @@ +`StateItem` contains the following properties: + +| Property | Type | Description | +| :------------------ | :--------------------: | :------------------------------------- | +| `key` | string | Key of user status. If the provided key already exists, the new value overwrites the previous one. If the provided key does not exist, a new key-value pair is created.用户状态的键。 | +| `value` | string | Value of user status. | \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_storage.mdx b/shared/signaling/reference/api-ref/shared/_storage.mdx new file mode 100644 index 000000000..e9b16c6dd --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_storage.mdx @@ -0,0 +1,92 @@ +export const setchannel = { + android: "setChannelMetadata", + ios: "setChannelMetadata", + javascript: "setChannelMetadata", + linux: "setChannelMetadata", + unity: "SetChannelMetadataAsync", +}; +export const getchannel = { + android: "getChannelMetadata", + ios: "getChannelMetadata", + javascript: "getChannelMetadata", + linux: "getChannelMetadata", + unity: "GetChannelMetadataAsync", +}; +export const removechannel = { + android: "removeChannelMetadata", + ios: "removeChannelMetadata", + javascript: "removeChannelMetadata", + linux: "removeChannelMetadata", + unity: "RemoveChannelMetadataAsync", +}; +export const updatechannel = { + android: "updateChannelMetadata", + ios: "updateChannelMetadata", + javascript: "updateChannelMetadata", + linux: "updateChannelMetadata", + unity: "UpdateChannelMetadataAsync", +}; +export const setuser = { + android: "setUserMetadata", + ios: "setUserMetadata", + javascript: "setUserMetadata", + linux: "setUserMetadata", + unity: "SetUserMetadataAsync", +}; +export const getuser = { + android: "getUserMetadata", + ios: "getUserMetadata", + javascript: "getUserMetadata", + linux: "getUserMetadata", + unity: "GetUserMetadataAsync", +}; +export const removeuser = { + android: "removeUserMetadata", + ios: "removeUserMetadata", + javascript: "removeUserMetadata", + linux: "removeUserMetadata", + unity: "RemoveUserMetadataAsync", +}; +export const updateuser = { + android: "updateUserMetadata", + ios: "updateUserMetadata", + javascript: "updateUserMetadata", + linux: "updateUserMetadata", + unity: "UpdateUserMetadataAsync", +}; +export const subscribeuser = { + android: "subscribeUserMetadata", + ios: "subscribeUserMetadata", + javascript: "subscribeUserMetadata", + linux: "", + unity: "SubscribeUserMetadataAsync", +}; +export const unsubscribeuser = { + android: "unsubscribeUserMetadata", + ios: "unsubscribeUserMetadata", + javascript: "unsubscribeUserMetadata", + linux: "", + unity: "UnsubscribeUserMetadataAsync", +}; +// class +export const metadata = { + android: "Metadata", + ios: "AgoraRtmMetadata", + javascript: "RtmMetadata", + linux: "IMetadata", + unity: "RtmMetadata", +}; +export const metadataitem = { + android: "MetadataItem", + ios: "AgoraRtmMetadataItem", + javascript: "MetadataItem[]", + linux: "MetadataItem", + unity: "MetadataItem", +}; +export const metadataoptions = { + android: "MetadataOptions", + ios: "AgoraRtmMetadataOptions", + javascript: "MetadataOptions", + linux: "MetadataOptions", + unity: "MetadataOptions", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/shared/_topic.mdx b/shared/signaling/reference/api-ref/shared/_topic.mdx new file mode 100644 index 000000000..2a8d4c033 --- /dev/null +++ b/shared/signaling/reference/api-ref/shared/_topic.mdx @@ -0,0 +1,134 @@ +export const join = { + android: "joinTopic", + ios: "joinTopic", + javascript: "joinTopic", + linux: "joinTopic", + unity: "JoinTopicAsync", +}; +export const publish = { + android: "publishTopicMessage", + ios: "publishTopicMessage", + javascript: "publishTopicMessage", + linux: "publishTopicMessage", + unity: "PublishTopicMessageAsync", +}; +export const leave = { + android: "leaveTopic", + ios: "leaveTopic", + javascript: "leaveTopic", + linux: "leaveTopic", + unity: "LeaveTopicAsync", +}; +export const subscribe = { + android: "subscribeTopic", + ios: "subscribeTopic", + javascript: "subscribeTopic", + linux: "subscribeTopic", + unity: "SubscribeTopicAsync", +}; +export const unsubscribe = { + android: "unsubscribeTopic", + ios: "unsubscribeTopic", + javascript: "unsubscribeTopic", + linux: "unsubscribeTopic", + unity: "UnsubscribeTopicAsync", +}; +export const joinoptions = { + android: "JoinTopicOptions", + ios: "AgoraRtmJoinTopicOption", + javascript: "joinTopicOptions", + linux: "joinTopicOptions", + unity: "JoinTopicOptions", +}; +export const publishoptions = { + android: "PublishOptions", + ios: "AgoraRtmPublishOptions", + javascript: "publishOptions", + linux: "publishOptions", + unity: "PublishOptions", +}; +export const topicoptions = { + android: "TopicOptions", + ios: "AgoraRtmTopicOption", + javascript: "TopicOptions", + linux: "topicOptions", + unity: "TopicOptions", +}; +export const joinresulttype = { + android: "/", + ios: "/", + javascript: "JoinTopicResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const joinresult = { + android: "/", + ios: "/", + javascript: "JoinTopicResponse>", + linux: "REMOTE_JOIN_CHANNEL", + unity: "JoinTopicResult", +}; +export const publishresulttype = { + android: "/", + ios: "/", + javascript: "PublishTopicMessageResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "RtmResult", +}; +export const publishresult = { + android: "/", + ios: "/", + javascript: "PublishTopicMessageResponse", + linux: "REMOTE_JOIN_CHANNEL", + unity: "PublishTopicMessageResult", +}; +export const leaveresulttype = { + android: "/", + ios: "/", + javascript: "LeaveTopicResponse", + linux: "REMOTE_leave_CHANNEL", + unity: "RtmResult", +}; +export const leaveresult = { + android: "/", + ios: "/", + javascript: "LeaveTopicResponse>", + linux: "REMOTE_leave_CHANNEL", + unity: "LeaveTopicResult", +}; +export const subscriberesulttype = { + android: "SubscribeTopicResult", + ios: "/", + javascript: "SubscribeTopicResponse", + linux: "REMOTE_subscribe_CHANNEL", + unity: "RtmResult", +}; +export const subscriberesult = { + android: "/", + ios: "AgoraRtmTopicSubscriptionResponse", + javascript: "SubscribeTopicResponse>", + linux: "REMOTE_subscribe_CHANNEL", + unity: "SubscribeTopicResult", +}; +export const unsubscriberesulttype = { + android: "/", + ios: "/", + javascript: "UnsubscribeTopicResponse", + linux: "REMOTE_unsubscribe_CHANNEL", + unity: "RtmResult", +}; +export const unsubscriberesult = { + android: "/", + ios: "/", + javascript: "UnsubscribeTopicResponse>", + linux: "REMOTE_unsubscribe_CHANNEL", + unity: "UnsubscribeTopicResult", +}; +// Parameters +export const meta = { + android: "topicMeta", + ios: "meta", + javascript: "meta", + linux: "", + unity: "meta", +}; \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/troubleshooting.mdx b/shared/signaling/reference/api-ref/troubleshooting.mdx new file mode 100644 index 000000000..5559a7592 --- /dev/null +++ b/shared/signaling/reference/api-ref/troubleshooting.mdx @@ -0,0 +1,96 @@ +import Status from './shared/_rtmstatus-en.mdx'; +import * as code from './shared/_error-codes.mdx' + +## Troubleshooting + +Refer to the following information for troubleshooting API calls. + +### ErrorInfo + + + + +### Error codes table + +Refer to the following error codes table to identify and troubleshoot the problem: + +| Error code| Error description| Cause and solution | +| :------ | :---------------------- | :------------------------------------------------------------| +| `0` | {code.ok[props.ag_platform]} | Correct call | +| `-10002` | {code.notlogin[props.ag_platform]} | The user called the API without logging in to Signaling, disconnected due to timeout, or actively logged out. Please log in to Signaling first. | +| `-10003` | {code.invalidapp[props.ag_platform]} | Invalid App ID:
    - Check that the App ID is correct.
    - Ensure that Signaling has been activated for the App ID. | +| `-10005` | {code.invalidtoken[props.ag_platform]} | Invalid Token:
    - The token is invalid, check whether the Token Provider generates a valid Signaling Token. | +| `-10006` | {code.invaliduser[props.ag_platform]} | Invalid User ID:
    - Check if user ID is empty.
    - Check if the user ID contains illegal characters. | +| `-10008` | {code.invalidchanel[props.ag_platform]} | Invalid channel name:
    - Check if the channel name is empty.
    - Check if the channel name contains illegal characters. | +| `-10009` | {code.tokenexpired[props.ag_platform]} | Token expired. Call `renewToken` to reacquire the Token. | +| `-10010` | {code.loginnoserverresources[props.ag_platform]} | Server resources are limited. It is recommended to log in again. | +| `-10011` | {code.logintimeout[props.ag_platform]} | Login timeout. Check whether the current network is stable and switch to a stable network environment. | +| `-10012` | {code.loginrejected[props.ag_platform]} | SDK login rejected by the server:
    - Check tha Signaling is activated on your App ID.
    - Check if the token or `userId` is banned. | +| `-10013` | {code.loginaborted[props.ag_platform]} | SDK login interrupted due to unknown problem:
    - Check that the current network is stable and switch to a stable network environment.
    - The current `userId` is logged in. | +| `-10015` | {code.loginnotauthorized[props.ag_platform]} | No RTM service permissions. Check that the console opens Signaling services. | +| `-10018` | {code.instancealreadyreleased[props.ag_platform]} | Repeat `rtm` instantiation or `RTMStreamChannel` instantiation. | +| `-10019` | {code.invalidchanneltype[props.ag_platform]} | The channel type is invalid. SDK only supports the following channel types. Please fill in the correct value:
    • `MESSAGE`: Message Channel
    • ` STREAM`: Stream Channel
    | +| `-10020` | {code.invalidencryptionparameter[props.ag_platform]} | Message encryption parameters are invalid.
    • Check that the encryption key generated is a String.
    • Check that the generated encryption salt is `Uint8Array` type and that the length is 32 bytes.
    • Check that the encryption method matches the encryption key and the encryption salt.
    | +| `-10021` | {code.operationrateexceedlimitation[props.ag_platform]} | Channel metadata or User Metadata -related API call frequency is exceeding the limit. Please control the call frequency within 10/second. | +| `-11001` | {code.channelnotjoined[props.ag_platform]} | The user has not joined the channel:
    - The user is not online, offline or has not joined the channel
    - Check for typos in `userId`. | +| `-11002` | {code.channelnotsub[props.ag_platform]} | The user has not subscribed to the channel:
    - The user is not online, offline or has not joined the channel
    - Check for typos in `userId`. | +| `-11003` | {code.channeluserexceed[props.ag_platform]} | The number of subscribers to this topic exceeds the limit. | +| `-11005` | {code.instanceexceed[props.ag_platform]} | The number of created or subscribed channels exceeds the limit. See API usage limits for details. | +| `-11006` | {code.inerror[props.ag_platform]} | Channel is not available. Please recreate the Stream Channel or resubscribe to the Message Channel. | +| `-11007` | {code.channeljoinfailed[props.ag_platform]} | Failed to join this channel:
    - Check if the number of joined channels exceeds the limit.
    - Check if the channel name is illegal.
    - Check if the network is disconnected. | +| `-11008` | {code.invalidtopic[props.ag_platform]} | Invalid topic name:
    - Check whether the topic name contains illegal characters.
    - Check if the topic name is empty. | +| `-11009` | {code.invalidmessage[props.ag_platform]} | Invalid message. Check whether the message type is legal, Signaling only supports `string`, `Uint8Array` type messages. | +| `-11010` | {code.lengthexceed[props.ag_platform]} | Message length exceeded limit. Check if the message payload size exceeds the limit:
    - Message Channel single message package limit is 32 KB.
    - Stream Channel single message package limit is 1 KB. | +| `-11012` | {code.channelnotavailable[props.ag_platform]} | Invalid user list:
    - Check if the user list is empty
    - Check if the user list contains illegal items. | +| `-11013` | {code.topicnotsub[props.ag_platform]} | The topic is not subscribed. | +| `-11014` | {code.topicexceed[props.ag_platform]} | The number of topics exceeds the limit. | +| `-11015` | {code.topicjoinfailed[props.ag_platform]} | Failed to join this topic. Check whether the number of added topics exceeds the limit. | +| `-11016` | {code.topicnotjoined[props.ag_platform]} | The topic has not been joined. To send a message, you need to join the Topic first. | +| `-11017` | {code.topicnotexist[props.ag_platform]} | The topic does not exist. Check that the topic name is correct. | +| `-11018` | {code.invalidtopicmeta[props.ag_platform]} | The `meta` parameters in the topic are invalid. Check if the `meta` parameter exceeds 256 bytes. | +| `-11019` | {code.subtimeout[props.ag_platform]} | Channel subscription timed out. Check for broken connections. | +| `-11020` | {code.subfrequent[props.ag_platform]} | The channel subscription operation is too frequent. Make sure that the subscription operation of the same channel within a 5 seconds interval does not exceed 2 attempts. | +| `-11021` | {code.subfailed[props.ag_platform]} | Channel subscription failed. Check if the number of subscribed channels exceeds the limit. | +| `-11023` | {code.encryptfailed[props.ag_platform]} | Message encryption failed:
    - Check that the `cipherKey` is valid.
    - Check that the `salt` is valid.
    - Check if `encryptionMode` mode matches the `cipherKey` and `salt`. | +| `-11024` | {code.publishfailed[props.ag_platform]} | Message publishing failed. Check for broken connections. | +| `-11026` | {code.publishtimeout[props.ag_platform]} | Message publishing timed out. Check for broken connections. | +| `-11028` | {code.channelleavefailed[props.ag_platform]} | Failed to leave the channel. Check for broken connections. | +| `-11029` | {code.customoverflow[props.ag_platform]} | Custom type length overflow. The length of the `customType` field must to be within 32 characters. | +| `-11030` | {code.custominvalid[props.ag_platform]} | `customType` field is invalid. Check the `customType` field for illegal characters. | +| `-12001` | {code.storagefailed[props.ag_platform]} | Storage operation failed. | +| `-12002` | {code.metadataexceed[props.ag_platform]} | The number of Storage Metadata Items exceeds the limit. | +| `-12003` | {code.invalidmetadata[props.ag_platform]} | Invalid Metadata Item. | +| `-12004` | {code.storageinvalidarg[props.ag_platform]} | Invalid argument. | +| `-12005` | {code.invalidrevision[props.ag_platform]} | Invalid Revision parameter. | +| `-12006` | {code.storageoverflow[props.ag_platform]} | Metadata overflows. | +| `-12007` | {code.invalidlock[props.ag_platform]} | Invalid Lock name. | +| `-12008` | {code.storagelocknotacquired[props.ag_platform]} | The Lock was not acquired. | +| `-12009` | {code.storageinvalidkey[props.ag_platform]} | Invalid Metadata key. | +| `-12010` | {code.storageinvalidvalue[props.ag_platform]} | Invalid metadata value. | +| `-12011` | {code.storagekeyoverflow[props.ag_platform]} | Metadata key length overflow. | +| `-12012` | {code.storagevalueoverflow[props.ag_platform]} | Metadata value length overflow. | +| `-12014` | {code.outdatedrevision[props.ag_platform]} | Outdated Revision parameter. | +| `-12015` | {code.storagenotsub[props.ag_platform]} | This channel is not subscribed. | +| `-12017` | {code.storagesubexceed[props.ag_platform]} | The number of subscribers exceeds the limit. | +| `-12018` | {code.storagetimeout[props.ag_platform]} | Storage operation timed out. | +| `-12019` | {code.storagenotavailable[props.ag_platform]} | The Storage service is not available. | +| `-13001` | {code.presencenotconnected[props.ag_platform]} | The user is not connected to the system. | +| `-13003` | {code.presenceinvalidarg[props.ag_platform]} | Invalid argument. | +| `-13004` | {code.cachestates[props.ag_platform]} | The temporary user state cached before joining the channel exceeds the limit. See API usage limits for details. | +| `-13005` | {code.stateoverflow[props.ag_platform]} | The number of temporary user state key/value pairs exceeds the limit. See API usage limits for details. | +| `-13006` | {code.invalidstatekey[props.ag_platform]} | Invalid state key. | +| `-13008` | {code.presencekeyoverflow[props.ag_platform]} | Presence key length overflow. | +| `-13009` | {code.presencevalueoverflow[props.ag_platform]} | Presence value overflow | +| `-13010` | {code.presenceduplicatekey[props.ag_platform]} | Repeated state key. | +| `-13011` | {code.usernotexist[props.ag_platform]} | The user does not exist. | +| `-13012` | {code.presencetimeout[props.ag_platform]} | Presence operation timed out. | +| `-13013` | {code.presencefailed[props.ag_platform]} | Presence operation failed. | +| `-14001` | {code.lockfailed[props.ag_platform]} | Lock operation failed. | +| `-14002` | {code.locktimeout[props.ag_platform]} | Lock operation timed out. | +| `-14003` | {code.performing[props.ag_platform]} | Lock operation in progress. | +| `-14004` | {code.lockexist[props.ag_platform]} | Lock already exists. | +| `-14005` | {code.lockinvalidname[props.ag_platform]} | Invalid Lock name. | +| `-14006` | {code.locknotacquired[props.ag_platform]} | The Lock was not acquired. | +| `-14007` | {code.lockacquirefailed[props.ag_platform]} | Failed to acquire the Lock. | +| `-14008` | {code.locknotexist[props.ag_platform]} | The Lock does not exist. | +| `-14009` | {code.locknotavailable[props.ag_platform]} | Lock service is not available. | \ No newline at end of file diff --git a/shared/signaling/reference/api-ref/web.mdx b/shared/signaling/reference/api-ref/web.mdx new file mode 100644 index 000000000..c82741a08 --- /dev/null +++ b/shared/signaling/reference/api-ref/web.mdx @@ -0,0 +1,50 @@ + +import Configuration from '@docs/shared/signaling/reference/api-ref/_configuration-en.javascript.mdx'; +import Channels from '@docs/shared/signaling/reference/api-ref/_channel-en.javascript.mdx'; +import Topics from '@docs/shared/signaling/reference/api-ref/_topic-en.javascript.mdx'; +import Messages from '@docs/shared/signaling/reference/api-ref/_message-en.javascript.mdx'; +import Presence from '@docs/shared/signaling/reference/api-ref/_presence-en.javascript.mdx'; +import Storage from '@docs/shared/signaling/reference/api-ref/_storage-en.javascript.mdx'; +import Lock from '@docs/shared/signaling/reference/api-ref/_lock-en.javascript.mdx'; +import Enums from '@docs/shared/signaling/reference/api-ref/_enumv-en.mdx'; +import Troubleshooting from '@docs/shared/signaling/reference/api-ref/troubleshooting.mdx'; + +The Signaling SDK API Reference lists the description, methods, basic usage, sample code, and return values. It is divided in to the following sections: + +* [Setup](#setup) +* [Channels](#channels) +* [Topics](#topics) +* [Messages](#messages) +* [Presence](#presence) +* [Storage](#storage) +* [Lock](#lock) +* [Enumerated types](#enumerated-types) +* [Troubleshooting](#troubleshooting) + +## Setup + + +## Channels + + +## Topics + + +## Messages + + +## Presence + + +## Storage + + +## Lock + + +## Enumerated types + + + + + \ No newline at end of file diff --git a/shared/signaling/release-notes/android.mdx b/shared/signaling/release-notes/android.mdx deleted file mode 100644 index 9078900bf..000000000 --- a/shared/signaling/release-notes/android.mdx +++ /dev/null @@ -1,721 +0,0 @@ - -This page contains information on the following releases: - -## v1.5.3 - -v1.5.3 was released on October 17, 2022. In this release, OpenSSL is upgraded to v1.1.1q. - - -## v1.5.2 - -v1.5.2 was released on October 12, 2022 and improves the stability of the SDK. - - -## v1.5.1 - -v1.5.1 was released on September 1, 2022 and improved the stability of the SDK. - - -## v1.5.0 -v1.5.0 was released on July 27, 2022. - -#### Sunset features -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - -#### API changes - - -The following methods are deprecated: - -- createFileMessageByMediaId -- createFileMessageByUploading -- createImageMessageByMediaId -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- downloadMediaToFile -- downloadMediaToMemory -- onFileMessageReceived -- onFileMessageReceivedFromPeer -- onImageMessageReceived -- onImageMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress -- enableOfflineMessaging -- enableHistoricalMessaging - -## v1.4.10 - -v1.4.10 was released on March 01, 2022. - -#### Compatibility changes - -As of v1.4.10, You don’t need to add the following permission to the `AndroidManifest.xml` file of an Android project: - -```java - -``` - -#### Issues fixed - -Fixed some rich media related crashes. - -## v1.4.9 - -v1.4.9 was released on November 19, 2021. - -#### Compatibility changes - -- As of v1.4.9, you can automatically integrate the Agora Android SDK through Maven Central. To integrate the SDK with Maven Central, see [Integrate the SDK](../get-started/get-started-sdk). - -- As of v1.4.9, you need to add the following permission to the `AndroidManifest.xml` file of an Android project to check the connection status of the WIFI network: - -#### Improvements - -Improved the login success rate and connection stability under the IPv4/IPv6 dual-stack network. - -## v1.4.7 - -v1.4.7 was released on July 19, 2021. - -Improved the success rate of logins and message delivery for the in poor network conditions. - -## v1.4.6 - -v1.4.6 was released on June 21, 2021. - -Fixed some issues that may cause crashes to improve stability. - -## v1.4.5 - -v1.4.5 was released on April 30, 2021. - -#### Improvements - -Fixed some issues that may cause crashes to improve stability. - -## v1.4.4 - -v1.4.4 was released on April 20, 2021. - -#### Compatibility changes - -**Integration changes** - -Because JCenter is about to retire, as of this release, Agora publishes the SDK package to JitPack instead of JCenter. To integrate the SDK with JitPack, see [Integrate the SDK](../get-started/get-started-sdk). - -#### Improvements - -Improved the success rate of logins and message delivery for the in poor network conditions. - -#### Issues fixed - -Fixed some issues that might cause the system to crash. - -## v1.4.3 - -v1.4.3 was released on February 10, 2021. - -#### Issues fixed - -This release fixed the following issues: - -- Crash issues caused by occasional multi-thread access conflict. - -- High timeout rate for login operations. - -## v1.4.2 - -v1.4.2 was released on November 23, 2020. - -#### Improvements - -Improved performance of login and messaging operations. - -## v1.4.1 - -v1.4.1 was released on September 30, 2020. - -#### Improvements - -Improved the log file. - -## v1.4.0 - -v1.4.0 was released on September 1, 2020. - -#### Compatibility changes - -- You need to add new ports to the firewall whitelist. See [Firewall Requirements](../reference/firewall). - - - New TCP ports: 8443, 9136, 9137, 9141. New UDP port: 8443. Reason: Support real-time transport encryption. - - - New UDP ports: 8130, 9120, 9121. Reason: Support UDP path to improve the SDK’s performance in sub-optimal network conditions. - - - New UDP port: 9700. Reason: Support data reporting. - -- In `setLogFileSize`, the default log file size increases from 512 KB to 10 MB. The maximum log file size increases from 10 MB to 1 GB. - -#### New features - -- Geofencing. You can call `setRtmServiceContext` to set the region of the Agora . The can only connect to Agora servers within the specified region. - -- Transport encryption. The encryption is enabled by default. To disable the feature, contact support@agora.io. - -#### Improvements - -- Improved the success rate of login and message delivery of the in poor network conditions. - -- Optimized the reconnection mechanism. - -#### API changes - -**New methods** - -setRtmServiceContext - -## v1.3.0 - -v1.3.0 was released on May 8, 2020. - -#### Compatibility changes - -- You need to add a new TCP port, 9140, to the firewall whitelist. The port is for sending and receiving image or file messages. See [Firewall Requirements](../reference/firewall). - -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. - -#### New features - -1. Send and receive file messages - - v1.3.0 supports downloading non-empty files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each file you upload to the Agora server corresponds to a media ID. The file stays on the Agora server for seven days. You can use the media ID to download the file as long as the file is still on the Agora server. - - v1.3.0 adds the `RtmFileMessage` message class for saving and transferring a media ID. The `RtmFileMessage` class inherits from the `RtmMessage` class, so you can use the existing peer-to-peer or channel messaging methods to transfer the `RtmFileMessage` instance. You can use the `RtmFileMessage` object to complete the following tasks: - - - Set the filename and thumbnail of the uploaded file. - - - Get the size of the uploaded file. - -2. Send and receive image messages - - v1.3.0 supports downloading non-empty image files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each image you upload to the Agora server corresponds to a media ID. The image file stays in the Agora server for seven days. You can use the media ID to download the image file as long as it is still on the Agora server. - - v1.3.0 adds the `RtmImageMessage` message class for saving and transferring a media ID. The `RtmImageMessage` class inherits from the `RtmMessage` class, so you can use the existing peer-to-peer or channel messaging methods to transfer the `RtmImageMessage` instance. You can use the `RtmImageMessage` object to complete the following tasks: - - - Set the filename and thumbnail of the uploaded image file. - - - Get the size of the uploaded image file. - - - Get the SDK-calculated width or height of image files in JPEG, JPG, BMP, or PNG format. - - - Set the width or height of image files. The width or height you set overwrites the width or height that the SDK calculates. - -3. Report the progress of upload or download - - The SDK returns the progress of an upload or download by callback every second during a task in progress. If the upload or download task pauses, the SDK ceases to return any further callback until the task continues. - -#### Bug fixes - -- Login failure caused by the SDK’s incorrect identification of user’s network type. - -- Other problems that may cause the system to crash. - -#### API changes - -**New methods** - -- createFileMessageByMediaId -- createImageMessageByMediaId -- createFileMessageByUploading -- createImageMessageByUploading -- downloadMediaToMemory -- downloadMediaToFile -- cancelMediaUpload -- cancelMediaDownload - -**New callbacks** -- onImageMessageReceived -- onFileMessageReceived -- onImageMessageReceivedFromPeer -- onFileMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress - -**Deprecated methods** -- sendMessage (RtmMessage message, ResultCallback\ resultCallback) is deprecated. Use sendMessage (RtmMessage message instead. - -## v1.2.2 - -v1.2.2 was released on December 13, 2019. - -**Issues Fixed** - -Occasionally fails to receive any callback after a channel attribute operation. - -## v1.2.1 - -v1.2.1 was released on November 29, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - -- The SDK fails to reconnect to the Agora system if the user disables VPN. - -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `onMemberJoined` twice. - -## v1.2.0 - -v1.2.0 was released on November 6, 2019. - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the onPeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - -If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - -**Issues Fixed** - -- The system returns `rtm native not ready`, if one creates multiple channels with the same `channelId` and then calls `join` or `leave`. - -## v1.1.0 - -v1.1.0 is released on September 18, 2019. It adds the following features: - -- Gets the member count of specified channel(s). - -- Automatically returns the latest numer of members in the current channel - -- Channel attribute operations - -**Compatibility Changes** - -1. Deprecates the sendMessageToPeer method, and uses sendMessageToPeer(const char \*, const IMessage \*, const SendMessageOptions &) instead. - -2. The getServerReceivedTs method of the RtmMessage object supports both peer-to-peer and channel messages. - -3. Timeout for sending a peer-to-peer message is 10 seconds from this release, compared to 5 seconds in previous versions. See PEER_MESSAGE_ERR_TIMEOUT. - -4. Puts a limit on the frequency of join the same channel: Two times every five seconds. - -**New Features** - -1. Gets the member count of specified channel(s). - - You can now get the member count of specified channel(s) without the need to join, by calling the getChannelMemberCount method. You can get the member counts of a maximum of 32 channels in one method call. - -2. Automatically returns the latest numer of members in the current channel - - If you are already in a channel, you do not have to call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members onMemberCountUpdated the latest channel member count when the number of channel members changes. Note that: - - - When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. - - - When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - - Please treat this callback and the getMembers method separately: - - - The former is an active callback. It returns the current numer of channel members; - - - The latter relies on the onSuccess callback to return a member list of the current channel. If the number of channel members exceeds 512, the SDK only returns a list of 512 randomly-selected channel members. - -3. Channel attribute operations - - Supports setting or getting the attribute(s) of a specified channel. You can use this feature to create group anouncement. - - Each channel attribute comes as a key-value pair. See RtmChannelAttribute for more information. Where: - - - The key of each channel attribute must be visible characters and not exceed 8 KB. - - - Each channel attribute must not exceed 8 KB in length. - - - The overall size of the attributes of a channel must not exceed 32 KB. - - - The number of attributes of a channel must not exceed 32. - - Specific features: - - - Sets the attributes of a specified channel with new ones. - - - Adds or updates the attribute(s) of a specified channel. - - - Deletes the attributes of a specified channel by attribute keys. - - - Clears all attributes of a specified channel. - - - Gets all attributes of a specified channel. - - - Gets the attributes of a specified channel by attribute keys. - - When updating attributes of a channel, you can use the setEnableNotificationToChannelMembers flag to decide whether or not to notify all members of the channel about this attribute change. - - The SDK caches the channel attributes. If multiple users have the privilege to update the channel attributes, then we recommend calling the getChannelAttributes to update the cache before updating the channel attributes. - -**Improvements** - -#### Resends peer-to-peer messages - -This release improves the resending mechanism of peer-to-peer messages, and extends the timeout for sending a peer-to-peer message from five to 10 seconds, greatly improving the success rate of peer-to-peer message sending under weak network conditions. - -#### Caches channel messages - -The Agora system will resend a maximum of 32 channel messages of up to 30 seconds to channel members, when they manage to reconnect to the system from poor network conditions. This greatly improves the overall arrival rate of channel messages under weak network conditions. - -**API Changes** - -#### Added Methods - -- setChannelAttributes: Sets the attributes of a specified channel with new ones. - -- addOrUpdaeChannelAttributes: Adds or updates the attribute(s) of a specified channel. - -- deleteChannelAttributesByKeys: Deletes the attributes of a specified channel by attribute keys. - -- clearChannelAttributes: Clears all attributes of a specified channel. - -- getChannelAttributes: Gets all attributes of a specified channel. - -- getChannelAttributesByKeys : Gets the attributes of a specified channel by attribute keys. - -- getChannelMemberCount : Gets the member count of specified channel(s). - -#### Added Callbacks - -- onAttributesUpdated: Returns all attributes of the channel when the channel attributes are updated. - -- onMemberCountUpdated : Occurs when the number of the channel members changes, and returns the new number. - -#### Added Error Codes - -- GetChannelMemberCountErrCode : Error codes related to retrieving the channel member count of specified channel(s). - -- JOIN_CHANNEL_ERR_JOIN_SAME_CHANNEL_TOO_OFTEN : The frequency of joining the same channel exceeds two times every five seconds. - -#### Deprecated Methods - -- sendMessageToPeer: Replaced by the sendMessageToPeer(const char \*, const IMessage \*, const SendMessageOptions &) method. - -#### Deprecated Error Codes - -- ATTRIBUTE_OPERATION_ERR_NOT_READY: Replaced by ATTRIBUTE_OPERATION_ERR_USER_NOT_LOGGED_IN. - -## v1.0.1 - -v1.0.1 is released on August 1st, 2019. - -**Issues Fixed** - -- When the connection to the Agora system is interrupted, the SDK does not return the `onConnectionStateChanged` callback. - -## v1.0.0 - -v1.0.0 is released on July 24th, 2019. - -**New Features** - -#### Interconnects with the legacy Agora Signaling SDK - -v1.0.0 implements the `LocalInvitation.setChannelId` and `LocalInvitation.getChannelId` methods. - -- To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora does not join the channel of the specified channel ID. - -- If your App does not involve the legacy Agora Signaling SDK, we recommend using the `LocalInvitation.setContent` method or the `RemoteInvitation.setResponse` method to set customized contents. - -#### Specifies the default path to the SDK log file - -Supports changing the default path to the SDK log file using the `setLogFile` method. To avoid creating an incomplete log file, we recommend calling this method once you have created and initialized an `RtmClient` instance. - -#### Sets the output log level of the SDK - -Supports setting the output log level of the SDK using the `setLogFilter` method. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. - -You can call this method once you have created and initializd an `RtmClient` instance. You do not have to call this method after calling the `login` method. - -#### Sets the log file size in KB - -Supports setting the log file size using the `setLogFileSize` method. The log file has a default size of 512 KB. File size settings of less than 512 KB or greater than 10 MB will not take effect. - -You can call this method once you have created and initializd an `RtmClient` instance. You do not have to call this method after calling the `login` method. - -**Improvements** - -Adds error codes based on the following scenarios: - -- The Agora service is not initialized. - -- The method call frequency exceeds the limit. - -- The user does not call the `login` method or the method call of `login` does not succeed before calling any of the core APIs. - -**Issues Fixed** - -- One can log in the Agora system with a static App ID and an token, which is generated from a dynamic App ID. - -**API Changes** - -- setLogFile: Specifies the default path to the SDK log file. - -- setLogFilter: Sets the output log level of the SDK. - -- setLogFileSize: Sets the log file size in KB. - -- getSdkVersion : Gets the SDK version. - -## v0.9.3 - -v0.9.3 was released on June 7th, 2019. - -**New Features** - -#### Sends an (offline) peer-to-peer message to a specified user (receiver) - -This version allows you to send a message to a specified user when he/she is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that for now we only cache 200 offline messages for up to seven days for each receiver. When the number of the cached messages reaches this limit, the newest message overrides the oldest one. - -#### User attribute-related operations - -This version allows you to set or update a user’s attributes. You can: - -- Substitutes the local user’s attributes with new ones. - -- Adds or updates the local user’s attribute(s). - -- Deletes the local user’s attributes using attribute keys. - -- Clears all attributes of the local user. - -- Gets all attributes of a specified user. - -- Gets the attributes of a specified user using attribute keys. - -Please note that: - -- Only after you successfully loggin in the Agora system can you execute user attribute-related operations. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_NOT_READY` error code. - -- The attributes you set will be clears when you log out of . - -- You can only set a maximum of 16 KB attributes in a single method call. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_SIZE_OVERFLOW` error code. - -**Improvements** - -- Supports creating an channel before logging in the Agora system. - -- Supports creating multiple channels. But a user can only join a maximum of 20 channels at the same time. When the number of the joined channels exceeds 20, the SDK triggers the `JOIN_CHANNEL_ERR_FAILURE` error code. - -**Issues Fixed** - -- Occasional system crashes. - -- A user who has logged out of the Agora system appears online to the other users until 30 seconds later. - -## v0.9.2 - -v0.9.2 is released on May 5th, 2019. - -This release does not support creating an RtmChannel instance before logging in the Agora system - -**New Features** - -#### Queries the Online Status of the Specified Users - -This release introduces a new concept: online and offline. - -- Online: The user has logged in the Agora system. - -- Offline: The user has logged out of the Agora system. - -This release adds the function of querying the online status of the specified users. After logging in the Agora system, you can get the online status of a maximum of 256 specified users. See queryPeersOnlineStatus. - -Please note that: - -- The sequence of the returned user IDs is identical to the input sequence. - -- The call frequency of this method is 10 times every five seconds. - -#### Renews the Token - -In the production environment, you need to use a token to log in the Agora system. Each token expires 24 hours after it is created. This release allows you to renew a token. - -- If you are logging in the Agora system and if your token has expired, the SDK returns the LOGIN_ERR_TOKEN_EXPIRED error code. - -- if you are logged in the Agora system, you will not be kicked out immediately when your token expires. But you need to renew your token the next time you log in the Agora system. Therefore, we still recommend that you renew your token when you receive the onTokenExpired callback. - -Please note that: - -- The renewToken method must be called before creating an RtmClient. - -- The call frequency of the renewToken method is two times every second. - -**Improvements** - -- Supports a `userId` that starts with a space. - -**API Changes** - -#### Queries the Online Status of the Specified Users - -#### Adds - -- Method: queryPeersOnlineStatus - -- Error Code: QueryPeersOnlineStatusError - -#### Renews the Token - -#### Adds - -- Method: renewToken - -- Callback: onTokenExpired - -- Error Codes: - -- RenewTokenError - -#### Call Invitation - -Adds the following error code for when a user sends a call invitation without logging in the Agora system. - -- LOCAL_INVITATION_ERR_NOT_LOGGEDIN - -## v0.9.1 - -v0.9.1 is released on April 4th, 2019. - -Please note that this version does not come with the `setLogFile` and `setLogFilter` method. The default log file location is at **/sdcard/\/agorartm.log**. - -**New Features** - -This release adds the call invitation feature, allowing you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. - -**Improvements** - -- Optimizes the object relations to facilitate understanding. - -- Renames some interfaces to conform to Java naming conventions. - -- Removes `ChannelMessageState` and `PeerMessageState` to simplify the process of sending a channel or peer-to-peer message. Uses `ChannelMessageError` and `PeerMessageError` instead. - -- Removes `IStateListener` for listening to message states. Uses the generic `ResultCallback` instead. - -**API Changes** - -#### Adds - -- LocalInvitation.setContent(): allows the caller to set the content of an outgoing call invitation. - -- LocalInvitation.getContent(): allows the caller to retrieve the content of an outgoing call invitation. - -- LocalInvitation.getResponse(): allows the caller to retrieve the response set by the callee. - -- LocalInvitation.getState(): allows the caller to retrieve the state of an outgoing call invitation. - -- RemoteInvitation.getCallerId() : allows the callee to retrieve the user ID of the caller. - -- RemoteInvitation.getContent() : allows the callee to retrieve the content set by the caller. - -- RemoteInvitation.setResponse(): allows the callee to set the response to the caller. - -- RemoteInvitation.getResponse(): allows the callee to retrieve the response to the caller. - -- RemoteInvitation.getState(): allows the callee to retrieve the state of the incoming call invitation - -- RtmCallEventListener.onLocalInvitationReceivedByPeer(): occurs when the callee receives the call invitation. - -- RtmCallEventListener.onLocalInvitationAccepted(): occurs when the callee accepts the call invitation. - -- RtmCallEventListener.onLocalInvitationRefused(): occurs when the callee declines the call invitation. - -- RtmCallEventListener.onLocalInvitationCanceled(): occurs when the caller cancels the call invitation. - -- RtmCallEventListener.onLocalInvitationFailure(): occurs when the outgoing call invitation fails. - -- RtmCallEventListener.onRemoteInvitationReceived(): occurs when the callee receives a call invitation. - -- RtmCallEventListener.onRemoteInvitationAccepted(): occurs when the callee accepts a call invitation. - -- RtmCallEventListener.onRemoteInvitationRefused(): occurs when the callee declines a call invitation. - -- RtmCallEventListener.onRemoteInvitationCanceled(): occurs when the caller cancels the call invitation. - -- RtmCallEventListener.onRemoteInvitationFailure(): occurs when the incoming call invitation fails. - -- RtmCallManager.setEventListener(): sets the event listener to the `RtmCallManager` instance. - -- RtmCallManager.createLocalInvitation(): creates a call invitation. - -- RtmCallManager.sendLocalInvitation(): sends a call invitation to a specified user. - -- RtmCallManager.acceptRemoteInvitation() : accepts an incoming call invitation. - -- RtmCallManager.refuseRemoteInvitation(): declines an incoming call invitation. - -- RtmCallManager.cancelLocalInvitation(): allows the caller to cancel an outgoing call invitation. - -- RtmStatusCode#LocalInvitationState: states of an outgoing call invitation. - -- RtmStatusCode#RemoteInvitationState : states of an incoming call invitation. - -- RtmStatusCode#LocalInvitationError: error codes of an outgoing call invitation. - -- RtmStatusCode#RemoteInvitationError: error codes of an incoming call invitation. - -- RtmStatusCode#InvitationApiCallError: error codes of the invitation-specific API calls. - -- ConnectionChangeReason#CONNECTION_CHANGE_REASON_REMOTE_LOGIN: another instance has logged in the Agora system with the same user ID. - -#### Renames - -- The `RtmClient.destroy()` method, which releases all resources used by the `RtmClient` instance, to: RtmClient.release(). - -- The `IResultCallback` class to: ResultCallback - -#### Deletes - -- Deletes `PEER_MESSAGE_RECEIVED_BY_SERVER` from PeerMessageError, uses `PEER_MESSAGE_ERR_OK` instead. - -- Deletes `CHANNEL_MESSAGE_RECEIVED_BY_SERVER` from ChannelMessageError, uses `CHANNEL_MESSAGE_OK` instead. - -- Deletes the `PeerMessageState` interface, uses PeerMessageError instead. - -- Deletes the `ChannelMessageState` interface, uses ChannelMessageError instead. - -- Deletes the `IStateListener` class for listening to message states, uses the ResultCallback class instead for listening to the peer or channel message results. - -- Success: the SDK returns the ResultCallback.onSuccess() callback. - -- Failure: the SDK returns the ResultCallback.onFailure() callback with the corresponding error codes. - -## v0.9.0 - -v0.9.0 is released on February 4th, 2019. - -Initial version. - -Key features: - -- Sends or receives peer-to-peer messages. - -- Joins or leaves a channel. - -- Sends or receives channel messages. - - diff --git a/shared/signaling/release-notes/cocos-creator.mdx b/shared/signaling/release-notes/cocos-creator.mdx deleted file mode 100644 index 1074f4db7..000000000 --- a/shared/signaling/release-notes/cocos-creator.mdx +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/shared/signaling/release-notes/cpp.mdx b/shared/signaling/release-notes/cpp.mdx deleted file mode 100644 index a07144582..000000000 --- a/shared/signaling/release-notes/cpp.mdx +++ /dev/null @@ -1,533 +0,0 @@ - - - -## v1.5.1 - -v1.5.1 was released on September 1, 2022 and improved the stability of the SDK. - - -### v1.5.0 -v1.5.0 was released on July 27, 2022. - -#### Sunset features -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - -#### API changes - -The following methods are deprecated: - -- createFileMessageByMediaId -- createFileMessageByUploading -- createImageMessageByMediaId -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- downloadMediaToMemory -- downloadMediaToFile -- enableOfflineMessaging -- enableHistoricalMessaging -- onFileMessageReceived -- onFileMessageReceivedFromPeer -- onImageMessageReceived -- onImageMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress - -### v1.4.10 -v1.4.10 was released on March 01, 2022. - -#### Issues fixed - -Fixed some rich media related crashes. - -### v1.4.9 -v1.4.9 was released on November 26, 2021. - -#### Improvements - -Improved the login success rate and connection stability under the IPv4/IPv6 dual-stack network. - -### v1.4.7 -v1.4.7 was released on July 19, 2021. - -Improved the success rate of logins and message delivery for the in poor network conditions. - -### v1.4.6 - -v1.4.6 was released on June 21, 2021. - -Fixed some issues that may cause crashes to improve stability. - -### v1.4.5 - -v1.4.5 was released on April 30, 2021. - -#### Improvements - -Fixed some issues that may cause crashes to improve stability. - -### v1.4.4 - -v1.4.4 was released on April 20, 2021. - -#### Improvements - -Improved the success rate of logins and message delivery for the in poor network conditions. - -#### Issues fixed - -Fixed some issues that might cause the system to crash. - -### v1.4.3 - -v1.4.3 was released on February 10, 2021. - -#### Issues fixed - -This release fixed the following issues: - -- Crash issues caused by occasional multi-thread access conflict. -- High timeout rate for login operations. - -### v1.4.2 - -v1.4.2 was released on November 23, 2020. - -**Compatibility changes** - -- For CentOS, v1.4.2 does not support CentOS 7 or earlier. If your CentOS is 7 or earlier, Agora recommends that you use v1.4.1. -- In `setLogFileSize`, the default log file size increases from 10 MB to 100 MB. - -**Improvements** - -- Improved the performance of login and messaging operations. -- Added the `AGORA_SDK_BOTH_RTM_AND_RTC` macro for the `RTM_AREA_CODE` enum type. You can use the macro to resolve naming conflicts when using and together. - -### v1.4.1 - -v1.4.1 was released on September 30, 2020. - -**Improvements** - -Improved the log file. - - -### v1.4.0 - -v1.4.0 was released on September 1, 2020. - -**Compatibility changes** - -- You need to add new ports to the firewall whitelist. See [Firewall Requirements](../reference/firewall). - - New TCP ports: 8443, 9136, 9137, 9141. New UDP port: 8443. Reason: Support real-time transport encryption. - - New UDP ports: 8130, 9120, 9121. Reason: Support UDP path to improve the SDK's performance in sub-optimal network conditions. - - New UDP port: 9700. Reason: Support data reporting. -- In `setLogFileSize`, the default log file size increases from 512 KB to 10 MB. The maximum log file size increases from 10 MB to 1 GB. - -**New features** - -- Geofencing. You can call `setRtmServiceContext` to set the region of the Agora . The can only connect to Agora servers within the specified region. -- Transport Layer Security (TLS) encryption. - -**Improvements** - -- Improved the success rate of login and message delivery of the in poor network conditions. -- The call frequency limit has increased for the following operations. See [Limitations](../reference/limitations). - -| Operation | Call frequency limit change | -| :---------------------------------------- | :----------------------------------------------------------- | -| Send peer-to-peer or channel messages | Increased from 300 calls every three seconds to 1,500 calls every three seconds | -| Query user online status | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Add, delete, or update user attributes | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Query user attributes | Increased from 80 calls every five seconds to 400 calls every five seconds | -| Add, delete, or update channel attributes | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Query channel attributes | Increased from 80 calls every five seconds to 400 calls every five seconds | - -- Optimized the reconnection mechanism. - -**API changes** - -#### New methods - -setRtmServiceContext. - -### v1.3.0 - -v1.3.0 was released on June 12. - -**Compatibility changes** - -- You need to add a new TCP port, 9140, to the firewall whitelist. The port is for sending and receiving image or file messages. See [Firewall Requirements](../reference/firewall). -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. - -**New features** - -#### 1. Send and receive file messages or image messages - -You can call `createFileMessageByUploading` or `createImageMessageByUploading` to upload non-empty files or image files no greater than 30 MB. Each uploaded file or image stays in the Agora server for seven days. The SDK returns a media ID as the unique indentifier of the file or image file. You can use the `IFileMessage` class or the `IImageMessage` class to save the media ID. The `IFileMessage` class and the `IImageMessage` class inherit from the `IMessage` class, so you can send and receive file or image messages via peer-to-peer or channel message methods. You can call `downloadMediaToMemory` or `downloadMediaToFile` to download the received file or image file. - -#### 2. Manage upload or download tasks - -You can call `cancelMediaUpload` or `cancelMediaDownload` to cancel an upload or download task. You also can use the `onMediaUploadingProgress` callback or the `onMediaDownloadingProgress` callback to return upload or download progress. - -**Improvements** - -The call limits of the following operations have increased. See [Limitations](../reference/limitations). - -| Operation | Call limit increase | -| :---------------------------------------- | :----------------------------------------------------------- | -| Send peer-to-peer or channel messages | From 180 calls every three seconds to 300 calls every three seconds | -| Query user online status | From 10 calls every five seconds to 20 calls every five seconds | -| Add, delete, or update user attributes | From 10 calls every five seconds to 20 calls every five seconds | -| Query user attributes | From 40 calls every five seconds to 80 calls every five seconds | -| Add, delete, or update channel attributes | From 10 calls every five seconds to 20 calls every five seconds | -| Query channel attributes | From 10 calls every five seconds to 80 calls every five seconds | - -**Fixed issues** - -- Login failure caused by the SDK's incorrect identification of user's network type. -- Other problems that may cause the system to crash. - -**API changes** - -#### New methods - -- createFileMessageByUploading -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- createFileMessageByMediaId -- createImageMessageByMediaId -- downloadMediaToMemory -- downloadMediaToFile - -#### New callbacks - -- onMediaUploadingProgress -- onMediaDownloadingProgress -- onMediaCancelResult -- onFileMediaUploadResult -- onImageMediaUploadResult -- onFileMessageReceivedFromPeer -- onImageMessageReceivedFromPeer -- onFileMessageReceived -- onImageMessageReceived -- onMediaDownloadToMemoryResult -- onMediaDownloadToFileResult - -#### Deprecated methods - -sendMessage is deprecated. Use sendMessage (const IMessage *message, const SendMessageOptions &options) instead. - -### v1.2.2 - -v1.2.2 was released on December 13, 2019. - - -**Compatibility Changes** - -This release deprecates the createAgoraService method, which creates an IAgoraService instance, and the initialize method, which initializes the created IAgoraService instance. As of this relase, you only need to call the createRtmService method and the initialize method to initialize it before being able to call its functions. - - -**Issues Fixed** - -Occasionally fails to receive any callback after a channel attribute operation. - -### v1.2.1 - -v1.2.1 was released on November 29, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - - -- The SDK fails to reconnect to the Agora system if the user disables VPN. -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `onMemberJoined` twice. - -### v1.2.0 - -v1.2.0 was released on November 6, 2019. - -**Compatibility Changes** - -Deprecated the `isOnline` property of the `PeerOnlineStatus`. Use `onlineState` instead. - - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the onPeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - - If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - -### v1.1.0 - -v1.1.0 was released on October 14, 2019. It adds the following features: - -- [Gets the member count of specified channel(s).](#getcount) -- [Automatically returns the latest numer of members in the current channel](#oncount) -- [Channel attribute operations](#channelattributes) - - - -**Compatibility Changes** - -1. Deprecates the sendMessageToPeer method, and uses sendMessageToPeer(const char \*, const IMessage \*, const SendMessageOptions \&) instead. -2. The getServerReceivedTs method of the IMessage object supports both peer-to-peer and channel messages. -3. Timeout for sending a peer-to-peer message is 10 seconds from this release, compared to 5 seconds in previous versions. See PEER_MESSAGE_ERR_SENT_TIMEOUT. -4. Puts a limit on the frequency of join the same channel: Two times every five seconds. - -**New Features** - - -#### 1. Gets the member count of specified channel(s). - -You can now get the member count of specified channel(s) without the need to join, by calling the getChannelMemberCount method. You can get the member counts of a maximum of 32 channels in one method call. - - -#### 2. Automatically returns the latest numer of members in the current channel - -If you are already in a channel, you do not have to call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members onMemberCountUpdated the latest channel member count when the number of channel members changes. Note that: - -- When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. -- When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - - - -> Please treat this callback and the onGetMembers callback separately: -> - The former is an automatic callback. It returns the current numer of channel members; -> - The latter is triggered by the getMembers method. It returns a member list of the current channel. If the number of channel members exceeds 512, the SDK only returns a list of 512 randomly-selected channel members. - - -#### 3. Channel attribute operations - -Supports setting or getting the attribute(s) of a specified channel. You can use this feature to create group anouncement. - -Each channel attribute comes as a key-value pair. See IRtmChannelAttribute for more information. Where: - -- The key of each channel attribute must be visible characters and not exceed 8 KB. -- Each channel attribute must not exceed 8 KB in length. -- The overall size of the attributes of a channel must not exceed 32 KB. -- The number of attributes of a channel must not exceed 32. - -Specific features: - -- Sets the attributes of a specified channel with new ones. -- Adds or updates the attribute(s) of a specified channel. -- Deletes the attributes of a specified channel by attribute keys. -- Clears all attributes of a specified channel. -- Gets all attributes of a specified channel. -- Gets the attributes of a specified channel by attribute keys. - -When updating attributes of a channel, you can use the enableNotificationToChannelMembers flag to decide whether or not to notify all members of the channel about this attribute change. - -> The SDK caches the channel attributes. If multiple users have the privilege to update the channel attributes, then we recommend calling the getChannelAttributes to update the cache before updating the channel attributes. - -**Improvements** - -#### Resends peer-to-peer messages - -This release improves the resending mechanism of peer-to-peer messages, and extends the timeout for sending a peer-to-peer message from five to 10 seconds, greatly improving the success rate of peer-to-peer message sending under weak network conditions. - -#### Caches channel messages - -The Agora system will resend a maximum of 32 channel messages of up to 30 seconds to channel members, when they manage to reconnect to the system from poor network conditions. This greatly improves the overall arrival rate of channel messages under weak network conditions. - - -**API Changes** - -#### Added Methods - -- createChannelAttribute: Creates and returns an IRtmChannelAttribute instance. -- setChannelAttributes: Substitutes the attributes of a specified channel with new ones. -- addOrUpdaeChannelAttributes: Adds or updates the attribute(s) of a specified channel. -- deleteChannelAttributesByKeys: Deletes the attributes of a specified channel by attribute keys. -- clearChannelAttributes: Clears all attributes of a specified channel. -- getChannelAttributes: Gets all attributes of a specified channel. -- getChannelAttributesByKeys: Gets the attributes of a specified channel by attribute keys. -- getChannelMemberCount: Gets the member count of specified channel(s). - -#### Added Callbacks - -- onSetChannelAttributesResult: Returns the result of the setChannelAttributes method call. -- onAddOrUpdateChannelAttributesResult: Returns the result of the addOrUpdaeChannelAttributes method call. -- onDeleteChannelAttributesResult: Returns the result of the deleteChannelAttributesByKeys method call. -- onClearChannelAttributesResult: Returns the result of the clearChannelAttributes method call. -- onGetChannelAttributesResult: Returns the result of the getChannelAttributes or getChannelAttributesByKeys method call. -- onAttributesUpdated: Returns all attributes of the channel when the channel attributes are updated. -- onGetChannelMemberCountResult: Returns the result of the getChannelMemberCount method call. -- onMemberCountUpdated: Occurs when the number of the channel members changes, and returns the new number. - -#### Added Error Codes - -- GET_CHANNEL_MEMBER_COUNT_ERR_CODE: Error codes related to retrieving the channel member count of specified channel(s). -- JOIN_CHANNEL_ERR_JOIN_SAME_CHANNEL_TOO_OFTEN: The frequency of joining the same channel exceeds two times every five seconds. - -#### Deprecated Methods - -- sendMessageToPeer: Replaced by the sendMessageToPeer method. - -#### Deprecated Error Codes - -- ATTRIBUTE_OPERATION_ERR_NOT_READY: Replaced by ATTRIBUTE_OPERATION_ERR_USER_NOT_LOGGED_IN. - - - - -### v1.0.1 - -v1.0.1 was released on August 1st, 2019. - -**Issues Fixed** - -- When the connection to the Agora system is interrupted, the SDK does not return the `onConnectionStateChanged` callback. - -### v1.0.0 - -v1.0.0 was released on July 24th, 2019. - -**New Features** - -#### Interconnects with the legacy Agora Signaling SDK - -v1.0.0 implements the `ILocalCallinvitation::setChannelId` and `ILocalCallinvitation::getChannelId` methods. - -> - To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora does not join the channel of the specified channel ID. -> - If your App does not involve the legacy Agora Signaling SDK, we recommend using the `ILocalCallInvitation::setContent` method or the `IRemoteCallInvitation::setResponse` method to set customized contents. - -#### Specifies the default path to the SDK log file - -Supports changing the default path to the SDK log file using the `setLogFile` method. To avoid creating an incomplete log file, we recommend calling this method once you have created and initialized an `IRtmService` instance. - - - -#### Sets the output log level of the SDK - -Supports setting the output log level of the SDK using the `setLogFilter` method. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. See also LOG_FILTER_TYPE. - -> You can call this method once you have created and initializd an `IRtmService` instance. You do not have to call this method after calling the `login` method. - -#### Sets the log file size in KB - -Supports setting the log file size using the `setLogFileSize` method. The log file has a default size of 512 KB. File size settings of less than 512 KB or greater than 10 MB will not take effect. - - -> You can call this method once you have created and initializd an `IRtmService` instance. You do not have to call this method after calling the `login` method. - -**Improvements** - -Adds error codes based on the following scenarios: - -- The Agora service is not initialized. -- The method call frequency exceeds the limit. -- The user does not call the `login` method or the method call of `login` does not succeed before calling any of the core APIs. - -**Issues Fixed** - -- One can log in the Agora system with a static App ID and an token, which is generated from a dynamic App ID. - - -**API Changes** - -- setLogFile: Specifies the default path to the SDK log file. -- setLogFilter: Sets the output log level of the SDK. -- setLogFileSize: Sets the log file size in KB. - - - -### v0.9.3 - -v0.9.3 was released on June 7th, 2019. - -**New Features** - -#### Sends an (offline) peer-to-peer message to a specified user (receiver) - -This version allows you to send a message to a specified user when he/she is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that for now we only cache 200 offline messages for up to seven days for each receiver. When the number of the cached messages reaches this limit, the newest message overrides the oldest one. - - -#### User attribute-related operations - -This version allows you to set or update a user's attributes. You can: - -- Substitutes the local user's attributes with new ones. -- Adds or updates the local user's attribute(s). -- Deletes the local user's attributes using attribute keys. -- Clears all attributes of the local user. -- Gets all attributes of a specified user. -- Gets the attributes of a specified user using attribute keys. - -> - Only after you successfully loggin in the Agora system can you execute user attribute-related operations. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_NOT_READY` error code. -> - The attributes you set will be clears when you log out of the system. -> - You can only set a maximum of 16 KB attributes in a single method call. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_SIZE_OVERFLOW` error code. - -**Improvements** - -- Supports creating an channel before logging in the Agora system. -- Supports creating multiple channels. But a user can only join a maximum of 20 channels at the same time. When the number of the joined channels exceeds 20, the SDK triggers the `JOIN_CHANNEL_ERR_FAILURE` error code. - -**Issues Fixed** - -- Occasional system crashes. -- A user who has logged out of the Agora system appears online to the other users until 30 seconds later. - -### v0.9.2 - -v0.9.2 was released on May 8th, 2019. - -**New Features** - -- Queries the Online Status of the Specified Users. -- Renews the Token. - -**Improvements** - -- Supports a `userId` that starts with a space. - - - - -### v0.9.1 - -v0.9.1 is released on April 4th, 2019. - -**New Features** - -This release adds the call invitation feature, allowing you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. - - -### v0.9.0 - -v0.9.0 is released on February 4th, 2019. - -Initial version. - -**Key features** - -- Sends or receives peer-to-peer messages. -- Joins or leaves a channel. -- Sends or receives channel messages. - - - - \ No newline at end of file diff --git a/shared/signaling/release-notes/index.mdx b/shared/signaling/release-notes/index.mdx index 1077dbc4f..e9edf22ec 100644 --- a/shared/signaling/release-notes/index.mdx +++ b/shared/signaling/release-notes/index.mdx @@ -1,15 +1,13 @@ -import Android from './android.mdx'; -import Ios from './ios.mdx'; -import Linux from './linux.mdx'; -import Macos from './macos.mdx'; -import Unity from './unity.mdx'; import Web from './web.mdx'; -import Windows from './windows.mdx'; - - - - - + +This release is for Web only. + + + + +This page contains information on the following releases: + - \ No newline at end of file + + diff --git a/shared/signaling/release-notes/ios.mdx b/shared/signaling/release-notes/ios.mdx deleted file mode 100644 index 32fa8c746..000000000 --- a/shared/signaling/release-notes/ios.mdx +++ /dev/null @@ -1,16 +0,0 @@ -import Text from './oc.mdx'; - - - -This page contains information on the following releases: - - -## Known issues and limitations - -#### Compatibility with iOS 15 - -As of v1.4.6, the SDK supports iOS 15. For the SDK versions v1.4.4 and v1.4.5, crashes occur on iOS 15. To fix this issue, upgrade the SDK to v1.4.6 or later. - - - - \ No newline at end of file diff --git a/shared/signaling/release-notes/java.mdx b/shared/signaling/release-notes/java.mdx deleted file mode 100644 index 8ff6242d2..000000000 --- a/shared/signaling/release-notes/java.mdx +++ /dev/null @@ -1,617 +0,0 @@ - -## v1.5.1 - -v1.5.1 was released on September 1, 2022 and improved the stability of the SDK. - - -### v1.5.0 - -v1.5.0 was released on July 27, 2022. - -#### Sunset features -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - - -#### API changes - -The following methods are deprecated - -- createFileMessageByMediaId -- createFileMessageByUploading -- createImageMessageByMediaId -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- downloadMediaToFile -- downloadMediaToMemory -- onFileMessageReceived -- onFileMessageReceivedFromPeer -- onImageMessageReceived -- onImageMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress -- enableOfflineMessaging -- enableHistoricalMessaging - - -### v1.4.10 -v1.4.10 was released on March 01, 2022. - -#### Issues fixed - -Fixed some rich media related crashes. - -### v1.4.9 -v1.4.9 was released on November 26, 2021. - -#### Improvements - -Improved the login success rate and connection stability under the IPv4/IPv6 dual-stack network. - -### v1.4.7 -v1.4.7 was released on July 19, 2021. - -Improved the success rate of logins and message delivery for the in poor network conditions. - -### v1.4.6 - -v1.4.6 was released on June 21, 2021. - -Fixed some issues that may cause crashes to improve stability. - -### v1.4.5 - -v1.4.5 was released on April 30, 2021. - -#### Improvements - -Fixed some issues that may cause crashes to improve stability. - -### v1.4.4 - -v1.4.4 was released on April 20, 2021. - -#### Improvements - -Improved the success rate of logins and message delivery for the in poor network conditions. - -#### Issues fixed - -Fixed some issues that might cause the system to crash. - -### v1.4.3 - -v1.4.3 was released on February 10, 2021. - -#### Issues fixed - -This release fixed the following issues: - -- Crash issues caused by occasional multi-thread access conflict. -- High timeout rate for login operations. - -### v1.4.2 - -v1.4.2 was released on November 23, 2020. - -**Compatibility changes** - -- For CentOS, v1.4.2 does not support CentOS 7 or earlier. If your CentOS is 7 or earlier, Agora recommends that you use v1.4.1. -- In `setLogFileSize`, the default log file size increases from 10 MB to 100 MB. - -**Improvements** - -Improved the performance of login and messaging operations. - -**Bug fixes** - -Fixed the issue that `java.lang.UnsatisfiedLinkError: no agora-rtm-sdk-jni in java.library.path` occurred when integrating the v1.4.0 and the v1.4.1 SDK. - -### v1.4.1 - -v1.4.1 was released on September 30, 2020. - -**Improvements** - -Improved the log file. - - -### v1.4.0 - -v1.4.0 was released on September 1, 2020. - -**Compatibility changes** - -- You need to add new ports to the firewall whitelist. See [Firewall Requirements](../reference/firewall). - - New TCP ports: 8443, 9136, 9137, 9141. New UDP port: 8443. Reason: Support real-time transport encryption. - - New UDP ports: 8130, 9120, 9121. Reason: Support UDP path to improve the SDK's performance in sub-optimal network conditions. - - New UDP port: 9700. Reason: Support data reporting. -- In `setLogFileSize`, the default log file size increases from 512 KB to 10 MB. The maximum log file size increases from 10 MB to 1 GB. - -**New features** - -- Geofencing. You can call `setRtmServiceContext` to set the region of the Agora . The can only connect to Agora servers within the specified region. -- Transport Layer Security (TLS) encryption. - -**Improvements** - -- Improved the success rate of login and message delivery of the in poor network conditions. -- The call frequency limit has increased for the following operations. See [Limitations](../reference/limitations). - -| Operation | Call frequency limit change | -| :---------------------------------------- | :----------------------------------------------------------- | -| Send peer-to-peer or channel messages | Increased from 300 calls every three seconds to 1,500 calls every three seconds | -| Query user online status | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Add, delete, or update user attributes | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Query user attributes | Increased from 80 calls every five seconds to 400 calls every five seconds | -| Add, delete, or update channel attributes | Increased from 20 calls every five seconds to 100 calls every five seconds | -| Query channel attributes | Increased from 80 calls every five seconds to 400 calls every five seconds | - -- Optimized the reconnection mechanism. - -**API changes** - -#### New methods - - - -### v1.3.0 - -v1.3.0 was released on June 12. - -**Compatibility changes** - -- You need to add a new TCP port, 9140, to the firewall whitelist. The port is for sending and receiving image or file messages. See [Firewall Requirements](../reference/firewall). -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. - -**New features** - -#### 1. Send and receive file messages or image messages - -You can call `createFileMessageByUploading` or `createImageMessageByUploading` to upload non-empty files or image files no greater than 30 MB. Each uploaded file or image stays in the Agora server for seven days. The SDK returns a media ID as the unique indentifier of the file or image file. You can use the `RtmFileMessage` class or the `RtmImageMessage` class to save the media ID. The `RtmFileMessage` class and the `RtmImageMessage` class inherit from the `RtmMessage` class, so you can send and receive file or image messages via peer-to-peer or channel message methods. You can call `downloadMediaToMemory` or `downloadMediaToFile` to download the received file or image file. - -#### 2. Manage upload or download tasks - -You can call `cancelMediaUpload` or `cancelMediaDownload` to cancel an upload or download task. You also can use the `onMediaUploadingProgress` callback or the `onMediaDownloadingProgress` callback to return upload or download progress. - -**Improvements** - -The call limits of the following operations have increased. See [Limitations](../reference/limitations). - -| Operation | Call limit increase | -| :---------------------------------------- | :----------------------------------------------------------- | -| Send peer-to-peer or channel messages | From 180 calls every three seconds to 300 calls every three seconds | -| Query user online status | From 10 calls every five seconds to 20 calls every five seconds | -| Add, delete, or update user attributes | From 10 calls every five seconds to 20 calls every five seconds | -| Query user attributes | From 40 calls every five seconds to 80 calls every five seconds | -| Add, delete, or update channel attributes | From 10 calls every five seconds to 20 calls every five seconds | -| Query channel attributes | From 10 calls every five seconds to 80 calls every five seconds | - - -**Fixed issues** - -- Login failure caused by the SDK's incorrect identification of user's network type. -- Other problems that may cause the system to crash. - -**API changes** - -#### New methods - -- createFileMessageByMediaId -- createImageMessageByMediaId -- createFileMessageByUploading -- createImageMessageByUploading -- downloadMediaToMemory -- downloadMediaToFile -- cancelMediaUpload -- cancelMediaDownload - -#### New callbacks - -- onImageMessageReceived -- onFileMessageReceived -- onImageMessageReceivedFromPeer -- onFileMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress - - -#### Deprecated methods - -sendMessage (RtmMessage message, ResultCallback\ resultCallback) is deprecated. Use sendMessage (RtmMessage message, SendMessageOptions options, ResultCallback\ resultCallback) instead. - -### v1.2.2 - -v1.2.2 was released on December 13, 2019. - - - -**Issues Fixed** - -Occasionally fails to receive any callback after a channel attribute operation. - -### v1.2.1 - -v1.2.1 was released on November 29, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - - -- The SDK fails to reconnect to the Agora system if the user disables VPN. -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `onMemberJoined` twice. - -### v1.2.0 - -v1.2.0 was released on November 6, 2019. - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the onPeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - - If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - -**Issues Fixed** - - - The system returns `rtm native not ready`, if one creates multiple channels with the same `channelId` and then calls `join` or `leave`. - -### v1.1.0 - -v1.1.0 was released on October 14, 2019. It adds the following features: - -- [Gets the member count of specified channel(s).](#getcount) -- [Automatically returns the latest numer of members in the current channel](#oncount) -- [Channel attribute operations](#channelattributes) - - - -**Compatibility Changes** - -1. Deprecates the sendMessageToPeer method, and uses sendMessageToPeer(const char \*, const IMessage \*, const SendMessageOptions \&) instead. -2. The getServerReceivedTs method of the RtmMessage object supports both peer-to-peer and channel messages. -3. Timeout for sending a peer-to-peer message is 10 seconds from this release, compared to 5 seconds in previous versions. See PEER_MESSAGE_ERR_TIMEOUT. -4. Puts a limit on the frequency of join the same channel: Two times every five seconds. - -**New Features** - - -#### 1. Gets the member count of specified channel(s). - -You can now get the member count of specified channel(s) without the need to join, by calling the getChannelMemberCount method. You can get the member counts of a maximum of 32 channels in one method call. - - -#### 2. Automatically returns the latest numer of members in the current channel - -If you are already in a channel, you do not have to call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members onMemberCountUpdated the latest channel member count when the number of channel members changes. Note that: - -- When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. -- When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - -> Please treat this callback and the getMembers method separately: -> - The former is an active callback. It returns the current numer of channel members; -> - The latter relies on the onSuccess callback to return a member list of the current channel. If the number of channel members exceeds 512, the SDK only returns a list of 512 randomly-selected channel members. - - -#### 3. Channel attribute operations - -Supports setting or getting the attribute(s) of a specified channel. You can use this feature to create group anouncement. - -Each channel attribute comes as a key-value pair. See RtmChannelAttribute for more information. Where: - -- The key of each channel attribute must be visible characters and not exceed 8 KB. -- Each channel attribute must not exceed 8 KB in length. -- The overall size of the attributes of a channel must not exceed 32 KB. -- The number of attributes of a channel must not exceed 32. - -Specific features: - -- Sets the attributes of a specified channel with new ones. -- Adds or updates the attribute(s) of a specified channel. -- Deletes the attributes of a specified channel by attribute keys. -- Clears all attributes of a specified channel. -- Gets all attributes of a specified channel. -- Gets the attributes of a specified channel by attribute keys. - -When updating attributes of a channel, you can use the setEnableNotificationToChannelMembers flag to decide whether or not to notify all members of the channel about this attribute change. - -> The SDK caches the channel attributes. If multiple users have the privilege to update the channel attributes, then we recommend calling the getChannelAttributes to update the cache before updating the channel attributes. - -**Improvements** - -#### Resends peer-to-peer messages - -This release improves the resending mechanism of peer-to-peer messages, and extends the timeout for sending a peer-to-peer message from five to 10 seconds, greatly improving the success rate of peer-to-peer message sending under weak network conditions. - -#### Caches channel messages - -The Agora system will resend a maximum of 32 channel messages of up to 30 seconds to channel members, when they manage to reconnect to the system from poor network conditions. This greatly improves the overall arrival rate of channel messages under weak network conditions. - - -**API Changes** - -#### Added Methods - -- setChannelAttributes: Sets the attributes of a specified channel with new ones. -- addOrUpdaeChannelAttributes: Adds or updates the attribute(s) of a specified channel. -- deleteChannelAttributesByKeys: Deletes the attributes of a specified channel by attribute keys. -- clearChannelAttributes: Clears all attributes of a specified channel. -- getChannelAttributes: Gets all attributes of a specified channel. -- getChannelAttributesByKeys: Gets the attributes of a specified channel by attribute keys. -- getChannelMemberCount: Gets the member count of specified channel(s). - -#### Added Callbacks - -- onAttributesUpdated: Returns all attributes of the channel when the channel attributes are updated. -- onMemberCountUpdated: Occurs when the number of the channel members changes, and returns the new number. - -#### Added Error Codes - -- GetChannelMemberCountErrCode: Error codes related to retrieving the channel member count of specified channel(s). -- JOIN_CHANNEL_ERR_JOIN_SAME_CHANNEL_TOO_OFTEN: The frequency of joining the same channel exceeds two times every five seconds. - -#### Deprecated Methods - -- sendMessageToPeer: Replaced by the sendMessageToPeer(const char \*, const IMessage \*, const SendMessageOptions \&) method. - -#### Deprecated Error Codes - -- ATTRIBUTE_OPERATION_ERR_NOT_READY: Replaced by ATTRIBUTE_OPERATION_ERR_USER_NOT_LOGGED_IN. - -### v1.0.1 - -v1.0.1 was released on August 1st, 2019. - -**Issues Fixed** - -- When the connection to the Agora system is interrupted, the SDK does not return the `onConnectionStateChanged` callback. - -### v1.0.0 - -v1.0.0 was released on July 24th, 2019. - -**New Features** - -#### Interconnects with the legacy Agora Signaling SDK - -v1.0.0 implements the `LocalInvitation.setChannelId` and `LocalInvitation.getChannelId` methods. - -> - To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora does not join the channel of the specified channel ID. -> - If your App does not involve the legacy Agora Signaling SDK, we recommend using the `LocalInvitation.setContent` method or the `RemoteInvitation.setResponse` method to set customized contents. - -#### Specifies the default path to the SDK log file - -Supports changing the default path to the SDK log file using the `setLogFile` method. To avoid creating an incomplete log file, we recommend calling this method once you have created and initialized an `RtmClient` instance. - - - -#### Sets the output log level of the SDK - -Supports setting the output log level of the SDK using the `setLogFilter` method. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. - -> You can call this method once you have created and initializd an `RtmClient` instance. You do not have to call this method after calling the `login` method. - -#### Sets the log file size in KB - -Supports setting the log file size using the `setLogFileSize` method. The log file has a default size of 512 KB. File size settings of less than 512 KB or greater than 10 MB will not take effect. - - -> You can call this method once you have created and initializd an `RtmClient` instance. You do not have to call this method after calling the `login` method. - -**Improvements** - -Adds error codes based on the following scenarios: - -- The Agora service is not initialized. -- The method call frequency exceeds the limit. -- The user does not call the `login` method or the method call of `login` does not succeed before calling any of the core APIs. - -**Issues Fixed** - -- One can log in the Agora system with a static App ID and an token, which is generated from a dynamic App ID. - - -**API Changes** - -- setLogFile: Specifies the default path to the SDK log file. -- setLogFilter: Sets the output log level of the SDK. -- setLogFileSize: Sets the log file size in KB. -- getSdkVersion: Gets the SDK version. - - - - -### v0.9.3 - -v0.9.3 was released on June 7th, 2019. - -**New Features** - -#### Sends an (offline) peer-to-peer message to a specified user (receiver) - -This version allows you to send a message to a specified user when he/she is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that for now we only cache 200 offline messages for up to seven days for each receiver. When the number of the cached messages reaches this limit, the newest message overrides the oldest one. - - -#### User attribute-related operations - -This version allows you to set or update a user's attributes. You can: - -- Substitutes the local user's attributes with new ones. -- Adds or updates the local user's attribute(s). -- Deletes the local user's attributes using attribute keys. -- Clears all attributes of the local user. -- Gets all attributes of a specified user. -- Gets the attributes of a specified user using attribute keys. - -> - Only after you successfully loggin in the Agora system can you execute user attribute-related operations. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_NOT_READY` error code. -> - The attributes you set will be clears when you log out of . -> - You can only set a maximum of 16 KB attributes in a single method call. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_SIZE_OVERFLOW` error code. - -**Improvements** - -- Supports creating an channel before logging in the Agora system. -- Supports creating multiple channels. But a user can only join a maximum of 20 channels at the same time. When the number of the joined channels exceeds 20, the SDK triggers the `JOIN_CHANNEL_ERR_FAILURE` error code. - -**Issues Fixed** - -- Occasional system crashes. -- A user who has logged out of the Agora system appears online to the other users until 30 seconds later. - -### v0.9.2 - -v0.9.2 was released on May 5th, 2019. - -**New Features** - -#### Queries the Online Status of the Specified Users - -This release introduces a new concept: online and offline. - -- Online: The user has logged in the Agora system. -- Offline: The user has logged out of the Agora system. - -This release adds the function of querying the online status of the specified users. After logging in the Agora system, you can get the online status of a maximum of 256 specified users. See queryPeersOnlineStatus. - -> - The sequence of the returned user IDs is identical to the input sequence. -> - The call frequency of this method is 10 queries every five seconds. See [Limitations](../reference/limitations). - -#### Renews the Token - -In the production environment, you need to use a token to log in the Agora system. Each token expires 24 hours after it is created. This release allows you to renew a token. - -- If you are logging in the Agora system and if your token has expired, the SDK returns the LOGIN_ERR_TOKEN_EXPIRED error code. -- if you are logged in the Agora system, you will not be kicked out immediately when your token expires. But you need to renew your token the next time you log in the Agora system. Therefore, we still recommend that you renew your token when receiving the onTokenExpired callback. - -> - The renewToken method must be called before creating an RtmClient. -> - The call freqency of the `RenewToken` method is two queries every second. See [Limitations](../reference/limitations). - -**Improvements** - -- Supports a `userId` that starts with a space. - -**API Changes** - -#### Queries the Online Status of the Specified Users - -##### Adds - -- Method: queryPeersOnlineStatus -- Error Code: [QueryPeersOnlineStatusError - -#### Renews the Token - -##### Adds - -- Method: renewToken -- Callback: onTokenExpired -- Error Codes: - - RenewTokenError - -#### Call Invitation - -Adds the following error code for when a user sends a call invitation without logging in the Agora system. - -- LOCAL_INVITATION_ERR_NOT_LOGGEDIN - -### v0.9.1 - -v0.9.1 was released on April 4th, 2019. - -**New Features** - -This release adds the call invitation feature, allowing you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. - -**Improvements** - -- Optimizes the object relations to facilitate understanding. -- Renames some interfaces to conform to Java naming conventions. -- Removes `ChannelMessageState` and `PeerMessageState` to simplify the process of sending a channel or peer-to-peer message. Uses `ChannelMessageError` and `PeerMessageError` instead. -- Removes `IStateListener` for listening to message states. Uses the generic `ResultCallback` instead. - -**API Changes** - -#### Adds - -- LocalInvitation.setContent(): allows the caller to set the content of an outgoing call invitation. -- LocalInvitation.getContent(): allows the caller to retrieve the content of an outgoing call invitation. -- LocalInvitation.getResponse(): allows the caller to retrieve the response set by the callee. -- LocalInvitation.getState(): allows the caller to retrieve the state of an outgoing call invitation. -- RemoteInvitation.getCallerId(): allows the callee to retrieve the user ID of the caller. -- RemoteInvitation.getContent(): allows the callee to retrieve the content set by the caller. -- RemoteInvitation.setResponse(): allows the callee to set the response to the caller. -- RemoteInvitation.getResponse(): allows the callee to retrieve the response to the caller. -- RemoteInvitation.getState(): allows the callee to retrieve the state of the incoming call invitation -- RtmCallEventListener.onLocalInvitationReceivedByPeer(): occurs when the callee receives the call invitation. -- RtmCallEventListener.onLocalInvitationAccepted(): occurs when the callee accepts the call invitation. -- RtmCallEventListener.onLocalInvitationRefused(): occurs when the callee declines the call invitation. -- RtmCallEventListener.onLocalInvitationCanceled(): occurs when the caller cancels the call invitation. -- RtmCallEventListener.onLocalInvitationFailure(): occurs when the outgoing call invitation fails. -- RtmCallEventListener.onRemoteInvitationReceived(): occurs when the callee receives a call invitation. -- RtmCallEventListener.onRemoteInvitationAccepted(): occurs when the callee accepts a call invitation. -- RtmCallEventListener.onRemoteInvitationRefused(): occurs when the callee declines a call invitation. -- RtmCallEventListener.onRemoteInvitationCanceled(): occurs when the caller cancels the call invitation. -- RtmCallEventListener.onRemoteInvitationFailure(): occurs when the incoming call invitation fails. -- RtmCallManager.setEventListener(): sets the event listener to the `RtmCallManager` instance. -- RtmCallManager.createLocalInvitation(): creates a call invitation. -- RtmCallManager.sendLocalInvitation(): sends a call invitation to a specified user. -- RtmCallManager.acceptRemoteInvitation(): accepts an incoming call invitation. -- RtmCallManager.refuseRemoteInvitation(): declines an incoming call invitation. -- RtmCallManager.cancelLocalInvitation(): allows the caller to cancel an outgoing call invitation. -- RtmStatusCode#LocalInvitationState states of an outgoing call invitation. -- RtmStatusCode#RemoteInvitationState: states of an incoming call invitation. -- RtmStatusCode#LocalInvitationError: error codes of an outgoing call invitation. -- RtmStatusCode#RemoteInvitationError: error codes of an incoming call invitation. -- RtmStatusCode#InvitationApiCallError: error codes of the invitation-specific API calls. -- ConnectionChangeReason#CONNECTION_CHANGE_REASON_REMOTE_LOGIN: another instance has logged in the Agora system with the same user ID. - -#### Renames - -- The `RtmClient.destroy()` method, which releases all resources used by the `RtmClient` instance, to: RtmClient.release(). -- The `IResultCallback` class to: ResultCallback - -#### Deletes - -- Deletes `PEER_MESSAGE_RECEIVED_BY_SERVER` from PeerMessageError, uses `PEER_MESSAGE_ERR_OK` instead. -- Deletes `CHANNEL_MESSAGE_RECEIVED_BY_SERVER` from ChannelMessageError, uses `CHANNEL_MESSAGE_OK` instead. -- Deletes the `PeerMessageState` interface, uses PeerMessageError instead. -- Deletes the `ChannelMessageState` interface, uses ChannelMessageError instead. -- Deletes the `IStateListener` class for listening to message states, uses the ResultCallback class instead for listening to the peer or channel message results. - - Success: the SDK returns the ResultCallback.onSuccess() callback. - - Failure: the SDK returns the ResultCallback.onFailure() callback with the corresponding error codes. - -### v0.9.0 - -v0.9.0 was released on February 4th, 2019. - -Initial version. - -Key features: - -- Sends or receives peer-to-peer messages. -- Joins or leaves a channel. -- Sends or receives channel messages. - - - - - diff --git a/shared/signaling/release-notes/linux.mdx b/shared/signaling/release-notes/linux.mdx deleted file mode 100644 index 6824f0a06..000000000 --- a/shared/signaling/release-notes/linux.mdx +++ /dev/null @@ -1,9 +0,0 @@ -import CPP from './cpp.mdx'; -import JAVA from './java.mdx'; - -This page contains information on the following releases: - - - - - diff --git a/shared/signaling/release-notes/macos.mdx b/shared/signaling/release-notes/macos.mdx deleted file mode 100644 index 826911551..000000000 --- a/shared/signaling/release-notes/macos.mdx +++ /dev/null @@ -1,15 +0,0 @@ -import Text from './oc.mdx'; - - - -This page contains information on the following releases: - -## Known issues and limitations - -#### Compatibility with macOS Monterey 12 - -As of v1.4.6, the SDK supports macOS Monterey 12. For the SDK versions v1.4.4 and v1.4.5, crashes occur on macOS Monterey 12. To fix this issue, upgrade the SDK to v1.4.6 or later. - - - - \ No newline at end of file diff --git a/shared/signaling/release-notes/oc.mdx b/shared/signaling/release-notes/oc.mdx deleted file mode 100644 index 342a5a5a6..000000000 --- a/shared/signaling/release-notes/oc.mdx +++ /dev/null @@ -1,667 +0,0 @@ - - -## v1.5.1 - -v1.5.1 was released on September 1, 2022 and improved the stability of the SDK. - -## v1.5.0 - -v1.5.0 was released on July 27, 2022. - -#### Sunset features -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - -#### API changes - -The following methods are deprecated: - -- createFileMessageByMediaId -- createFileMessageByUploading -- createImageMessageByMediaId -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- downloadMedia -- downloadMediaToMemory -- fileMessageReceived -- imageMessageReceived -- uploadingProgress -- downloadingProgress -- enableOfflineMessaging -- enableHistoricalMessaging - - -## v1.4.10 -v1.4.10 was released on March 01, 2022. - -#### Compatibility changes - -This release adds supports for running the iOS simulator on devices with M1 chips. - -#### Issues fixed - -Fixed some rich media related crashes. - - -## v1.4.9 - -v1.4.9 was released on November 19, 2021. - -#### Improvements - -Improved the login success rate and connection stability under the IPv4/IPv6 dual-stack network. - -#### Bug fixes - -This release fixed the following issues: - -- The internal class name conflicts when used together with the Agora , causing unexpected prompts when running the app. -- A crash occurred occasionally when exiting the app. - -## v1.4.8 - -v1.4.8 was released on July 23, 2021. - -This release update the SDK version in the Info.plist file to the latest version. - -## v1.4.7 -v1.4.7 was released on July 19, 2021. - -#### Improvement - -- Fixed the potential crashes caused by adding support for iOS 15, and improved the stability of the SDK. -- Improved the success rate of logins and message delivery for the in poor network conditions. - -## v1.4.6 -v1.4.6 was released on June 21, 2021. This release supports iOS 15. - -## v1.4.5 - -v1.4.5 was released on April 30, 2021. - -#### Compatibility changes - -As of v1.4.4, the SDK has been upgraded from a static library to a dynamic library, and the format of all dynamic libraries changes from framework to XCFramework. -If you are using a build tool that does not support the dynamic library in XCFramework format, Agora provides the following scripts to help you integrate: - -- Use the [change_to_all_arch.sh](https://web-cdn.agora.io/docs-files/1621391958917) script to convert the XCFramework to the universal framework. -- If you need to publish an iOS/macOS app on the App Store, use the [remove_simulator_arch.sh](https://web-cdn.agora.io/docs-files/1621392005121) script to remove the simulator before packaging the app. - -#### Improvements - -Fixed some issues that might cause crashes to improve stability. - -#### Fixed issues - -The iOS app integrated with the SDK v1.4.4 cannot be published on the App Store due to review issues. - -## v1.4.4 - -v1.4.4 was released on April 20, 2021. - -#### Compatibility changes - -This release replaces the static library with a dynamic library for the following reasons: - -- Improving overall security. -- Avoiding compatibility issues with other third-party libraries. -- Making it easier to upload the app to the App Store. - -To upgrade the Native SDK, you must re-integrate the dynamic library, **AgoraRtmKit.xcframework.** And there is no need to integrate dependent libraries. - -The format of all dynamic libraries changes from Framework to XCFramework. A dynamic library in XCFramework format supports running a project on both physical devices and simulators. - -#### Improvements - -Improved the success rate of logins and message delivery for the in poor network conditions. - -#### Issues Fixed - -This release fixed the following issues: - -- A memory leak issue with the SDK. -- Some issues that may cause the system to crash. - -## v1.4.3 - -v1.4.3 was released on February 10, 2021. - -#### Issues fixed - -This release fixed the following issues: - -- Naming conflict between the values in the `AgoraAreaCode` constant of the Agora and the `AgoraRtmAreaCode` constant of the Agora when using Swift. As of v1.4.3, Agora Objective-C SDK for iOS/macOS provides `AgoraRtmKit_swift.h`, which updates the constant values of `AgoraRtmAreaCode`, to avoid this naming conflict. -- Crash issues caused by OpenSSL upgrade in Agora v1.4.2. -- Crash issues caused by occasional multi-thread access conflict. -- High timeout rate for login operations. - -## v1.4.2 - -v1.4.2 was released on November 23, 2020. - -#### Improvements - -- Improved performance of login and messaging operations. -- Added the `AGORA_SDK_BOTH_RTM_AND_RTC` macro for the `AgoraRtmAreaCode` enum type. You can use the macro to resolve naming conflicts when using and together. - -## v1.4.1 - -v1.4.1 was released on September 30, 2020. - -#### Improvements - -Improved the log file. - -#### Bug fixes - -Fixed the pop up issue in iOS 14. - -## v1.4.0 - -v1.4.0 was released on September 1, 2020. - -#### Compatibility changes - -- You need to add new ports to the firewall whitelist. See [Firewall Requirements](../reference/firewall). - - New TCP ports: 8443, 9136, 9137, 9141. New UDP port: 8443. Reason: Support real-time transport encryption. - - New UDP ports: 8130, 9120, 9121. Reason: Support UDP path to improve the SDK's performance in sub-optimal network conditions. - - New UDP port: 9700. Reason: Support data reporting. -- In `setLogFileSize`, the default log file size increases from 512 KB to 10 MB. The maximum log file size increases from 10 MB to 1 GB. -- Before destroying an `AgoraRtmKit` instance, you must call `destroyChannelWithId` to destroy all existing `AgoraRtmChannel` instances. Otherwise, the SDK may crash. - -#### New features - -- Geofencing. You can call `setRtmServiceContext` to set the region of the Agora . The can only connect to Agora servers within the specified region. -- Transport Layer Security (TLS) encryption. - -#### Improvements - -- Improved the success rate of login and message delivery of the in poor network conditions. -- Optimized the reconnection mechanism. - -#### API changes - -**New methods** - -setRtmServiceContext - -## v1.3.0 - -v1.3.0 was released on May 8, 2020. - -**Compatibility changes** - -- You need to add a new TCP port, 9140, to the firewall whitelist. The port is for sending and receiving image or file messages. See [Firewall Requirements](../reference/firewall). -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. - -**New features** - -#### 1. Send and receive file messages - -v1.3.0 supports downloading non-empty files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each file you upload to the Agora server corresponds to a media ID. The file stays on the Agora server for seven days. You can use the media ID to download the file as long as it is is still on the Agora server. - -
    You can only download files using the download methods provided by the SDK.
    - -v1.3.0 adds the `AgoraRtmFileMessage` interface for saving and transferring a media ID. The `AgoraRtmFileMessage` interface inherits from the `AgoraRtmMessage` interface, so you can use existing peer-to-peer or channel messaging methods to transfer the `AgoraRtmFileMessage` instance. You can use the `AgoraRtmFileMessage` interface to complete the following tasks: - -- Set the filename and thumbnail of the uploaded file. -- Get the size of the uploaded file. - -
    The total size of the message content, the filename, and the thumbnail must not exceed 32 KB.
    - -#### 2. Send and receive image messages - -v1.3.0 supports downloading non-empty image files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each image file you upload to the Agora server corresponds to a media ID. The image file stays on the Agora server for seven days. You can use media ID to download the image file as long as the image file is still on the Agora server. - -
    You can only download images using the download methods provided by the SDK.
    - -v1.3.0 adds the `AgoraRtmImageMessage` interface for saving and transferring a media ID. The `AgoraRtmImageMessage` interface inherits from the `AgoraRtmMessage` interface, so you can use existing peer-to-peer or channel messaging methods to transfer the `AgoraRtmImageMessage` instance. You can use the `AgoraRtmImageMessage` interface to complete the following tasks: - -- Set the filename and thumbnail of the uploaded image. -- Get the size of the uploaded image. -- Get the SDK-calculated width and height of images in JPEG, JPG, BMP, or PNG format. -- Set the width or height of images. The width or height you set overwrite the width or height that the SDK calculates. - -
    The total size of the message content, the filename, and the thumbnail must not exceed 32 KB.
    - -#### 3. Report the progress of upload or download - -SDK returns the progress of an upload or download by callback every second during a task in progress. If the upload or download task pauses, the SDK ceases to return any further callback until the task continues. - -**Bug fixes** - -- Login failure caused by the SDK's incorrect identification of user's network type. -- Other problems that may cause the system to crash. - -**API changes** - -#### New methods - -- createFileMessageByUploading:withRequest:completion: -- createImageMessageByUploading:withRequest:completion: -- cancelMediaUpload:completion: -- cancelMediaDownload:completion: -- createFileMessageByMediaId: -- createImageMessageByMediaId: -- downloadMediaToMemory:withRequest:completion: -- downloadMedia:toFile:withRequest:completion: - -#### New callbacks - -- rtmKit:media:uploadingProgress: -- rtmKit:media:downloadingProgress: -- kAgoraRtmUploadFileMediaBloc -- AgoraRtmUploadImageMediaBlock -- AgoraRtmCancelMediaBlock -- AgoraRtmDownloadMediaToMemoryBlock -- AgoraRtmDownloadMediaToFileBlock -- rtmKit:fileMessageReceived:fromPeer: -- rtmKit:imageMessageReceived:fromPeer: -- channel:fileMessageReceived:fromMember: -- channel:imageMessageReceived:fromMember: - -#### Deprecated methods - -sendMessage:completion: is deprecated. Use sendMessage:sendMessageOptions:completion: instead. - -## v1.2.2 - -v1.2.2 was released on December 13, 2019. - - - -**Issues Fixed** - -Occasionally fails to receive any callback after a channel attribute operation. - -## v1.2.1 - -v1.2.1 was released on November 29, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - - -- The SDK fails to reconnect to the Agora system if the user disables VPN. -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `MemberJoined` twice. - -## v1.2.0 - -v1.2.0 was released on November 6, 2019. - -**Compatibility Changes** - -Deprecated the `isOnline` property of the `AgoraRtmPeerOnlineStatus`. Use `state` instead. - - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the PeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the PeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the PeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - - If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - -## v1.1.0 - -v1.1.0 is released on September 18, 2019. It adds the following features: - -- [Gets the member count of specified channel(s).](#getcount) -- [Automatically returns the latest numer of members in the current channel](#oncount) -- [Channel attribute operations](#channelattributes) - - - -**Compatibility Changes** - -1. Deprecates the sendMessage:toPeer:completion: method, and uses sendMessage:toPeer:sendMessageOptions:completion: instead -2. The serverReceivedTs property of the AgoraRtmMessage instance supports both peer-to-peer and channel messages. -3. Timeout for sending a peer-to-peer message is 10 seconds from this release, compared to 5 seconds in previous versions. See AgoraRtmSendPeerMessageErrorTimeout -4. Puts a limit on the frequency of joinWithCompletion the same channel: Two times every five seconds. - -**New Features** - - -#### 1. Gets the member count of specified channel(s). - -You can now get the member count of specified channel(s) without the need to join, by calling the getChannelMemberCount method. You can get the member counts of a maximum of 32 channels in one method call. - - -#### 2. Automatically returns the latest numer of members in the current channel - -If you are already in a channel, you do not have to call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members memberCount the latest channel member count when the number of channel members changes. Note that: - -- When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. -- When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - -> Please treat this callback and the AgoraRtmGetMembersBlock callback separately: -> - The former is an automatic callback. It returns the current numer of channel members; -> - The latter is triggered by the getMembersWithCompletion method. It returns a member list of the current channel. If the number of channel members exceeds 512, the SDK only returns a list of 512 randomly-selected channel members. - - -#### 3. Channel attribute operations - -Supports setting or getting the attribute(s) of a specified channel. You can use this feature to create group anouncement. - -Each channel attribute comes as a key-value pair. See AgoraRtmChannelAttribute. Where: - -- The key of each channel attribute must be visible characters and not exceed 8 KB. -- Each channel attribute must not exceed 8 KB in length. -- The overall size of the attributes of a channel must not exceed 32 KB. -- The number of attributes of a channel must not exceed 32. - -Specific features: - -- Sets the attributes of a specified channel with new ones. -- Adds or updates the attribute(s) of a specified channel. -- Deletes the attributes of a specified channel by attribute keys. -- Clears all attributes of a specified channel. -- Gets all attributes of a specified channel. -- Gets the attributes of a specified channel by attribute keys. - -When updating attributes of a channel, you can use the enableNotificationToChannelMembers flag to decide whether or not to notify all members of the channel about this attribute change. - -> The SDK caches the channel attributes. If multiple users have the privilege to update the channel attributes, then we recommend calling the getChannelAllAttributes to update the cache before updating the channel attributes. - -**Improvements** - -#### Resends peer-to-peer messages - -This release improves the resending mechanism of peer-to-peer messages, and extends the timeout for sending a peer-to-peer message from five to 10 seconds, greatly improving the success rate of peer-to-peer message sending under weak network conditions. - -#### Caches channel messages - -The Agora system will resend a maximum of 32 channel messages of up to 30 seconds to channel members, when they manage to reconnect to the system from poor network conditions. This greatly improves the overall arrival rate of channel messages under weak network conditions. - - -**API Changes** - -#### Added Methods - -- setChannelAttributes:Substitutes the attributes of a specified channel with new ones. -- addOrUpdaeChannelAttributes:Adds or updates the attribute(s) of a specified channel. -- deleteChannelAttributesByKeys:Deletes the attributes of a specified channel by attribute keys. -- clearChannelAttributes:Clears all attributes of a specified channel. -- getChannelAllAttributes: Gets all attributes of a specified channel. -- getChannelAttributesByKeys: Gets the attributes of a specified channel by attribute keys. -- getChannelMemberCount: Gets the member count of specified channel(s). - -#### Added Callbacks - -- attributesUpdate: Returns all attributes of the channel when the channel attributes are updated. -- memberCount: Occurs when the number of the channel members changes, and returns the new number. - -#### Added Error Codes - -- AgoraRtmChannelMemberCountErrorCode: Error codes related to retrieving the channel member count of specified channel(s). -- AgoraRtmJoinSameChannelErrorTooOften: The frequency of joining the same channel exceeds two times every five seconds. - -#### Deprecated Methods - -- sendMessage:toPeer:completion:: Replaced by the sendMessage:toPeer:sendMessageOptions:completion: method. - -#### Deprecated Error Codes - -- AgoraRtmAttributeOperationErrorNotReady: Replaced by AgoraRtmAttributeOperationErrorNotLoggedIn. - - - - - - -## v1.0.1 - -v1.0.1 is released on August 1st, 2019. - -#### Issues Fixed - -- When the connection to the Agora system is interrupted, the SDK does not return the `connectionStateChanged` callback. -- Occasional crashes on iOS. - -## v1.0.0 - -v1.0.0 is released on July 24th, 2019. - -#### New Features - -#### Interconnects with the legacy Agora Signaling SDK - -v1.0.0 implements the `channelId` property in the `AgoraRtmLocalInvitation` class. - -> - To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora does not join the channel of the specified channel ID. -> - If your App does not involve the legacy Agora Signaling SDK, we recommend using the `content` property of the `AgoraRtmLocalInvitation` class or the `response` property of the `AgoraRtmRemoteInvitation` class to set customized contents. - -#### Specifies the default path to the SDK log file - -Supports changing the default path to the SDK log file using the `setLogFile` method. To avoid creating an incomplete log file, we recommend calling this method once you have created and initialized an `AgoraRtmKit` instance. - - - -#### Sets the output log level of the SDK - -Supports setting the output log level of the SDK using the `setLogFilter` method. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING. See also AgoraRtmLogFilter. - -> You can call this method once you have created and initializd an `AgoraRtmKit` instance. You do not have to call this method after calling the `loginByToken` method. - -#### Sets the log file size in KB - -Supports setting the log file size using the `setLogFileSize` method. The log file has a default size of 512 KB. File size settings of less than 512 KB or greater than 10 MB will not take effect. - - -> You can call this method once you have created and initializd an `AgoraRtmKit` instance. You do not have to call this method after calling the `loginByToken` method. - -#### Improvements - -Adds error codes based on the following scenarios: - -- The Agora service is not initialized. -- The method call frequency exceeds the limit. -- The user does not call the `loginByToken` method or the method call of `loginByToken` does not succeed before calling any of the core APIs. - -#### Issues Fixed - -- Occasional crashes on iOS. -- One can log in the Agora system with a static App ID and an token, which is generated from a dynamic App ID. - - -#### API Changes - -- setLogFile: Specifies the default path to the SDK log file. -- setLogFilter: Sets the output log level of the SDK. -- setLogFileSize: Sets the log file size in KB. -- getSDKVersion: Gets the version of the Agora . - - - - -## v0.9.3 - -v0.9.3 is released on June 7th, 2019. - -#### New Features - -#### Sends an (offline) peer-to-peer message to a specified user (receiver) - -This version allows you to send a message to a specified user when he/she is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that for now we only cache 200 offline messages for up to seven days for each receiver. When the number of the cached messages reaches this limit, the newest message overrides the oldest one. - - -#### User attribute-related operations - -This version allows you to set or update a user's attributes. You can: - -- Substitutes the local user's attributes with new ones. -- Adds or updates the local user's attribute(s). -- Deletes the local user's attributes using attribute keys. -- Clears all attributes of the local user. -- Gets all attributes of a specified user. -- Gets the attributes of a specified user using attribute keys. - -> - Only after you successfully loggin in the Agora system can you execute user attribute-related operations. Otherwise, the SDK triggers the `AgoraRtmAttributeOperationErrorNotReady` error code. -> - The attributes you set will be clears when you log out of . -> - You can only set a maximum of 16 KB attributes in a single method call. Otherwise, the SDK triggers the `AgoraRtmAttributeOperationErrorSizeOverflow` error code. - -#### Improvements - -- Supports creating an channel before logging in the Agora system. -- Supports creating multiple channels. But a user can only join a maximum of 20 channels at the same time. When the number of the joined channels exceeds 20, the SDK triggers the `AgoraRtmJoinChannelErrorFailure` error code. - -#### Issues Fixed - -- Occasional system crashes. -- A user who has logged out of the Agora system appears online to the other users until 30 seconds later. - -## v0.9.2 - -v0.9.2 is released on May 5th, 2019. - -> This release does not support creating an RtmChannel instance before logging in the Agora system - -#### New Features - -#### Queries the Online Status of the Specified Users - -This release introduces a new concept: online and offline. - -- Online: The user has logged in the Agora system. -- Offline: The user has logged out of the Agora system. - -This release adds the function of querying the online status of the specified users. After logging in the Agora system, you can get the online status of a maximum of 256 specified users. See queryPeersOnlineStatus. - -> - The sequence of the returned user IDs is identical to the input sequence. -> - The call frequency of this method is 10 times every five seconds. See [Limitations](../reference/limitations). - - -#### Renews the Token - -In the production environment, you need to use a token to log in the Agora system. Each token expires 24 hours after it is created. This release allows you to [renew a token. - -- If you are logging in the Agora system and if your token has expired, the SDK returns the AgoraRtmLoginErrorTokenExpired error code. -- if you are logged in the Agora system, you will not be kicked out immediately when your token expires. But you need to renew your token the next time you log in the Agora system. Therefore, we still recommend that you renew your token when you receive the rtmKitTokenDidExpire: callback. - - -> - The renewToken method must be called before creating an RtmClient. -> - The call frequency of the renewToken method is two times every second. See [Limitations](../reference/limitations). - -#### Improvements - -- Supports a `userId` that starts with a space. - - -#### API Changes - -#### Queries the Online Status of the Specified User(s) - -##### Adds - -- Method: queryPeersOnlineStatus:completion: -- Error Code: QueryPeersOnlineStatusError - -#### Renews the Token - -##### Adds - -- Method: renewToken -- Callback: onTokenExpired -- Error Code: AgoraRtmRenewTokenErrorCode - -#### Call Invitation - -Adds the following error code for when a user sends a call invitation without logging in the Agora system. - -- AgoraRtmLocalInvitationErrorNotLoggedIn - -## v0.9.1 - -v0.9.1 is released on April 4th, 2019. - -#### New Features - -This release adds the call invitation feature, allowing you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. - -> This version does not come with the `setLogFile` or `setLogFilter` method. -> - For iOS platforms, all log information is kept at **/Library/Caches/agorartm.log** by default. -> - For macOS platforms, all log information is kept at **~/Library/Logs/agorartm.log** by default. - -#### Improvements - -- Optimizes the object relations to facilitate understanding. -- Simplifies the process of sending a channel or peer-to-peer message. - -#### API Changes - -#### Adds - -- initWithCalleeId: allows the caller to create an AgoraRtmLocalInvitation instance. -- AgoraRtmLocalInvitation: the caller's call invitation object. -- localInvitationReceivedByPeer: occurs when the callee receives the call invitation. -- localInvitationAccepted: occurs when the callee accepts the call invitation. -- localInvitationRefused: occurs when the callee declines the call invitation. -- localInvitationCanceled: occurs when the caller cancels the call invitation. -- localInvitationFailure: occurs when the life cycle of the outgoing call invitation ends in failure. -- remoteInvitationReceived: occurs when the callee receives a call invitation. -- remoteInvitationAccepted: occurs when the callee accepts a call invitation. -- remoteInvitationRefused: occurs when the callee declines a call invitation. -- remoteInvitationCanceled: occurs when the caller cancels the call invitation. -- remoteInvitationFailure: occurs when the life cyle of the incoming call invitation ends in failure. -- AgoraRtmCallDelegate: enables Agora call callback event notifications to your app. -- sendLocalInvitation: sends a call invitation to a specified user. -- acceptRemoteInvitation: accepts an incoming call invitation. -- refuseRemoteInvitation: declines an incoming call invitation. -- cancelLocalInvitation: allows the caller to cancel an outgoing call invitation. -- AgoraRtmLocalInvitationState: states of an outgoing call invitation. -- AgoraRtmRemoteInvitationState: states of an incoming call invitation. -- AgoraRtmLocalInvitationErrorCode: error codes of an outgoing call invitation. -- AgoraRtmRemoteInvitationErrorCode: error codes of an incoming call invitation. -- AgoraRtmInvitationApiCallErrorCode: error codes of the invitation-specific API calls. -- AgoraRtmConnectionChangeReasonRemoteLogin: another instance has logged in the Agora system with the same user ID. -- AgoraRtmSendPeerMessageErrorCode: error codes of sending a peer-to-peer message. -- AgoraRtmSendChannelMessageErrorCode: error codes of sending a channel message. -- AgoraRtmConnectionChangeReasonRemoteLogin: error codes of the connection state change. - - - -#### Deletes - -- Deletes the `AgoraRtmSendMessageErrorCode` constants, uses AgoraRtmSendPeerMessageErrorCode and AgoraRtmSendChannelMessageErrorCode instead. - -#### Modifies - -- Sets `channelDelegate` as a property so that developers can freely update it. -- Removes rtmKit from the callbacks under `AgoraRtmChannelDelegate`. -- Changes the parameter of the setParameters method, which configures the SDK with JSON options. -- Deletes AgoraRtmSendChannelMessageStateReceivedByServer from AgoraRtmSendChannelMessageErrorCode. -- Deletes the AgoraRtmSendPeerMessageState interface, uses AgoraRtmSendPeerMessageErrorCode instead. -- Deletes the AgoraRtmSendChannelMessageState interface, uses AgoraRtmSendChannelMessageErrorCode instead. - -## v0.9.0 - -v0.9.0 is released on February 4th, 2019. - -Initial version. - -Key features: - -- Sends or receives peer-to-peer messages. -- Joins or leaves a channel. -- Sends or receives channel messages. - - diff --git a/shared/signaling/release-notes/unity.mdx b/shared/signaling/release-notes/unity.mdx deleted file mode 100644 index f50565e07..000000000 --- a/shared/signaling/release-notes/unity.mdx +++ /dev/null @@ -1,21 +0,0 @@ - - -This page contains information on the following releases: - -## v1.4.10 -v1.4.10 was released on August 17, 2022. - -Fixed some issues that may cause crashes when working in tandem with . - -## v1.4.8 -v1.4.8 was released on August 24, 2021. - -This release is the first release of Unity SDK. You can refer to the following documents to integrate the SDK and implement sending and receiving functions: - -- [Peer-to-peer or Channel Messaging](../get-started/get-started-sdk) - -- API Reference - -Agora provides an open-source sample project [Agora-Unity--SDK](https://github.com/AgoraIO-Community/Agora-Unity--SDK/) , you can download and experience it. - - \ No newline at end of file diff --git a/shared/signaling/release-notes/web.mdx b/shared/signaling/release-notes/web.mdx index 94a2338da..9f70fcc2b 100644 --- a/shared/signaling/release-notes/web.mdx +++ b/shared/signaling/release-notes/web.mdx @@ -1,543 +1,104 @@ -## v1.5.1 +### v2.1.5 -v1.5.1 was released on September 1, 2022. +v2.1.5 was released on December 22, 2023 -In previous versions, when users fail to send a channel message because they either could not log in to Signaling, or not join a channel, the `CHANNEL_MESSAGE_ERR_NOT_IN_CHANNEL = 5` error code was returned. +This release makes changes to the following APIs. Modify your implementation code after upgrading the SDK: -As of this version, the circumstances that trigger this error are further refined. Users can now easily identify and troubleshoot. When a failure of sending a channel message occurs: - -* The `CHANNEL_MESSAGE_ERR_USER_NOT_LOGGED_IN = 102` error code is returned if users do not log in to the . -* The `CHANNEL_MESSAGE_ERR_NOT_IN_CHANNEL = 5` error code is returned if users log in to the SDK whereas do not join the channel. - -## v1.5.0 - -v1.5.0 was released on July 27, 2022. - -#### Sunset features - -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - -#### New features - -**Cloud Proxy** - -Enable Cloud Proxy with the new optional `enableCloudProxy` parameter in `RtmConfig`. See API reference. - -#### Bug fixes - -This release fixed the unit of timeout in output logs from milliseconds (ms) to seconds (s). - -#### API changes - -**Added** - -- `enableCloudProxy` - -**Deprecated** - -- `createMediaMessageByUploading` -- `downloadMedia` -- `IMAGE and FILE in messageType` -- `RtmImageMessage` -- `RtmFileMessage` -- `MediaTransferHandler` -- `MediaOperationProgress` -- `UploadMediaError` -- `DownloadMediaError` -- `SendMessageOptions` - -## v1.4.4 -v1.4.4 was released on December 24, 2021. - -Fixed an issue where the Agora Web SDK could reconnect to (with the connection status RECONNECTING) when the browser or tab was running in the background, if the Web SDK was used in Chrome 88 or higher. - -## v1.4.3 -v1.4.3 was released on May 27, 2021. - -#### Compatibility changes - -**Firewall domain whitelist** - -As of v1.4.3, the list of destination domains required for your firewall whitelist changes to the following: - - -- `.edge.agora.io` -- `.edge.sd-rtn.com` -- `web-1.ap.sd-rtn.com`` -- `web-2.ap.sd-rtn.com` -- `ap-web-1.agora.io` -- `ap-web-2.agora.io` -- `webcollector-rtm.agora.io` -- `logservice-rtm.agora.io` -- `rtm.statscollector.sd-rtn.com` -- `rtm.logservice.sd-rtn.com` - -If you upgrade the SDK to v1.4.3, update your firewall domain whitelist to ensure you can use Agora products in environments with restricted network access. +- Change the parameter type of the `messageType` from `string | binary` to `STRING | BINARY`. +- Rename the `TokenPrivilegeWillExpire` callback to `tokenPrivilegeWillExpire`. #### New features -**Regional connection** - -This release adds the `AgoraRTM.setArea` method for specifying the region for connection. After specifying the region, the SDK connects to the Agora servers within that region. The following regions are supported: - -- Mainland China -- North America -- Europe -- Asia, excluding Mainland China -- Japan -- India -- Global - -If you specify the region for connection as GLOBAL, you can use the excludeArea parameter in the AgoraRTM.setArea method to remove individual region from the regions for connection possibilities. - -#### API changes +**Stream Channel** -**Added** +Experience seamless, delay-free data flow from one point to another. Stream channel solution refers to a real-time data pipeline that enables the uninterrupted flow of data from one point to another without delay or latency. -createInstance +**Pub/Sub** +Embrace asynchronous messaging, enabling instant communication between publishers and subscribers without the need for immediate responses. The pub/sub model is a messaging pattern used in real-time messaging solutions where publishers send messages to channels, and subscribers receive messages from the channels they are subscribed to. -**Deprecated** +**Topic** -`createInstance`. Use createInstance. +Effectively manage data streams with topics, enabling seamless communications between users. Topic serves as a data flow management mechanism in the stream channel. It enables users to subscribe to, distribute, and notify events of data streams. Topics allow users to register as message publishers, send messages, and receive messages from subscribed publishers in a channel. -## v1.4.2 +**Storage** -v1.4.2 was released on March 2, 2021. +Storage is important in signaling solutions to ensure reliable message delivery and prevent message loss or drop. -#### Compatibility changes +**Removing Event Listeners** -**Behavioral changes** +This release adds the `removeEventListener` method. You can use it to remove a specified event listener. -- To better describe the behavior of the `setParameters` method in terms of naming, this version adds the `updateConfig` method, which is a duplicate of the `setParameters` method. The `updateConfig` method deprecates the `setParameters` method. -- When the size of `content` is greater than 8 KB, the `INVITATION_API_CALL_ERR_INVALID_ARGUMENT` error code is triggered when calling `send` instead of calling `setContent`. +**Interval Mode** -**Integration changes** +This release supports the interval mode of presence function. When the number of online users in a channel exceeds the specified **Announce Max** value, the channel enters the interval mode. The SDK triggers the `presence` event notification at regular intervals and provides aggregated incremental information about user join, leave, timeout, and state changes in the `interval` property. For more details, see [Interval Mode](../reference/api?platform=web#presence-event-types). -- As of this version, you must include the [js-sha1](https://www.npmjs.com/package/js-sha1) library in order to use the SDK to upload files or images in Microsoft Edge legacy or Internet Explorer 11 by one of the following methods: - - In the HTML file, expose js-sha1 to the global `sha1` variable: - - ```xml - - ``` - - - Add the following line to the JS file: - - ```javascript - window.sha1 = require('js-sha1') - ``` - -- The `isHistoricalMessage` member variable is removed from the `ReceivedMessageProperties` object. +Signaling version 2.x does not support history and peer-to-peer messages in favor of the pub/sub model. #### Improvements -- The size of the decompressed SDK decreases by about 20%. -- (SDK from NPM only) The TS file in the SDK adds the following exports: - - `LocalInvitation` - - `RemoteInvitation` - - `RtmMessage` - - `RtmRawMessage` - - `RtmTextMessage` - - `RtmFileMessage` - - `RtmImageMessage` -- The SDK automatically adds the corresponding MIME type to the Blob type from `downloadMedia`. The SDK supports automatically detecting and adding the following MIME types: - - image/png - - image/gif - - application/pdf - - image/jpeg - - application/zip - -#### API changes - -**Added** - -updateConfig - -**Deprecated** - -`setParameters` - -**Removed** - -`isHistoricalMessage` member variable in `ReceivedMessageProperties` - -## v1.4.1 - -v1.4.1 was released on November 5, 2020. - -**New features** - -Fixed the performance issue when communicating with the Native SDK. - -## v1.4.0 - -v1.4.0 was released on September 25, 2020. - -**Compatibility changes** - -v1.4.0 supports only TypeScript 3.8 or higher. - - -**New features** - -Geofencing. You can use the `areaCodes` parameter in `createInstance` to set the region of the Agora . The can only connect to Agora servers within the specified region. - - -**API changes** - -#### Added - -The `areaCodes` parameter is added to createInstance. - - -## v1.3.1 - -v1.3.1 was released on August 7, 2020. - -**Fixed issues** - -- Connection stability issue between the Agora and the Agora system. -- The same offline message might be delivered multiple times. -- Login stability issue of the . -- Stability issue of sending and receiving peer-to-peer messages. -- The TokenExpired. callback could not be triggered in time. - - -## v1.3.0 - -v1.3.0 was released on June 16, 2020. - -**Compatibility changes** - -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. -- The typical timeout for asynchronously calling a method changes from 5 seconds to 10 seconds. -- You need to add port 9601 to the TCP protocol of the firewall whitelist to support sending and receiving file or image messages. See [Firewall Requirements](../reference/firewall). - -**New features** - -#### 1. Send and receive file messages or image messages - -You can call `createMediaMessageByUploading` to upload non-empty files or image files no greater than 30 MB. Each uploaded file or image stays in the Agora server for seven days. The SDK returns a media ID as the unique identifier of the file or image file. You can use the `RtmFileMessage` interface or the `RtmImageMessage` interface to save the media ID. The `RtmFileMessage` interface and the `RtmImageMessage` interface are type aliases of the `RtmMessage` interface, so you can send and receive file or image messages via peer-to-peer or channel message methods. You can call `downloadMedia` to download the received file or image file. - -#### 2. Manage upload or download tasks - -You can use the `mediaTransferHandler` interface to cancel or report the progress of an upload or download task. - -**Fixed issues** - -Fixed the login issues for some users. - -**API changes** - -#### Added - -- createMediaMessageByUploading. -- downloadMedia. -- createMessage. -- RtmImageMessage. -- RtmFileMessage. -- mediaTransferHandler. -- mediaOperationProgress. - - -## v1.2.2 - -v1.2.2 was released on February 21, 2020. - -**Compatibility Changes** - - -| Timeout | Before v1.2.2 | v1.2.2 | -| ---------------- | ---------------- | ---------------- | -| Send a channel message. | 5 s | 10 s | - - - -**Issues fixed** - -The SDK occasionally returns `LOGIN_ERR_UNKNOWN` when logging in from a recent version of Chrome on a Windows platform. - -## v1.2.1 - -v1.2.1 was released on December 17, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - - -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `MemberJoined` twice. - -## v1.2.0 - -v1.2.0 was released on November 15, 2019. - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the PeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the PeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the PeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - - If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - -**Issues fixed** - -The SDK is occasionally kicked by the server: When the issue occurs, the Client instance receives the `ConnectionStateChange` callback, which indicates the connection state is `ABORTED` and the reason for the connection state change `INTERRUPTED`. The log file shows the error code from the server is 10001. - - -## v1.1.0 - -v1.1.0 was released on September 18, 2019. It adds the following features: - -- [Gets the member count of specified channel(s).](#getcount) -- [Automatically returns the latest numer of members in the current channel](#oncount) -- [Channel attribute operations](#channelattributes) - - - -**Compatibility Changes** - -1. The getServerReceivedTs method of the RtmMessage object supports both peer-to-peer and channel messages. -2. Timeout for sending a peer-to-peer message is 10 seconds from this release, compared to 5 seconds in previous versions. See PEER_MESSAGE_ERR_TIMEOUT. - -**New Features** - - -#### 1. Gets the member count of specified channel(s). - -You can now get the member count of specified channel(s) without the need to join, by calling the `getChannelMemberCount` method. You can get the member counts of a maximum of 32 channels in one method call. - - -#### 2. Automatically returns the latest numer of members in the current channel - -If you are already in a channel, you do not have to call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members `MemberCountUpdated` the latest channel member count when the number of channel members changes. Note that: - -- When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. -- When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - - -#### 3. Channel attribute operations - -Supports setting or getting the attribute(s) of a specified channel. You can use this feature to create group anouncement. - -Each channel attribute comes as a key-value pair. Where: - -- The key of each channel attribute must be visible characters and not exceed 8 KB. -- Each channel attribute must not exceed 8 KB in length. -- The overall size of the attributes of a channel must not exceed 32 KB. -- The number of attributes of a channel must not exceed 32. - -Specific features: - -- Sets the attributes of a specified channel with new ones. -- Adds or updates the attribute(s) of a specified channel. -- Deletes the attributes of a specified channel by attribute keys. -- Clears all attributes of a specified channel. -- Gets all attributes of a specified channel. -- Gets the attributes of a specified channel by attribute keys. - -When updating attributes of a channel, you can use the `enableNotificationToChannelMembers` flag to decide whether or not to notify all members of the channel about this attribute change. - -**Improvements** - -#### Resends peer-to-peer messages - -This release improves the resending mechanism of peer-to-peer messages, and extends the timeout for sending a peer-to-peer message from five to 10 seconds, greatly improving the success rate of peer-to-peer message sending under weak network conditions. - -#### Caches channel messages - -The Agora system will resend a maximum of 32 channel messages of up to 30 seconds to channel members, when they manage to reconnect to the system from poor network conditions. This greatly improves the overall arrival rate of channel messages under weak network conditions. - - -**API Changes** - -#### Added Methods - -- setChannelAttributes: Sets the attributes of a specified channel with new ones. -- addOrUpdateChannelAttributes: Adds or updates the attribute(s) of a specified channel. -- deleteChannelAttributesByKeys: Deletes the attributes of a specified channel by attribute keys. -- clearChannelAttributes: Clears all attributes of a specified channel. -- getChannelAttributes: Gets all attributes of a specified channel. -- getChannelAttributesByKeys: Gets the attributes of a specified channel by attribute keys. -- getChannelMemberCount: Gets the member count of specified channel(s). - -#### Added Callbacks - -- AttributesUpdated: Returns all attributes of the channel when the channel attributes are updated. -- MemberCountUpdated: Occurs when the number of the channel members changes, and returns the new number. - -#### Added Error Codes - -- GetChannelMemberCountErrCode: Error codes related to retrieving the channel member count of specified channel(s). -- JOIN_CHANNEL_ERR_JOIN_SAME_CHANNEL_TOO_OFTEN: The frequency of joining the same channel exceeds two times every five seconds. -- JOIN_CHANNEL_ERR_ALREADY_JOINED_CHANNEL_OF_SAME_ID: You have already joined another channel instance of the same channel ID. - - - - - - - -## v1.0.1 - -v1.0.1 was released on September 5, 2019. - -**Issues Fixed** - -- Peer-to-peer messages have a chance to become offline messages even if enableOfflineMessaging is not set. -- The local user has a chance of not being able to retrieve the latest user attributes of a remote user, if the remote user updates his/her attributes immediately after logging in the Agora system. - -**Improvements** - -- Caches up to six seconds of peer-to-peer messages sent when the network is interrupted, and resends the cached messages immediately after the SDK reconnects to the Agora system. -- Timeout for sending a peer-to-peer message is reset to 10 seconds. - -## v1.0.0 - -v1.0.0 was released on August 5th, 2019. - -**New Features** - -#### Interconnects with the legacy Agora Signaling SDK - -v1.0.0 implements the `LocalInvitation.channelId` and `LocalInvitation.channelId` property. - -> - To intercommunicate with the legacy Agora Signaling SDK, you MUST set the channel ID. However, even if the callee successfully accepts the call invitation, the Agora does not join the channel of the specified channel ID. -> - If your App does not involve the legacy Agora Signaling SDK, we recommend using the `LocalInvitation.content` or the `RemoteInvitation.response` property to set customized contents. - - -#### Sets the output log level of the SDK - -Supports setting the output log level of the SDK using the `logFilter` parameter. The log level follows the sequence of OFF, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels ERROR and WARNING. - - -#### API Changes - -#### Adds - -- logFilter -- setParameters - - - -## v0.9.3 - -v0.9.3 was released on July 24th, 2019. - -**New Features** - -#### Sends an (offline) peer-to-peer message to a specified user (receiver) - -This version allows you to send a message to a specified user when he/she is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that for now we only cache 200 offline messages for up to seven days for each receiver. When the number of the cached messages reaches this limit, the newest message overrides the oldest one. - - -#### User attribute-related operations - -This version allows you to set or update a user's attributes. You can: - -- Substitutes the local user's attributes with new ones. -- Adds or updates the local user's attribute(s). -- Deletes the local user's attributes using attribute keys. -- Clears all attributes of the local user. -- Gets all attributes of a specified user. -- Gets the attributes of a specified user using attribute keys. - -> The attributes you set will be cleard when you log out of . - - -#### Queries the Online Status of the Specified Users - -This release introduces a new concept: online and offline. - -- Online: The user has logged in the Agora system. -- Offline: The user has logged out of the Agora system. - -This release adds the function of querying the online status of the specified users. After logging in the Agora system, you can get the online status of a maximum of 256 specified users. - - -#### Renews the Token +**Presence Service** -This release allows you to renew a token. +User and device online/offline and status change notification capabilities get a list of online users in a channel, retrieve the channel list of online users, and dynamically monitor users joining or leaving channels. -**API Changes** +This release also improves the behavior of calling presence APIs when the presence service is not ready. After joining a stream channel or subscribing to a message channel, if the presence service is not ready, the SDK locally stores your operations related to the presence module and sends them out once the presence service becomes ready. -#### Adds +Additionally, in the return value of the `getOnlineUsers` method, this release removes the information of timed-out users. -- sendMessageToPeer -- setLocalUserAttributes -- addOrUpdateLocalUserAttributes -- deleteLocalUserAttributesByKeys -- clearLocalUserAttributes -- getUserAttributes -- getUserAttributesByKeys -- queryPeersOnlineStatus -- renewToken +**Subscribing Message Publisher** -## v0.9.1 +This release improvements the behavior of subscribing to message publishers with invalid user IDs. When calling the `{topic.subscribe[frontMatter.ag_platform]}` method, if the list of publishers (`users` property) contains invalid user IDs, the SDK ignores the invalid user IDs and can successfully subscribe to the valid users. -v0.9.1 was released on May 20th, 2019. +**Custom Message Type** -**New Features** +This release supports to pass special characters such as Chinese characters into the `customType` parameter when calling the `{message.publish[frontMatter.ag_platform]}` or `{topic.publish[frontMatter.ag_platform]}` methods. -This release adds the call invitation feature, allowing you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. +**Encryption Salt** +This release allows to omit the `salt` parameter when setting encryption. +**State Synchronization** -**API Changes** +Ensures that the shared state between devices or systems remains consistent and up to date in real time. -#### Adds +**Authentication** -- createLocalInvitation: Creates a call invitation. -- LocalInvitation.send: Allows the caller to send a call invitation to a specified user (callee). -- LocalInvitation.cancel Allows the caller to cancel a sent call invitation. -- LocalInvitationState: **RETURNED TO THE CALLER** Call invitation status codes. -- LocalInvitationFailureReason: **RETURNED TO THE CALLER** Reason for failure of the outgoing call invitation. -- RemoteInvitationReceived: Occurs when the callee receives a call invitation. -- RemoteInvitation.accept: Allows the callee to accept an incoming call invitation. -- RemoteInvitation.refuse: Allows the callee to declien an incoming call invitation. -- RemoteInvitationState: **RETURNED TO THE CALLEE**: Call invitation status codes. -- RemoteInvitationFailureReason: **RETURNED TO THE CALLEE**: Reason for the failure of the incoming call invitation. +Utilize token-based access control, ensuring secure interactions and protecting data. -#### Renames +**Locks** -- `RtmClient.ConnectionStateChange` to ConnectionStateChanged . +Implement locks to maintain the sequence of messages, ensuring your data is processed in a specific order, preventing any data conflicts. When a client accesses a resource, it can acquire a lock on that resource to prevent other clients from accessing it. -#### Deletes +**Logout Optimization** -- The `RtmChannel.getId()` method. Uses the channelId property instead. +This release reduces the response time of the `logout` method. -## v0.9.0 +**Error Message Optimization** -v0.9.0 was released on February 14th, 2019. +To facilitate troubleshooting, this release adds error descriptions for each error code and adds error stacks in the error messages of the storage and lock modules. Additionally, this release removes the `RTM_ERROR_INVALID_ARGUMENT(-2)` and `RTM_ERROR_TOO_OFTEN(-12)` error codes, and adds the following error codes: -Initial version. +- `RTM_ERROR_LOGIN_NOT_AUTHORIZED(-10015)` +- `RTM_ERROR_INCONSISTENT_APPID(-10016)` +- `RTM_ERROR_INVALID_CHANNEL_TYPE(-10019)` +- `RTM_ERROR_INVALID_ENCRYPTION_PARAMETER(-10020)` +- `RTM_ERROR_OPERATION_RATE_EXCEED_LIMITATION(-10021)` -**Key features** +For error code descriptions and troubleshooting ways, see [Error Codes](../reference/api?platform=web#error-codes-table). -- Sends or receives peer-to-peer messages. -- Joins or leaves a channel. -- Sends or receives channel messages. +#### Fixed issues +This release fixed the following issues: +- The SDK version information was lost in the log file. +- The `userId` property of the `GetStateResponse` data type was `null`. +- After calling the `removeState` method, the SDK returned the `RemoveStateResponse` data type before the removing operation. +- Exceptions in poor network scenarios. +- When joining a channel and setting the parameter as `withPresence: false`, the `userId` property returned by the `{presence.getstate[frontMatter.ag_platform]}` method was empty. +- During network disconnection and reconnection, any API call failed and returned the `RTM_ERROR_NOT_LOGIN(-10002)` error code. +- Calling any API of the presence module failed when the client woke up from sleep mode. +- Calling the `login` method failed when the resource was not loaded. +- If special characters such as Chinese were passed into the API of the presence module, messages sent to the remote client were truncated. - \ No newline at end of file + diff --git a/shared/signaling/release-notes/windows.mdx b/shared/signaling/release-notes/windows.mdx deleted file mode 100644 index 6f67db789..000000000 --- a/shared/signaling/release-notes/windows.mdx +++ /dev/null @@ -1,388 +0,0 @@ - - - -This page contains information about the following releases: - -## v1.5.1 - -v1.5.1 was released on September 1, 2022 and improved the stability of the SDK. - -### v1.5.0 -v1.5.0 was released on July 27, 2022. - -#### Sunset features -Image or file messages, historical messages, and offline messages are deprecated as of this release. If you have integrated these features in a previous release, you can continue to use them. - -#### API changes - -The following methods are deprecated: - -- createFileMessageByMediaId -- createFileMessageByUploading -- createImageMessageByMediaId -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- downloadMediaToMemory -- downloadMediaToFile -- enableOfflineMessaging -- enableHistoricalMessaging -- onFileMessageReceived -- onFileMessageReceivedFromPeer -- onImageMessageReceived -- onImageMessageReceivedFromPeer -- onMediaUploadingProgress -- onMediaDownloadingProgress - -### v1.4.10 -v1.4.10 was released on March 01, 2022. - - -#### Issues fixed - -Fixed some rich media related crashes. -### v1.4.9 -v1.4.9 was released on November 26, 2021. - -#### Improvements - -Improved the login success rate and connection stability under the IPv4/IPv6 dual-stack network. - -## v1.4.7 -v1.4.7 was released on July 19, 2021. - -Improved the success rate of logins and message delivery for the in poor network conditions. - -## v1.4.6 - -v1.4.6 was released on June 21, 2021. - -Fixed some issues that may cause crashes to improve stability. - -## v1.4.5 - -v1.4.5 was released on April 30, 2021. - -#### Improvements - -Fixed some issues that may cause crashes to improve stability. - -## v1.4.4 - -v1.4.4 was released on April 20, 2021. - -#### Improvements - -Improved the success rate of logins and message delivery for the in poor network conditions. - -#### Issues fixed - -Fixed some issues that might cause the system to crash. - -## v1.4.3 - -v1.4.3 was released on February 10, 2021. - -#### Issues fixed - -This release fixed the following issues: - -- Crash issues caused by occasional multi-thread access conflict. -- High timeout rate for login operations. - -## v1.4.2 - -v1.4.2 was released on November 23, 2020. - -**Improvements** - -- Improved performance of login and messaging operations. -- Added the `AGORA_SDK_BOTH_RTM_AND_RTC` macro for the `RTM_AREA_CODE` enum type. You can use the macro to resolve naming conflicts when using and together. - -## v1.4.1 - -v1.4.1 was released on September 30, 2020. - -**Improvements** - -Improved the log file. - - -## v1.4.0 - -v1.4.0 was released on September 1, 2020. - -**Compatibility changes** - -- You need to add new ports to the firewall whitelist. See [Firewall Requirements](../reference/firewall). - - New TCP ports: 8443, 9136, 9137, 9141. New UDP port: 8443. Reason: Support real-time transport encryption. - - New UDP ports: 8130, 9120, 9121. Reason: Support UDP path to improve the SDK's performance in sub-optimal network conditions. - - New UDP port: 9700. Reason: Support data reporting. -- In `setLogFileSize`, the default log file size increases from 512 KB to 10 MB. The maximum log file size increases from 10 MB to 1 GB. - -**New features** - -- Geofencing. You can call `setRtmServiceContext` to set the region of the Agora . The can only connect to Agora servers within the specified region. -- Transport Layer Security (TLS) encryption. - -**Improvements** - -- Improved the success rate of login and message delivery of the in poor network conditions. -- Optimized the reconnection mechanism. - -**API changes** - -#### New methods - -setRtmServiceContext - -## v1.3.0 - -v1.3.0 was released on May 8, 2020. - -**Compatibility changes** - -- You need to add a new TCP port, 9140, to the firewall whitelist. The port is for sending and receiving image or file messages. See [Firewall Requirements](../reference/firewall). -- The Agora server blocks any file message or image message that you send to 1.2.2 or earlier, or to the Signaling SDK. - -**New features** - -#### 1. Send and receive file messages - -v1.3.0 supports downloading non-empty files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each file you upload to the Agora server corresponds to a media ID. The file stays on the Agora server for seven days. You can use the media ID to download the file as long as the it is still on the Agora server. - -You can only download files using the methods provided by the SDK. - -v1.3.0 adds the `IFileMessage` message class for saving and transferring a media ID. The `IFileMessage` class inherits from the `IMessage` class, so you can use the existing peer-to-peer or channel messaging methods to transfer the `IFileMessage` instance. You can use the `IFileMessage` object to complete the following tasks: - -- Set the filename and thumbnail of the uploaded file. -- Get the size of the uploaded file. - -
    The total size of the message content, the filename, and the thumbnail must not exceed 32 KB.
    - -#### 2. Send and receive image messages - -v1.3.0 supports downloading non-empty image files that are smaller than 30 MB. You can cancel an ongoing upload or download process at any time. Each image you upload to the Agora server corresponds to a media ID. The image file stays on the Agora server for seven days. You can use the media ID to download the image file as long as it is still on the Agora server. - -
    You can only download image files using the download methods provided by the SDK.
    - -v1.3.0 adds the `IImageMessage` message class for saving and transferring a media ID. The `IImageMessage` class inherits from the `IMessage` class, so you can use the existing peer-to-peer or channel messaging methods to transfer the `IImageMessage` instance. You can use the `IImageMessage` object to complete the following tasks: - -- Set the filename and thumbnail of the uploaded image file. -- Get the size of the uploaded image file. -- Get the SDK-calculated width and height of image files in JPEG, JPG, BMP, or PNG format. -- Set the width or height of image files. The width or height you set overwrites the width or height that the SDK calculates. - -
    The total size of the message content, the filename, and the thumbnail must not exceed 32 KB.
    - -#### 3. Report the progress of upload or download - -The SDK returns the progress of an upload or download by callback every second during a task in progress. If the upload or download task pauses, the SDK ceases to return any further callback until the task continues. - -**Bug fixes** - -- Login failure caused by the SDK's incorrect identification of user's network type. -- Other problems that may cause the system to crash. - -**API changes** - -#### New methods - -- createFileMessageByUploading -- createImageMessageByUploading -- cancelMediaUpload -- cancelMediaDownload -- createFileMessageByMediaId -- createImageMessageByMediaId -- downloadMediaToMemory -- downloadMediaToFile - -#### New callbacks - -- onMediaUploadingProgress -- onMediaDownloadingProgress -- onMediaCancelResult -- onFileMediaUploadResult -- onImageMediaUploadResult -- onFileMessageReceivedFromPeer -- onImageMessageReceivedFromPeer -- onFileMessageReceived -- onImageMessageReceived -- onMediaDownloadToMemoryResult -- onMediaDownloadToFileResult - -#### Deprecated methods - -sendMessage is deprecated. Use sendMessage (const IMessage *message, const SendMessageOptions &options) instead. - -## v1.2.2 - -v1.2.2 was released on December 13, 2019. - - -**Compatibility Changes** - -This release deprecates the createAgoraService method, which creates an IAgoraService instance, and the initialize method, which initializes the created IAgoraService instance. As of this relase, you only need to call the createRtmService method and the initialize method to initialize it before being able to call its functions. - - -**Issues Fixed** - -Occasionally fails to receive any callback after a channel attribute operation. - -## v1.2.1 - -v1.2.1 was released on November 29, 2019. - -**New Feature** - -*Compatible with the endCall method of the Agora Signaling SDK* - -If you use the `sendMessageToPeer` method to send a text message in the format of AgoraRTMLegacyEndcallCompatibleMessagePrefix_\_\, then this method is compatible with the endCall method of the legacy Agora Signaling SDK. Replace \ with the channel ID from which you want to leave (end call), and replace \ with any additional information. Note that you must not put any "_" (underscore) in your additional information but you can set \ as empty "". - -**Issues Fixed** - - -- The SDK fails to reconnect to the Agora system if the user disables VPN. -- If a channel member reconnects to the Agora server after being interrupted, chances are the rest members of the channel can receive `onMemberJoined` twice. - -## v1.2.0 - -v1.2.0 was released on November 6, 2019. - -**Compatibility Changes** - -Deprecated the `isOnline` property of the `PeerOnlineStatus`. Use `onlineState` instead. - - -**New Features** - -#### Subscribe to the online status of the specified user(s) - -When the method call succeeds, the SDK returns the onPeersOnlineStatusChanged callback to report the online status of peers, to whom you subscribe. -When the online status of the peers, to whom you subscribe, changes, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed. -If the online status of the peers, to whom you subscribe, changes when the SDK is reconnecting to the server, the SDK returns the onPeersOnlineStatusChanged callback to report whose online status has changed when successfully reconnecting to the server. - -#### Unsubscribe from the online status of the specified user(s) - -Allows you to unsubscribe from the online status of the specified user(s). - -#### Get a list of the peers, to whose specific status you have subscribed - -Allows you to get a list of the peers, to whose specific status you have subscribed. - -#### Create a raw message - -Creates and initializes a raw message to be sent. - - If you set a text description, ensure that the size of the raw message and the description combined does not exceed 32 KB. - - - - - - -## v1.1.0 - -v1.1.0 was released on September 30, 2019. It added the following features: - -**Send an (offline) peer-to-peer message to a specified user** - -This version allows you to send a message to a specified user when that user is offline. If you set a message as an offline message and the specified user is offline when you send it, the server caches it. Please note that we only cache 200 offline messages for up to seven days for each receiver. If the number of the cached messages reaches this limit, the newest message overrides the oldest one. - - - - - -**Get the member count of specified channel(s)** - -Use the getChannelMemberCount method get the member count of specified channel(s) without the need to join them. One method call can get the member counts of a maximum of 32 channels. - -**Query the online status of the specified users** - -**User attribute operations** - -This version enables you to set or update a user's attributes. Please note: - -- Only after you successfully logging in the Agora system can you execute user attribute-related operations. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_NOT_LOGGED_IN` error code. -- The attributes you set will be cleared when you log out of . -- You can only set a maximum of 16 KB attributes in a single method call. Otherwise, the SDK triggers the `ATTRIBUTE_OPERATION_ERR_SIZE_OVERFLOW` error code. - -You can do the following: - -- Substitute the local user's attributes with new ones. -- Add or update the local user's attribute(s). -- Use attribute keys to delete the local user's attributes. -- Clear all attributes of the local user. -- Get all attributes of a specified user. -- Use attribute keys to get the attributes of a specified user. - -**Channel attribute operations** - -This version enables you to set or get the attribute(s) of a specified channel. You can use this feature to create group announcements. - -Each channel attribute exists as a key-value pair. See IRtmChannelAttribute for more information. Please note: - -- The key for each channel attribute must be printable characters and not exceed 8 KB. -- Each channel attribute must not exceed 8 KB in length. -- The overall size of the attributes of a channel must not exceed 32 KB. -- The number of attributes of a channel must not exceed 32. - -You can do the following: - -- Substitute the attributes of a specified channel with new ones. -- Adds or update the attribute of a specified channel. -- Use attribute keys to deletes the attributes of a specified channel. -- Clear all attributes of a specified channel. -- Get all attributes of a specified channel. -- Use attribute keys to get the attributes of a specified channel. - -> The enableNotificationToChannelMembers flag decides whether to notify all members of a channel about this attribute change. - -**Call invitation** - -This version enables you to create, send, cancel, accept, and decline a call invitation in a one-to-one or one-to-many voice/video call. - -**Join or leave a channel** - -**Send or receive channel messages** - - - -**Automatically return the latest number of members in the current channel** - -Once you are in a channel, you no longer must call the `getChannelMemberCount` method to get the member count of the current channel. We also do not recommend using `onMemberJoined` and `onMemberLeft` to keep track of the member counts. As of this release, the SDK returns to the channel members onMemberCountUpdated the latest channel member count when the number of channel members changes. Note that: - -- When the number of channel members ≤ 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once per second. -- When the number of channel members exceeds 512, the SDK returns this callback when the number changes and at a MAXIMUM speed of once every three seconds. - - - -> Please treat this callback and the onGetMembers callback separately: -> -> - The former is an automatic callback. It returns the current numer of channel members; -> - The latter is triggered by the getMembers method. It returns a member list of the current channel. If the number of channel members exceeds 512, the SDK only returns a list of 512 randomly selected channel members. - -**Renew the Token** - -**Specify the default path to the SDK log file** - -Use the `setLogFile` method to change the default path to the SDK log file. To ensure that errors are completely written to the log file, we recommend calling this method immediately after you have created and initialized an `IRtmService` instance. - - - -**Set the output log level of the SDK** - -Use the `setLogFilter` method to set the output log level of the SDK. The log level follows the sequence of OFF, CRITICAL, ERROR, WARNING, and INFO. Choose a level to see the logs preceding that level. If, for example, you set the log level to WARNING, you see the logs within levels CRITICAL, ERROR, and WARNING (the OFF level does not return any log results). See also LOG_FILTER_TYPE. - -> You can call this method once you have created and initialized an `IRtmService` instance. You do not have to call this method until after calling the `login` method. - -**Set the log file size in KB** - -Use the `setLogFileSize` method to set the log file size. The log file has a default size of 512 KB. File size settings of less than 512 KB or greater than 10 MB will not take effect. - -> You can call this method once you have created and initialized an `IRtmService` instance. You do not have to call this method until after calling the `login` method. - - - - -
    \ No newline at end of file diff --git a/shared/signaling/run-the-sample-project/android.mdx b/shared/signaling/run-the-sample-project/android.mdx index bdcdba717..668af0b21 100644 --- a/shared/signaling/run-the-sample-project/android.mdx +++ b/shared/signaling/run-the-sample-project/android.mdx @@ -2,7 +2,7 @@ ### 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-Android` folder. @@ -10,9 +10,9 @@ Refer to the following steps to integrate the into the sampl 3. Copy the `*.jar` file in the SDK folder into the `libs` directory of the project folder, and copy the `x86_64`, `x86`, `arm64-v8a`, and `armeabi-v7a` folders to `Agora-Signaling-Tutorial-Android\app\src\main\jniLibs`. -### 4. Run the sample project +### 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. Open `app` with Android Studio. Android automatically syncs the project with gradle. @@ -25,7 +25,7 @@ Refer to the following steps to run the sample project: ``` -3. Compile and run the sample project. Enter any string as the user ID (such as `userA`) and click **Login** to log into . +3. Compile and run the reference app. Enter any string as the user ID (such as `userA`) and click **Login** to log into . You need to specify the user ID yourself. The user ID supports the following character set: diff --git a/shared/signaling/run-the-sample-project/cpp.mdx b/shared/signaling/run-the-sample-project/cpp.mdx index 6796f423e..b6a7e7747 100644 --- a/shared/signaling/run-the-sample-project/cpp.mdx +++ b/shared/signaling/run-the-sample-project/cpp.mdx @@ -2,7 +2,7 @@ ## 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-Linux` folder. @@ -10,9 +10,9 @@ Refer to the following steps to integrate the into the sampl 3. Copy the `*.so` file in the SDK folder into the `lib` directory of the project folder, and copy the `*.h` file in the SDK folder into the `include` directory of the project folder. -## 4. Run the sample project +## 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. Go to the project directory, and run the following command to build the project: ```shellscript diff --git a/shared/signaling/run-the-sample-project/ios.mdx b/shared/signaling/run-the-sample-project/ios.mdx index 505f7fc38..878be7c56 100644 --- a/shared/signaling/run-the-sample-project/ios.mdx +++ b/shared/signaling/run-the-sample-project/ios.mdx @@ -2,7 +2,7 @@ ### 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-iOS-Swift` folder or the `Agora-Signaling-Tutorial-iOS-Objective-C` folder. @@ -35,13 +35,13 @@ Refer to the following steps to integrate the into the sampl 4. Change the **Embed** property of `AgoraRtmKit.xcframework` to **Embed & Sign**. -### 4. Run the sample project +### 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. (Agora--Tutorial-iOS-Swift) Enter your App ID in `AppId.swift`; (Agora--Tutorial-iOS-Objective-C) Enter your App ID in `AppId.m`. -2. Compile and run the sample project. +2. Compile and run the reference app. 3. Enter any string as the user ID (such as `userA`) and click **Login** to log in to . diff --git a/shared/signaling/run-the-sample-project/java.mdx b/shared/signaling/run-the-sample-project/java.mdx index 33190bf66..8fada7f6d 100644 --- a/shared/signaling/run-the-sample-project/java.mdx +++ b/shared/signaling/run-the-sample-project/java.mdx @@ -3,15 +3,15 @@ ## 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-Java` folder. 2. Download the latest version of [ (Linux Java)](../reference/downloads) and extract the files. 3. Copy the `*.jar` file and the `*.so` file in the SDK folder into the `lib` directory of the project folder. -## 4. Run the sample project +## 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. Enter your App ID in `RtmJavaDemo.java`. @@ -31,7 +31,7 @@ Refer to the following steps to run the sample project: $ mvn package ``` -4. Run the sample project. +4. Run the reference app. ```shell $ java -cp target/Signaling-Client-Demo-1.0-SNAPSHOT.jar -Dsun.boot.library.path=lib/ io.agora.mainClass.RtmJavaDemo diff --git a/shared/signaling/run-the-sample-project/macos.mdx b/shared/signaling/run-the-sample-project/macos.mdx index 913d3c930..e1c006606 100644 --- a/shared/signaling/run-the-sample-project/macos.mdx +++ b/shared/signaling/run-the-sample-project/macos.mdx @@ -2,7 +2,7 @@ ### 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-macOS-Swift` folder. @@ -30,13 +30,13 @@ Refer to the following steps to integrate the into the sampl 3. Change the **Embed** property of `AgoraRtmKit.framework` to **Embed & Sign**. -### 4. Run the sample project +### 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. (Agora--Tutorial-macOS-Swift) Enter your App ID in `AppId.swift`. -2. Compile and run the sample project. +2. Compile and run the reference app. 3. Enter any string as the user ID (such as `userA`) and click **Login** to log in to . diff --git a/shared/signaling/run-the-sample-project/unity.mdx b/shared/signaling/run-the-sample-project/unity.mdx index 85acc63ed..ad500e2cb 100644 --- a/shared/signaling/run-the-sample-project/unity.mdx +++ b/shared/signaling/run-the-sample-project/unity.mdx @@ -20,7 +20,7 @@ For testing purposes, Agora Console supports generating tokens. 2. Fill in the App ID, App certificate, and user ID to log in to . You need to specify the user ID yourself (for example, "test"). The generated token is showed on the screen. When calling the `login` method later, ensure that the user ID is the same with the one that you use to generate the token. -### 5. Configure the sample project +### 5. Configure the reference app #### Approach 1: Configure through the Agora asset package @@ -60,13 +60,13 @@ For testing purposes, Agora Console supports generating tokens. 6. Find **Agora Properties** in Inspector list, and enter the App ID and the token. -### 6. Run the sample project +### 6. Run the reference app -Run the sample project according to the following steps: +Run the reference app according to the following steps: 1. Click the **File** menu bar in Unity, and set the device you need to run through **Build Settings**. -2. Click the **Play** button at the top of the Unity main interface to run the sample project directly, or click **File** > **Build And Run** in the menu bar to compile and run the sample project. If the project runs successfully, you can see the following screen on your device: +2. Click the **Play** button at the top of the Unity main interface to run the reference app directly, or click **File** > **Build And Run** in the menu bar to compile and run the reference app. If the project runs successfully, you can see the following screen on your device: ![1625553123694](https://web-cdn.agora.io/docs-files/1625553123694) diff --git a/shared/signaling/run-the-sample-project/web.mdx b/shared/signaling/run-the-sample-project/web.mdx index f235be16b..bd420bbde 100644 --- a/shared/signaling/run-the-sample-project/web.mdx +++ b/shared/signaling/run-the-sample-project/web.mdx @@ -21,9 +21,9 @@ For testing purposes, Agora Console supports generating tokens. 2. Fill in the App ID, App certificate, and user ID to log in to . You need to specify the user ID yourself (for example, "test"). The generated token is showed on the screen. When calling the `login` method later, ensure that the user ID is the same with the one that you use to generate the token. -### 5. Install dependencies and run the sample project +### 5. Install dependencies and run the reference app -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-Web` folder. @@ -31,7 +31,7 @@ Refer to the following steps to integrate the into the sampl $ npm install -3. Run the following command to run the sample project: +3. Run the following command to run the reference app: $ npm run dev @@ -41,7 +41,7 @@ Refer to the following steps to integrate the into the sampl ## Expected result -When the sample project runs successfully, you can see the following interface. You can enter the same App ID, Account Name (user ID) and temporary token to join the same channel and communicate with the remote user. +When the reference app runs successfully, you can see the following interface. You can enter the same App ID, Account Name (user ID) and temporary token to join the same channel and communicate with the remote user. ![1618220582780](https://web-cdn.agora.io/docs-files/1618220582780) diff --git a/shared/signaling/run-the-sample-project/windows.mdx b/shared/signaling/run-the-sample-project/windows.mdx index b4546503f..5b305f376 100644 --- a/shared/signaling/run-the-sample-project/windows.mdx +++ b/shared/signaling/run-the-sample-project/windows.mdx @@ -2,7 +2,7 @@ ### 3. Integrate the -Refer to the following steps to integrate the into the sample project: +Refer to the following steps to integrate the into the reference app: 1. Download the [](https://github.com/AgoraIO/Signaling) repository on Github, and locate the `Agora-Signaling-Tutorial-Windows` folder. @@ -10,9 +10,9 @@ Refer to the following steps to integrate the into the sampl 3. Copy all files in `sdk` to `Agora-Signaling-Tutorial-Windows\SDK`. -### 4. Run the sample project +### 4. Run the reference app -Refer to the following steps to run the sample project: +Refer to the following steps to run the reference app: 1. Use to Visual Studio open `AgoraRTMTutorial.sln`. diff --git a/shared/signaling/storage/_storage.mdx b/shared/signaling/storage/_storage.mdx new file mode 100644 index 000000000..15c602ae2 --- /dev/null +++ b/shared/signaling/storage/_storage.mdx @@ -0,0 +1,62 @@ +import * as data from '@site/data/variables'; +import ProjectImplement from '@docs/shared/signaling/storage/project-implementation/index.mdx'; +import ProjectTest from '@docs/shared/signaling/storage/project-test/index.mdx'; +import Reference from '@docs/shared/signaling/storage/reference/index.mdx'; + + storage is a powerful feature that enables you to store and manage channel and user attributes in a serverless storage system. It acts as an extension of your database, offering synchronization across all participants. By using signaling storage, you can develop innovative, reliable, and scalable applications without the hassle of setting up your own database. This seamless integration ensures that data is readily available and up-to-date for all users, making it easier to build real-time and collaborative applications. + +Your receives metadata modification events in real-time enabling you to update the front-end accordingly. You can leverage user and channel metadata in apps to: + +* **Maintain search history**: Enable users to quickly search for specific messages, users, or topics within the app. + +* **Customize notifications**: Enable users to customize their notification settings, such as choosing notifications to receive and setting custom alert tones. + +* **Enhance security**: Enforce security measures, such as verifying user identity and encrypting messages. + +## Understand the tech + +Using storage you associate metadata with a particular channel or a specific user: + +* **Channel metadata**: store and distribute contextual channel data in your , such as props, announcements, member lists, and relationship chains. +When channel properties are set, updated, or deleted by a user, an event notification is triggered, and other users in the channel receive this information within 100ms. + +* **User metadata**: store and distribute contextual data about users in your . A user has one +set of metadata with one or more attributes. When an attribute is set, updated or deleted, an event notification is +triggered, and users who subscribe to this users metadata will receive this information within 100ms. + +This section presents an overview of the steps required to integrate storage into your . The following figure shows the basic workflow you implement to read and write channel and user metadata: + +![Signaling workflow](/images/signaling/signaling-metadata-workflow.svg) + + +**The implementation is coming soon.** + + + + +## Prerequisites + +To follow this page, you must have: + +- Setup the [ reference app](/en/signaling/get-started/get-started-sdk#project-setup). + + +## Implement storage + +In the storage reference app, after the local user logs in to , you set their metadata in the form of key-value pairs. When the user modifies a value stored as metadata, you call the update method to save the new value. You show a list of all users currently in the channel. When the local user selects another user from the list, you retrieve and display their metadata. You subscribe to the metadata of remote users to be notified of changes. + + + +## Test storage + +This section explains how to run the `storage` reference app and test channel and user metadata features. To run the project, take the following steps: + + + +## Reference + +This section contains additional information that either supplements the content on this page or directs you to documentation that covers other aspects of this product. + + + + diff --git a/shared/signaling/storage/project-implementation/android.mdx b/shared/signaling/storage/project-implementation/android.mdx new file mode 100644 index 000000000..99183d028 --- /dev/null +++ b/shared/signaling/storage/project-implementation/android.mdx @@ -0,0 +1,340 @@ + + +### Implement the user interface + +To show a list of users in the channel and enable the local user to update their status, you add the following elements to the user interface: + +* A `TextView` to display a caption +* A `Button` to switch the local user status +* A `LinearLayout` inside a `ScrollView` to display a list of users in the channel and their status + +To update the UI, in `/app/res/layout/activity_main.xml`, replace the entire `...` block with the following: + + ```xml + + + +