Skip to content

Commit

Permalink
Merge pull request #86 from AgoraIO-Community/handle-rtm-flutter
Browse files Browse the repository at this point in the history
RTM Flutter Handling
  • Loading branch information
maxxfrazer authored Jan 13, 2023
2 parents 7d5ab72 + f326ff4 commit 664c057
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ extension AgoraVideoViewer: RtmControllerDelegate {
func handleDecodedMessage(_ rtmAction: DecodedRtmAction, from peerId: String) {
switch rtmAction {
case .mute(let muteReq):
self.handleMuteRequest(muteReq: muteReq)
self.handleMuteRequest(muteReq: muteReq, from: peerId)
case .userData(let user):
AgoraVideoViewer.agoraPrint(
.verbose, message: "Received user data: \n\(user.prettyPrint())"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,15 @@ extension SingleVideoViewDelegate {
extension AgoraVideoViewer {
/// Handle mute request, by showing popup or directly changing the device state
/// - Parameter muteReq: Incoming mute request data
public func handleMuteRequest(muteReq: MuteRequest) {
guard let device = MutingDevices(rawValue: muteReq.device) else { return }
public func handleMuteRequest(muteReq: MuteRequest, from peerId: String) {
guard var device = MutingDevices(rawValue: muteReq.device) else { return }
if let peerData = self.rtmLookup[peerId] as? AgoraVideoViewer.UserData,
peerData.uikit.framework == "flutter",
// Flutter 1.1.1 and below had camera and microphone swapped.
"1.1.1".compare(peerData.uikit.version) != .orderedAscending,
let newDevice = MutingDevices(rawValue: (muteReq.device + 1) % 2) {
device = newDevice
}
if device == .camera, self.agoraSettings.cameraEnabled == !muteReq.mute { return }
if device == .microphone, self.agoraSettings.micEnabled == !muteReq.mute { return }

Expand Down
12 changes: 9 additions & 3 deletions Sources/Agora-Video-UIKit/AgoraUIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import AgoraRtcKit
public struct AgoraUIKit: Codable {
/// Instance of the current AgoraUIKit instance.
public static var current: AgoraUIKit {
AgoraUIKit(version: AgoraUIKit.version, platform: AgoraUIKit.platform, framework: AgoraUIKit.framework)
AgoraUIKit(version: AgoraUIKit.version,
platform: AgoraUIKit.platform,
framework: AgoraUIKit.framework
)
}
/// Platform that is being used: ios, macos, android, unknown
public fileprivate(set) var platform: String
Expand All @@ -22,7 +25,7 @@ public struct AgoraUIKit: Codable {
/// Framework type of UIKit. "native", "flutter", "reactnative"
public fileprivate(set) var framework: String
/// Version of UIKit being used
public static let version = "4.0.5"
public static let version = "4.0.6"
/// Framework type of UIKit. "native", "flutter", "reactnative"
public static let framework = "native"
#if os(iOS)
Expand Down Expand Up @@ -67,6 +70,9 @@ public struct AgoraUIKit: Codable {
/// - Parameter userInt: Signed integer userId
/// - Returns: Unsigned integer userId
public static func intToUInt(_ userInt: Int) -> UInt {
UInt(UInt32(bitPattern: Int32(userInt)))
if userInt > Int(Int32.max), userInt <= Int(UInt32.max) {
return UInt(userInt)
}
return UInt(UInt32(bitPattern: Int32(userInt)))
}
}
100 changes: 29 additions & 71 deletions Tests/Agora-UIKit-Tests/RtmMessagingTests.swift
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
import XCTest
import AgoraRtcKit
#if canImport(AgoraRtmController) && canImport(AgoraUIKit_iOS)
#if canImport(AgoraRtmControl) && canImport(AgoraUIKit)
import AgoraRtmKit
import AgoraRtmController
@testable import AgoraUIKit_iOS
import AgoraRtmControl
@testable import AgoraUIKit

final class RtmMessagesTests: XCTestCase {
func testEncodeMuteReq() throws {
let muteReq = AgoraVideoViewer.MuteRequest(
rtcId: 999, mute: true, device: .camera, isForceful: true
)
guard let rawMsg = AgoraRtmController.createRtmMessage(from: muteReq) else {
guard let rtmMessage = AgoraRtmController.createRtmMessage(from: muteReq) else {
return XCTFail("MuteRequest should be encodable")
}
XCTAssert(rawMsg.text == "AgoraUIKit", "Message text data should be AgoraUIKit")
let msgText = String(data: rawMsg.rawData, encoding: .utf8)

guard let unencodedJSON = try? JSONSerialization.jsonObject(
with: rawMsg.rawData, options: .allowFragments
) as? [String: Any] else {
XCTAssert(rtmMessage.type == .text, "Message type should be .text")
guard let rawData = rtmMessage.text.data(using: .utf8),
let unencodedJSON = try? JSONSerialization.jsonObject(
with: rawData, options: []) as? [String: Any]
else {
return XCTFail("Could not unencode data")
}
XCTAssertEqual((unencodedJSON["rtcId"] as? UInt), muteReq.rtcId, "rtcId invalid!")

guard let decodedMsg = AgoraVideoViewer.decodeRtmData(
data: rawData, from: ""
) else { return XCTFail("Could not decode RTM data.") }

XCTAssertEqual((unencodedJSON["rtcId"] as? Int), muteReq.rtcId, "rtcId invalid!")
XCTAssertEqual((unencodedJSON["mute"] as? Bool), muteReq.mute, "mute invalid!")
XCTAssertEqual((unencodedJSON["device"] as? Int), muteReq.device, "device invalid!")
XCTAssertEqual((unencodedJSON["isForceful"] as? Bool), muteReq.isForceful, "mute invalid!")
let msgTextValid = "{\"rtcId\":999,\"mute\":true,\"messageType\":"
+ "\"MuteRequest\",\"device\":0,\"isForceful\":true}"

XCTAssertEqual(msgText, msgTextValid, "Message text not matching mstTextValid")
guard let decodedMsg = AgoraVideoViewer.decodeRtmData(
data: rawMsg.rawData, from: ""
) else {
return XCTFail("Failed to decode message")
}
XCTAssertEqual(rtmMessage.text, msgTextValid, "Message text not matching mstTextValid")

switch decodedMsg {
case .mute(let decodedMuteReq):
Expand All @@ -53,63 +53,20 @@ final class RtmMessagesTests: XCTestCase {
rtmId: "1234-5678", rtcId: 190, username: "username",
role: AgoraClientRole.broadcaster.rawValue, agora: .current, uikit: .current
)
guard let rawMsg = AgoraRtmController.createRtmMessage(from: userData) else {
guard let rtmMessage = AgoraRtmController.createRtmMessage(from: userData) else {
return XCTFail("UserData should be encodable")
}
XCTAssert(rawMsg.text == "AgoraUIKit", "Message text data should be AgoraUIKit")
let msgText = String(data: rawMsg.rawData, encoding: .utf8)

guard let unencodedJSON = try? JSONSerialization.jsonObject(
with: rawMsg.rawData, options: .allowFragments
) as? [String: Any] else {
return XCTFail("Could not unencode data")
}
XCTAssertEqual((unencodedJSON["rtcId"] as? UInt), userData.rtcId, "rtcId invalid!")
XCTAssertEqual((unencodedJSON["role"] as? Int), userData.role, "mute invalid!")
XCTAssertEqual((unencodedJSON["username"] as? String), userData.username, "device invalid!")
if let agoraData = unencodedJSON["agora"] as? [String: Any] {
XCTAssertEqual((agoraData["rtc"] as? String), AgoraRtcEngineKit.getSdkVersion(), "rtcId invalid!")
XCTAssertEqual((agoraData["rtm"] as? String), AgoraRtmKit.getSDKVersion(), "mute invalid!")
} else { XCTFail("Could not parse agora version data") }
let msgTextValid = "{\"uikit\":{"
+ "\"platform\":\"ios\",\"version\":\"\(AgoraUIKit.version)\",\"framework\":\"native\"},"
+ "\"role\":1,\"rtmId\":\"1234-5678\",\"username\":\"username\",\"agora\":{\"rtm\":"
+ "\"\(AgoraRtmKit.getSDKVersion()!)\",\"rtc\":\"\(AgoraRtcEngineKit.getSdkVersion())\"},"
+ "\"messageType\":\"UserData\",\"rtcId\":190}"

XCTAssertEqual(msgText, msgTextValid, "Message text not matching msgTextValid")
guard let decodedMsg = AgoraVideoViewer.decodeRtmData(data: rawMsg.rawData, from: "") else {
return XCTFail("Failed to decode message")
}

switch decodedMsg {
case .userData(let decodedUserData):
XCTAssertEqual(decodedUserData.rtcId, userData.rtcId, "rtcId invalid!")
XCTAssertEqual(decodedUserData.rtmId, userData.rtmId, "rtmId invalid!")
XCTAssertEqual(decodedUserData.agora.rtc, AgoraRtcEngineKit.getSdkVersion(), "RTC version invalid!")
XCTAssertEqual(decodedUserData.uikit.framework, "native", "RTC version invalid!")
default:
XCTFail("Should decode to userData")
}
}
XCTAssert(rtmMessage.type == .text, "Message type should be .text")

func testEncodeUserData() throws {
let userData = AgoraRtmController.UserData(
rtmId: "1234-5678", rtcId: 190, username: "username",
role: AgoraClientRole.broadcaster.rawValue, agora: .current, uikit: .current
)
guard let rawMsg = AgoraRtmController.createRawRtm(from: userData) else {
return XCTFail("UserData should be encodable")
}
XCTAssert(rawMsg.text == "AgoraUIKit", "Message text data should be AgoraUIKit")
let msgText = String(data: rawMsg.rawData, encoding: .utf8)

guard let unencodedJSON = try? JSONSerialization.jsonObject(
with: rawMsg.rawData, options: .allowFragments
) as? [String: Any] else {
guard let rawData = rtmMessage.text.data(using: .utf8),
let unencodedJSON = try? JSONSerialization.jsonObject(
with: rawData, options: []) as? [String: Any]
else {
return XCTFail("Could not unencode data")
}
XCTAssertEqual((unencodedJSON["rtcId"] as? UInt), userData.rtcId, "rtcId invalid!")

XCTAssertEqual((unencodedJSON["rtcId"] as? Int), userData.rtcId, "rtcId invalid!")
XCTAssertEqual((unencodedJSON["role"] as? Int), userData.role, "mute invalid!")
XCTAssertEqual((unencodedJSON["username"] as? String), userData.username, "device invalid!")
if let agoraData = unencodedJSON["agora"] as? [String: Any] {
Expand All @@ -122,10 +79,11 @@ final class RtmMessagesTests: XCTestCase {
+ "\"\(AgoraRtmKit.getSDKVersion()!)\",\"rtc\":\"\(AgoraRtcEngineKit.getSdkVersion())\"},"
+ "\"messageType\":\"UserData\",\"rtcId\":190}"

XCTAssertEqual(msgText, msgTextValid, "Message text not matching msgTextValid")
guard let decodedMsg = AgoraRtmController.decodeRawRtmData(data: rawMsg.rawData, from: "") else {
return XCTFail("Failed to decode message")
}
XCTAssertEqual(rtmMessage.text, msgTextValid, "Message text not matching msgTextValid")

guard let decodedMsg = AgoraVideoViewer.decodeRtmData(
data: rawData, from: ""
) else { return XCTFail("Could not decode RTM data.") }

switch decodedMsg {
case .userData(let decodedUserData):
Expand Down
36 changes: 36 additions & 0 deletions Tests/Agora-UIKit-Tests/RtmUserIdHandlingTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// RtmUserIdHandlingTests.swift
//
//
// Created by Max Cobb on 13/01/2023.
//

import XCTest
import AgoraRtcKit
@testable import AgoraUIKit

final class RtmUserIdHandlingTests: XCTestCase {

func testNegativeUID() throws {
let userData = AgoraVideoViewer.UserData(
rtmId: "example-test-rtm-id", rtcId: -512,
role: AgoraClientRole.broadcaster.rawValue
)
XCTAssertEqual(userData.rtcId, -512, "UserData rtcId should be -512")
XCTAssertEqual(
userData.iOSUInt, 4294966784,
"UserData iOSUInt should be 4294966784"
)
}

func testLargeUID() throws {
let userData = AgoraVideoViewer.UserData(
rtmId: "example-test-rtm-id", rtcId: 4294966784,
role: AgoraClientRole.broadcaster.rawValue
)
XCTAssertEqual(
userData.rtcId, Int(userData.iOSUInt ?? 0),
"UserData rtcId should be the same as iOSUInt"
)
}
}

0 comments on commit 664c057

Please sign in to comment.