diff --git a/Podfile b/Podfile index bf7fdd3e..1a658245 100644 --- a/Podfile +++ b/Podfile @@ -35,6 +35,8 @@ target 'xplan-ios' do pod 'MarqueeLabel-ObjC' #声网 pod 'AgoraRtcEngine_iOS', '~> 3.0.1' + #TRTC + pod 'TXLiteAVSDK_TRTC', :podspec => 'http://pod-1252463788.cosgz.myqcloud.com/liteavsdkspec/TXLiteAVSDK_TRTC.podspec' #pop动画 pod 'pop', '~> 1.0.12' #云信 diff --git a/Podfile.lock b/Podfile.lock index c4fea639..882a2d57 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -68,6 +68,7 @@ PODS: - SVGAPlayer/ProtoFiles (2.5.7): - Protobuf (~> 3.4) - SZTextView (1.3.0) + - TXLiteAVSDK_TRTC (8.7.10102) - UMCommon (7.3.5): - UMDevice - UMDevice (2.0.5) @@ -102,6 +103,7 @@ DEPENDENCIES: - SSKeychain - SVGAPlayer (~> 2.3) - SZTextView + - TXLiteAVSDK_TRTC (from `http://pod-1252463788.cosgz.myqcloud.com/liteavsdkspec/TXLiteAVSDK_TRTC.podspec`) - UMCommon - UMDevice - YYText @@ -140,6 +142,10 @@ SPEC REPOS: - UMDevice - YYText +EXTERNAL SOURCES: + TXLiteAVSDK_TRTC: + :podspec: http://pod-1252463788.cosgz.myqcloud.com/liteavsdkspec/TXLiteAVSDK_TRTC.podspec + SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce AgoraRtcEngine_iOS: 8ccceaaecff2e80ab28fcd33f3dfd2b417eb5365 @@ -169,10 +175,11 @@ SPEC CHECKSUMS: SSZipArchive: e7b4f3d9e780c2acc1764cd88fbf2de28f26e5b2 SVGAPlayer: 318b85a78b61292d6ae9dfcd651f3f0d1cdadd86 SZTextView: 094dc6acc9beec537685c545d6e3e0d4975174e1 + TXLiteAVSDK_TRTC: e78365f430926a1064e175fd8d97601559e7d3d1 UMCommon: ab4d875ddefe1b06c60b577e4a58bc4d433ee067 UMDevice: c13bbb2e8ca6c67d1e23e03162553e3ec5a8b5b0 YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 -PODFILE CHECKSUM: 5784f27468bf1fc975791ded5ab665168b6d1611 +PODFILE CHECKSUM: 90bfc18d3332c11bf6da588fa02ae11025118de0 COCOAPODS: 1.10.1 diff --git a/xplan-ios.xcodeproj/project.pbxproj b/xplan-ios.xcodeproj/project.pbxproj index a9cee80b..295f8ac8 100644 --- a/xplan-ios.xcodeproj/project.pbxproj +++ b/xplan-ios.xcodeproj/project.pbxproj @@ -102,6 +102,7 @@ 18EE401A2754BA9F00A452BF /* NIMMessageMaker.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EE40182754BA9F00A452BF /* NIMMessageMaker.m */; }; 18F403CB2758C66800A6C548 /* MessageContentText.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F403CA2758C66800A6C548 /* MessageContentText.m */; }; 18F403EE2758CF2F00A6C548 /* MessageContentImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F403ED2758CF2F00A6C548 /* MessageContentImage.m */; }; + 18F4043A275E20D900A6C548 /* TRTCRtcImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F40439275E20D900A6C548 /* TRTCRtcImpl.m */; }; 73FFADDC93E195344047A2EC /* Pods_xplan_ios.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CACF623970097D653132D69A /* Pods_xplan_ios.framework */; }; 9B0E1C5926E77022005D4442 /* BaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E1C5826E77022005D4442 /* BaseNavigationController.m */; }; 9B7D804A2753783D003DAC0C /* SessionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B7D80492753783D003DAC0C /* SessionViewController.m */; }; @@ -496,6 +497,8 @@ 18F403CA2758C66800A6C548 /* MessageContentText.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MessageContentText.m; sourceTree = ""; }; 18F403EC2758CF2F00A6C548 /* MessageContentImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageContentImage.h; sourceTree = ""; }; 18F403ED2758CF2F00A6C548 /* MessageContentImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MessageContentImage.m; sourceTree = ""; }; + 18F40438275E20D900A6C548 /* TRTCRtcImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TRTCRtcImpl.h; sourceTree = ""; }; + 18F40439275E20D900A6C548 /* TRTCRtcImpl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TRTCRtcImpl.m; sourceTree = ""; }; 7DB00EC07F1D0ADFF900B38D /* Pods-xplan-ios.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-xplan-ios.debug.xcconfig"; path = "Target Support Files/Pods-xplan-ios/Pods-xplan-ios.debug.xcconfig"; sourceTree = ""; }; 9B0E1C5726E77022005D4442 /* BaseNavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseNavigationController.h; sourceTree = ""; }; 9B0E1C5826E77022005D4442 /* BaseNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNavigationController.m; sourceTree = ""; }; @@ -951,6 +954,8 @@ 18486234271EB794005FC5DC /* AgoraRtcImpl.m */, 184862CD27213FD7005FC5DC /* ZegoRtcImpl.h */, 184862CC27213FD7005FC5DC /* ZegoRtcImpl.m */, + 18F40438275E20D900A6C548 /* TRTCRtcImpl.h */, + 18F40439275E20D900A6C548 /* TRTCRtcImpl.m */, E81D587B271FBC3B003063FE /* RtcInterface.h */, 9BB865B4272076140029CDE0 /* RtcImplDelegate.h */, ); @@ -2863,6 +2868,7 @@ E878893F273A54F500BF1D57 /* XPGiftPresenter.m in Sources */, E8AEAEED27141AE20017FCE0 /* XPRoomBackContainerView.m in Sources */, E88B5CC126FB407B00DA9178 /* XPMineUserInfoViewController.m in Sources */, + 18F4043A275E20D900A6C548 /* TRTCRtcImpl.m in Sources */, E824545926F5E65900BE8163 /* XPMineVerifIdentityView.m in Sources */, 189DD74026E21C3F00AB55B1 /* YYUtility+App.m in Sources */, 189DD74526E21CCC00AB55B1 /* YYReachability.m in Sources */, diff --git a/xplan-ios/Global/XPConstant.h b/xplan-ios/Global/XPConstant.h index eedd5438..c37d29cb 100644 --- a/xplan-ios/Global/XPConstant.h +++ b/xplan-ios/Global/XPConstant.h @@ -21,6 +21,7 @@ typedef NS_ENUM(NSUInteger, KeyType) { KeyType_WechatAppid,///微信的 appid KeyType_WechatSecret,///微信的 secret KeyType_Agora,///声网 key + KeyType_TRTC,///TRTC key KeyType_NetEase,///云信的key KeyType_APNSCer,///推送证书的名字 keyType_YiDunBussinessId,///易盾的id diff --git a/xplan-ios/Global/XPConstant.m b/xplan-ios/Global/XPConstant.m index e7866dae..bf9af5d1 100644 --- a/xplan-ios/Global/XPConstant.m +++ b/xplan-ios/Global/XPConstant.m @@ -30,13 +30,14 @@ NSString * const KeyWithType(KeyType type) { @(KeyType_WechatAppid) : @"wx3f0462eb7eccd64f", @(KeyType_WechatSecret) : @"1c07949e3f53433f1c6038bfcdd54c40", @(KeyType_Agora) : @"7ae1a8dabe7a44a9a67c829faa409e70", + @(KeyType_TRTC) : @"1400600174", @(KeyType_NetEase) : @"14ef7a0d0a84cb49bae1c22d78cf1ddf", @(KeyType_APNSCer) : @"yinyouApnsRelease", @(keyType_YiDunBussinessId) : @"2eda1894214da27d5ab7aec146fed2a2", @(keyType_UMengAppKey) : @"5ff6bc6dadb42d5826a1cbc4", @(keyType_UMengAppChannel) : @"App Store", }, - ///测试环境 + ///测试环境 @(NO):@{ @(KeyType_PasswordEncode) : @"1ea53d260ecf11e7b56e00163e046a26", @(KeyType_NTESQuickLoginBusinessId) : @"09c1214706c34f4798d3f05d86148608", @@ -45,6 +46,7 @@ NSString * const KeyWithType(KeyType type) { @(KeyType_WechatAppid) : @"wx3f0462eb7eccd64f", @(KeyType_WechatSecret) : @"1c07949e3f53433f1c6038bfcdd54c40", @(KeyType_Agora) : @"7ae1a8dabe7a44a9a67c829faa409e70", + @(KeyType_TRTC) : @"1400600174", @(KeyType_NetEase) : @"82a8d602aacbbb27a1c0fc809052286e", @(KeyType_APNSCer) : @"yinyouApnsDebug", @(keyType_YiDunBussinessId) : @"7ed4c5f72673dfc2d813a27bd5854874", diff --git a/xplan-ios/Main/Message/SessionList/SessionListViewController.h b/xplan-ios/Main/Message/SessionList/SessionListViewController.h index d57c6a3a..e6ac594c 100644 --- a/xplan-ios/Main/Message/SessionList/SessionListViewController.h +++ b/xplan-ios/Main/Message/SessionList/SessionListViewController.h @@ -4,7 +4,7 @@ // // Created by zu on 2021/11/25. // -// 请注意,这是一次冒险。 +// 请注意,这是一次冒险。😱 // #import "BaseViewController.h" diff --git a/xplan-ios/Main/RTC/RtcImpl/RtcInterface.h b/xplan-ios/Main/RTC/RtcImpl/RtcInterface.h index 2a98d0cc..becf1792 100644 --- a/xplan-ios/Main/RTC/RtcImpl/RtcInterface.h +++ b/xplan-ios/Main/RTC/RtcImpl/RtcInterface.h @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol RtcInterface +@required /** 加入频道(房间) */ @@ -34,6 +35,12 @@ NS_ASSUME_NONNULL_BEGIN 销毁引擎 */ - (void)destory; + +@optional +/** + 加入频道(房间),TRTC 进房需要动态签名。 + */ +- (BOOL)joinChannel:(NSString *)channelId sign:(NSString *)sign completion:(void(^ __nullable)(void))completion; @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.h b/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.h new file mode 100644 index 00000000..bd5ac447 --- /dev/null +++ b/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.h @@ -0,0 +1,16 @@ +// +// TRTCRtcImpl.h +// xplan-ios +// +// Created by zu on 2021/12/6. +// + +#import "BaseRtcImpl.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TRTCRtcImpl : BaseRtcImpl + +@end + +NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.m b/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.m new file mode 100644 index 00000000..a9b9dc3d --- /dev/null +++ b/xplan-ios/Main/RTC/RtcImpl/TRTCRtcImpl.m @@ -0,0 +1,104 @@ +// +// TRTCRtcImpl.m +// xplan-ios +// +// Created by zu on 2021/12/6. +// + +#import "TRTCRtcImpl.h" +#import "XPConstant.h" +#import + +@interface TRTCRtcImpl() + +@property (strong, nonatomic) TRTCCloud *engine; + +@end + +@implementation TRTCRtcImpl + +- (instancetype)initWithDelegate:(id)delegate { + self = [super initWithDelegate:delegate]; + if (self) { + _engine = [TRTCCloud sharedInstance]; + [_engine enableAudioVolumeEvaluation:900]; + _engine.delegate = self; + } + return self; +} + +#pragma mark - RtcInterface impl +- (BOOL)joinChannel:(NSString *)channelId sign:(nonnull NSString *)sign completion:(void (^)(void))completion { + TRTCParams *params = [[TRTCParams alloc] init]; + UInt32 appId; + sscanf([KeyWithType(KeyType_TRTC) UTF8String], "%u", &appId); + params.sdkAppId = appId; + UInt32 roomId; + sscanf([channelId UTF8String], "%u", &roomId); + params.roomId = roomId; + params.userId = [[AccountInfoStorage instance] getUid]; + params.userSig = sign; + params.role = TRTCRoleAudience; + [self.engine enterRoom:params appScene:TRTCAppSceneLIVE]; + if (completion) { + completion(); + } + return YES; +} + +- (BOOL)muteRemote:(BOOL)mute { + [self.engine muteAllRemoteAudio:mute]; + return YES; +} + +- (void)broadcast:(BOOL)on { + [self.engine switchRole:on ? TRTCRoleAnchor : TRTCRoleAudience]; + if (on) { + [self.engine startLocalAudio:TRTCAudioQualityDefault]; + } else { + [self.engine stopLocalAudio]; + } +} + +- (BOOL)muteLocal:(BOOL)mute { + [self.engine muteLocalAudio:mute]; + return YES; +} + +- (void)exitChannel:(void (^)(void))completion { + /** + * 1.2 离开房间 + * + * 调用 exitRoom() 接口会执行退出房间的相关逻辑,例如释放音视频设备资源和编解码器资源等。 + * 待资源释放完毕,SDK 会通过 TRTCCloudDelegate 中的 onExitRoom() 回调通知到您。 + * + * 如果您要再次调用 enterRoom() 或者切换到其他的音视频 SDK,请等待 onExitRoom() 回调到来之后再执行相关操作。 + * 否则可能会遇到摄像头或麦克风(例如 iOS 里的 AudioSession)被占用等各种异常问题。 + */ + [self.engine exitRoom]; + if (completion) { + completion(); + } +} + +- (void)destory { + [TRTCCloud destroySharedIntance]; +} + +#pragma mark - TRTCCloudDelegate +- (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume { + NSMutableArray *uids = [NSMutableArray array]; + for (TRTCVolumeInfo *userInfo in userVolumes) { + NSString *uid = userInfo.userId; + if (userInfo.volume > 15){ + if (uid.integerValue == 0) { + [uids addObject:[[AccountInfoStorage instance] getUid]]; + }else { + [uids addObject:uid]; + } + } + } + [self.delegate usersSpeaking:uids]; +} + +@end diff --git a/xplan-ios/Main/RTC/RtcImpl/ZegoRtcImpl.m b/xplan-ios/Main/RTC/RtcImpl/ZegoRtcImpl.m index 82e1c647..bca6b685 100644 --- a/xplan-ios/Main/RTC/RtcImpl/ZegoRtcImpl.m +++ b/xplan-ios/Main/RTC/RtcImpl/ZegoRtcImpl.m @@ -97,7 +97,7 @@ } -#pragma mark - Zego +#pragma mark - ZegoAudioRoomDelegate - (void)onStreamUpdated:(ZegoAudioStreamType)type stream:(ZegoAudioStream *)stream { switch (type) { case ZEGO_AUDIO_STREAM_ADD: diff --git a/xplan-ios/Main/RTC/RtcManager.h b/xplan-ios/Main/RTC/RtcManager.h index 4d9cd684..ed003c19 100644 --- a/xplan-ios/Main/RTC/RtcManager.h +++ b/xplan-ios/Main/RTC/RtcManager.h @@ -11,9 +11,10 @@ NS_ASSUME_NONNULL_BEGIN typedef enum : NSUInteger { RtcEngineType_Agora = 1001, // 声网 - RtcEngineType_Zego, // 即构 + RtcEngineType_Zego, // 即构 RtcEngineType_WJ, // 无界 RtcEngineType_AgoraFast, // 声网急速 + RtcEngineType_TRTC, // 腾讯TRTC } RtcEngineType; /** 音频服务管理单例,对所有音频服务 SDK 的封装。 @@ -74,6 +75,11 @@ typedef enum : NSUInteger { */ - (BOOL)enterRoom:(NSString *)roomUid; +/** + * 加入频道(房间),TRTC 进房需要动态签名。 + */ +- (BOOL)enterRoom:(NSString *)roomUid trtcSign:(NSString *)sign; + /** * 上下麦(说话) */ diff --git a/xplan-ios/Main/RTC/RtcManager.m b/xplan-ios/Main/RTC/RtcManager.m index f63fbdd8..5494cffc 100644 --- a/xplan-ios/Main/RTC/RtcManager.m +++ b/xplan-ios/Main/RTC/RtcManager.m @@ -9,6 +9,7 @@ #import "RtcImplDelegate.h" #import "AgoraRtcImpl.h" #import "ZegoRtcImpl.h" +#import "TRTCRtcImpl.h" @interface RtcManager() @@ -38,7 +39,7 @@ return self; } -+ (instancetype)initEngineWithType:(RtcEngineType)type delegate:(id _Nullable)delegate{ ++ (instancetype)initEngineWithType:(RtcEngineType)type delegate:(id _Nullable)delegate { RtcManager* rtcManager = [self instance]; [rtcManager setEngineType:type]; [rtcManager setEngineDelegate:delegate]; @@ -52,6 +53,13 @@ }]; } +- (BOOL)enterRoom:(NSString *)roomUid trtcSign:(nonnull NSString *)sign { + return [self.engine joinChannel:roomUid sign:sign completion:^{ + [self muteRemote:NO]; + [self muteLocal:NO]; + }]; +} + - (BOOL)muteRemote:(BOOL)mute { return [self.engine muteRemote:mute]; } @@ -119,6 +127,11 @@ _engine = [[ZegoRtcImpl alloc] initWithDelegate:self]; } break; + case RtcEngineType_TRTC: + { + _engine = [[TRTCRtcImpl alloc] initWithDelegate:self]; + } + break; default: { _engine = [[AgoraRtcImpl alloc] initWithDelegate:self]; diff --git a/xplan-ios/Main/Room/Model/RoomInfoModel.h b/xplan-ios/Main/Room/Model/RoomInfoModel.h index 7c37e3c9..3d9818c3 100644 --- a/xplan-ios/Main/Room/Model/RoomInfoModel.h +++ b/xplan-ios/Main/Room/Model/RoomInfoModel.h @@ -37,6 +37,7 @@ typedef NS_ENUM(NSInteger, RoomModeType){ @property (nonatomic , assign) NSInteger calcSumDataIndex; @property (nonatomic , copy) NSString * roomTag; @property (nonatomic , copy) NSString * audioSdkType; +@property (nonatomic , copy) NSString * trtcSig; @property (nonatomic , assign) NSInteger hideFlag; @property (nonatomic , assign) NSInteger blindDateState; @property (nonatomic , assign) RoomType type; @@ -72,12 +73,9 @@ typedef NS_ENUM(NSInteger, RoomModeType){ @property (nonatomic , assign) NSInteger closeScreenFlag; @property (nonatomic , assign) NSInteger operatorStatus; @property (nonatomic , assign) BOOL isRoomFans; -///房间密码 -@property(nonatomic, copy) NSString *roomPwd; -///是否打开离开模式 -@property (nonatomic, assign) BOOL leaveMode; -///房间的模式 -@property (nonatomic, assign) RoomModeType roomModeType;//房间模式 +@property (nonatomic , copy) NSString * roomPwd; +@property (nonatomic , assign) BOOL leaveMode; +@property (nonatomic , assign) RoomModeType roomModeType;//房间模式 @end NS_ASSUME_NONNULL_END diff --git a/xplan-ios/Main/Room/View/StageView/StageView.m b/xplan-ios/Main/Room/View/StageView/StageView.m index aa7938e1..c5476e4a 100644 --- a/xplan-ios/Main/Room/View/StageView/StageView.m +++ b/xplan-ios/Main/Room/View/StageView/StageView.m @@ -83,9 +83,32 @@ RoomInfoModel* roomInfo = self.hostDelegate.getRoomInfo; self.leaveMode = roomInfo.leaveMode; // 1. 加入语音房间。 - RtcEngineType type = [roomInfo.audioSdkType isEqualToString:@"wujie"] ? RtcEngineType_WJ : ([roomInfo.audioSdkType isEqualToString:@"zego"] ? RtcEngineType_Zego : RtcEngineType_Agora); + RtcEngineType type; + if ([roomInfo.audioSdkType isEqualToString:@"wujie"]) { + type = RtcEngineType_WJ; + } else if ([roomInfo.audioSdkType isEqualToString:@"zego"]) { + type = RtcEngineType_Zego; + } else if ([roomInfo.audioSdkType isEqualToString:@"trtc"]) { + type = RtcEngineType_TRTC; + } else { + type = RtcEngineType_Agora; + } [RtcManager initEngineWithType:type delegate:self]; - [[RtcManager instance] enterRoom:[NSString stringWithFormat:@"%ld", (long)roomInfo.roomId]]; + switch (type) { + /** + * 🐴 Agora + * 🐴 Zego + * 🦄️ TRTC + * TRTC,就你 🦄️ 不一样? + */ + case RtcEngineType_TRTC: + [[RtcManager instance] enterRoom:[NSString stringWithFormat:@"%ld", (long)roomInfo.roomId] trtcSign:roomInfo.trtcSig]; + break; + + default: + [[RtcManager instance] enterRoom:[NSString stringWithFormat:@"%ld", (long)roomInfo.roomId]]; + break; + } // 2. 获取麦位的状态,并初始化 self.micQueue 。 [[NIMSDK sharedSDK].chatManager addDelegate:self];