BGLiveBaseController.m 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. //
  2. // BGLiveBaseController.m
  3. // BugoLive
  4. //
  5. // Created by xfg on 16/11/23.
  6. // Copyright © 2016年 xfg. All rights reserved.
  7. //
  8. #import "BGLiveBaseController.h"
  9. #import "CountDownView.h"
  10. #import "MusicCenterManager.h"
  11. @interface BGLiveBaseController ()
  12. @property(nonatomic, strong) UIImageView *otherPushBgView;
  13. @property(nonatomic, strong) UILabel *otherPushLabel;
  14. @end
  15. @implementation BGLiveBaseController
  16. - (void)dealloc
  17. {
  18. [self releaseAll];
  19. }
  20. - (void)releaseAll
  21. {
  22. [[NSNotificationCenter defaultCenter] removeObserver:self];
  23. AVAudioSession *aSession = [AVAudioSession sharedInstance];
  24. [aSession setMode:_audioSesstionMode error:nil];
  25. }
  26. - (void)initCurrentLiveItem:(id<FWShowLiveRoomAble>)liveItem
  27. {
  28. CurrentLiveInfo *tmpLiveItem;
  29. if ([liveItem isKindOfClass:[CurrentLiveInfo class]])
  30. {
  31. tmpLiveItem = (CurrentLiveInfo *)liveItem;
  32. }
  33. IMAHost *host = [IMAPlatform sharedInstance].host;
  34. NSString *loginId = [host imUserId];
  35. // NSString *loginId = [[ILiveLoginManager getInstance] getLoginId];
  36. // 判断是否主播掉线后重新连接上来的
  37. if (liveItem.liveType == FW_LIVE_TYPE_AUDIENCE && [loginId isEqualToString:[[liveItem liveHost] imUserId]])
  38. {
  39. _isReEnterChatGroup = YES;
  40. [self performSelector:@selector(hostBackTip) withObject:nil afterDelay:4];
  41. }
  42. _roomIDStr = StringFromInt([liveItem liveAVRoomId]);
  43. _isHost = [loginId isEqualToString:[[liveItem liveHost] imUserId]];
  44. if (_isHost)
  45. {
  46. liveItem.liveType = FW_LIVE_TYPE_HOST;
  47. }
  48. if (tmpLiveItem.live_in)
  49. {
  50. if (tmpLiveItem.live_in == FW_LIVE_STATE_ING)
  51. {
  52. _liveType = FW_LIVE_TYPE_AUDIENCE;
  53. }
  54. else
  55. {
  56. _liveType = liveItem.liveType;
  57. }
  58. }
  59. else
  60. {
  61. _liveType = liveItem.liveType;
  62. }
  63. _sdkType = liveItem.sdkType;
  64. _sdkType = [[GlobalVariables sharedInstance].appModel.sdk_type intValue];
  65. // _mickType = liveItem.mickType;
  66. _mickType = FW_MICK_TYPE_AGORA;
  67. self.liveItem = liveItem;
  68. [self.liveItem setIsHost:_isHost];
  69. SUS_WINDOW.isHost = _isHost;
  70. SUS_WINDOW.liveType = (int)_liveType;
  71. }
  72. - (void)hostBackTip
  73. {
  74. SendCustomMsgModel *sendCustomMsgModel = [[SendCustomMsgModel alloc] init];
  75. sendCustomMsgModel.msgType = MSG_ANCHOR_BACK;
  76. sendCustomMsgModel.msg = ASLocalizedString(@"主播回来啦,视频即将恢复~");
  77. sendCustomMsgModel.chatGroupID = [self.liveItem liveIMChatRoomId];
  78. [_iMMsgHandler sendCustomGroupMsg:sendCustomMsgModel succ:nil fail:nil];
  79. }
  80. - (instancetype)initWith:(id<FWShowLiveRoomAble>)liveItem modelArr:(NSArray *)modelArr
  81. {
  82. if (self = [super init])
  83. {
  84. _isAtForeground = YES;
  85. _vagueImgUrl = [liveItem vagueImgUrl];
  86. _iMMsgHandler = [BGIMMsgHandler sharedInstance];
  87. _enterChatGroupTimes = 3;
  88. _modelArr = [NSMutableArray arrayWithArray:modelArr];
  89. [self initCurrentLiveItem:liveItem];
  90. }
  91. return self;
  92. }
  93. - (void)viewWillAppear:(BOOL)animated
  94. {
  95. [super viewWillAppear:animated];
  96. [IQKeyboardManager sharedManager].enable = NO;
  97. [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
  98. // [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
  99. [self.navigationController setNavigationBarHidden:YES animated:YES];
  100. self.navigationController.navigationBar.tintColor = kClearColor;
  101. [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
  102. }
  103. - (void)viewWillDisappear:(BOOL)animated
  104. {
  105. [super viewWillDisappear:animated];
  106. [self.navigationController setNavigationBarHidden:NO animated:YES];
  107. // [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
  108. }
  109. - (void)viewDidLoad
  110. {
  111. [super viewDidLoad];
  112. [self vagueBackGround];
  113. [self checkNetWorkBeforeLive];
  114. // _lossRateSendTipLabel = [[UILabel alloc]initWithFrame:CGRectMake(kDefaultMargin, 135, kScreenW-kDefaultMargin*2, 35)];
  115. _lossRateSendTipLabel = [[UILabel alloc]initWithFrame:CGRectMake(kDefaultMargin, 135, 0, 0)];
  116. _lossRateSendTipLabel.textColor = [UIColor whiteColor];
  117. _lossRateSendTipLabel.font = [UIFont systemFontOfSize:15.0];
  118. [self.view addSubview:_lossRateSendTipLabel];
  119. if ([GlobalVariables sharedInstance].isOtherPush) {
  120. [self.view addSubview:self.otherPushBgView];
  121. [self.view addSubview:self.otherPushLabel];
  122. }
  123. _lossRateSendTipLabel.shadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.8];
  124. _lossRateSendTipLabel.shadowOffset = CGSizeMake(1, 1);
  125. _lossRateSendTipLabel.hidden = YES;
  126. }
  127. #pragma mark - ----------------------- 添加相关监听 -----------------------
  128. - (void)addAVSDKObservers
  129. {
  130. NSError *error = nil;
  131. AVAudioSession *aSession = [AVAudioSession sharedInstance];
  132. _audioSesstionCategory = [aSession category];
  133. _audioSesstionMode = [aSession mode];
  134. [aSession setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&error];
  135. [aSession setMode:AVAudioSessionModeDefault error:&error];
  136. [aSession setActive:YES error: &error];
  137. // 监听声音打断
  138. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAudioInterruption:) name:AVAudioSessionInterruptionNotification object:nil];
  139. // 监听耳机插入和拔出
  140. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:nil];
  141. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
  142. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillTeminal:) name:UIApplicationWillTerminateNotification object:nil];
  143. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
  144. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
  145. }
  146. - (BOOL)isOtherAudioPlaying
  147. {
  148. UInt32 otherAudioIsPlaying;
  149. UInt32 propertySize = sizeof (otherAudioIsPlaying);
  150. #pragma clang diagnostic push
  151. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  152. AudioSessionGetProperty(kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying);
  153. #pragma clang diagnostic pop
  154. return otherAudioIsPlaying;
  155. }
  156. - (void)onAppBecomeActive:(NSNotification *)notification
  157. {
  158. if (![self isOtherAudioPlaying])
  159. {
  160. [[AVAudioSession sharedInstance] setActive:YES error: nil];
  161. }
  162. }
  163. #pragma mark app将要销毁
  164. - (void)onAppWillTeminal:(NSNotification*)notification
  165. {
  166. // _isDirectCloseLive = YES;
  167. // [self realExitLive:nil failed:nil];
  168. }
  169. #pragma mark - ----------------------- 进入、退出直播 -----------------------
  170. #pragma mark 弹出退出或直接退出
  171. - (void)alertExitLive:(BOOL)isDirectCloseLive isHostShowAlert:(BOOL)isHostShowAlert succ:(FWVoidBlock)succ failed:(FWErrorBlock)failed
  172. {
  173. [BGUtils closeKeyboard];
  174. if (_iMMsgHandler.isExitRooming)
  175. {
  176. if (failed)
  177. {
  178. failed(FWCode_Normal_Error, ASLocalizedString(@"正在退出直播中"));
  179. }
  180. return;
  181. }
  182. MUSIC_CENTER_MANAGER.musicPlayingState = NO;
  183. _isDirectCloseLive = isDirectCloseLive;
  184. if (_isHost && _liveType == FW_LIVE_TYPE_HOST && isHostShowAlert)
  185. {
  186. FWWeakify(self)
  187. [FanweMessage alert:nil message:ASLocalizedString(@"您当前正在直播,是否退出直播?") destructiveAction:^{
  188. FWStrongify(self)
  189. [self realExitLive:succ failed:failed];
  190. } cancelAction:^{
  191. // 音乐恢复 判断有局限性
  192. MUSIC_CENTER_MANAGER.musicPlayingState = YES;
  193. }];
  194. }
  195. else
  196. {
  197. [self realExitLive:succ failed:failed];
  198. }
  199. }
  200. #pragma mark 判断对应类型然后做对应的退出操作
  201. - (void)realExitLive:(FWVoidBlock)succ failed:(FWErrorBlock)failed
  202. {
  203. _iMMsgHandler.isExitRooming = YES;
  204. // 直接退出聊天组
  205. [self exitChatGroup];
  206. // 释放电话监听
  207. [self removePhoneListener];
  208. // 业务上退出直播:退出的时候分SDK退出和业务退出,减少退出等待时间
  209. [self onServiceExitLive:_isDirectCloseLive succ:succ failed:failed];
  210. }
  211. - (void)realExitLiveChatGroup
  212. {
  213. __weak BGIMMsgHandler *im = _iMMsgHandler;
  214. [[IMAPlatform sharedInstance] asyncExitAVChatRoom:self.liveItem succ:^{
  215. [im removeGroupChatListener];
  216. NSLog(@"直播间退出群:%@ 成功1",[self.liveItem liveIMChatRoomId]);
  217. } fail:^(int code, NSString *msg) {
  218. [im removeGroupChatListener];
  219. NSLog(@"直播间退出群:%@ 失败1,错误码:%d,错误原因:%@",[self.liveItem liveIMChatRoomId],code,msg);
  220. }];
  221. }
  222. #pragma mark 退出聊天组:观众退出聊天组前先发退出消息、主播直接退出(主播不用解散聊天组,服务端会做该操作)
  223. - (void)exitChatGroup
  224. {
  225. __weak typeof(self) ws = self;
  226. [ws realExitLiveChatGroup];
  227. if (!_isHost)
  228. {
  229. SendCustomMsgModel *sendCustomMsgModel = [[SendCustomMsgModel alloc] init];
  230. sendCustomMsgModel.msgType = MSG_VIEWER_QUIT;
  231. sendCustomMsgModel.chatGroupID = [self.liveItem liveIMChatRoomId];
  232. [_iMMsgHandler sendCustomGroupMsg:sendCustomMsgModel succ:^{
  233. } fail:^(int code, NSString *msg) {
  234. }];
  235. }
  236. else
  237. {
  238. }
  239. }
  240. #pragma mark - ----------------------- 模糊背景 -----------------------
  241. #pragma mark 进入直播间时的显示模糊背景
  242. - (void)vagueBackGround
  243. {
  244. _vagueImgView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
  245. if (_vagueImgUrl && ![_vagueImgUrl isEqualToString:@""])
  246. {
  247. [_vagueImgView sd_setImageWithURL:[NSURL URLWithString:_vagueImgUrl]];
  248. }
  249. else
  250. {
  251. [_vagueImgView setImage:[UIImage imageNamed:@"wel"]];
  252. }
  253. [self.view addSubview:_vagueImgView];
  254. [self.view bringSubviewToFront:_vagueImgView];
  255. UIBlurEffect *beffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
  256. UIVisualEffectView *view = [[UIVisualEffectView alloc]initWithEffect:beffect];
  257. view.frame = self.view.bounds;
  258. [_vagueImgView addSubview:view];
  259. }
  260. #pragma mark 视频第一帧加载出来后隐藏模糊背景
  261. - (void)hideVagueImgView
  262. {
  263. FWWeakify(self)
  264. [UIView animateWithDuration:0.2f animations:^{
  265. FWStrongify(self)
  266. self.vagueImgView.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
  267. self.vagueImgView.alpha = 0.f;
  268. } completion:^(BOOL finished) {
  269. FWStrongify(self)
  270. self.vagueImgView.hidden = YES;
  271. }];
  272. if (_isHost)
  273. {
  274. // 加载倒计时效果
  275. [CountDownView showCountDownViewInLiveVCwithFrame:CGRectMake(0, 0, 250, 250) inViewController:self block:nil];
  276. _hasShowVagueImg = YES;
  277. }
  278. }
  279. @end
  280. #pragma mark - BGLiveBaseController (ProtectedMethod) 供子类重写
  281. @implementation BGLiveBaseController (ProtectedMethod)
  282. #pragma mark 请求完接口后,刷新直播间相关信息
  283. - (void)refreshLiveItem:(id<FWShowLiveRoomAble>)liveItem liveInfo:(CurrentLiveInfo *)liveInfo
  284. {
  285. [self initCurrentLiveItem:liveItem];
  286. }
  287. #pragma mark - ----------------------- 进入、退出直播 -----------------------
  288. #pragma mark 加入聊天组成功
  289. - (void)enterChatGroupSucc:(CurrentLiveInfo *)liveInfo
  290. {
  291. [_iMMsgHandler setGroupChatListener:self.liveItem block:^(id selfPtr) {
  292. TCShowLiveListItem *liveRoom = (TCShowLiveListItem *)self.liveItem;
  293. if (![BGUtils isBlankString:liveInfo.group_id])
  294. {
  295. liveRoom.chatRoomId = liveInfo.group_id;
  296. }
  297. if ([BGUtils isBlankString:liveRoom.host.uid])
  298. {
  299. liveRoom.host.uid = liveInfo.podcast.user.user_id;
  300. }
  301. liveRoom.host.username = liveInfo.podcast.user.nick_name;
  302. liveRoom.host.avatar = liveInfo.podcast.user.head_image;
  303. self.liveItem = liveRoom;
  304. // 发送加入直播间消息
  305. if (!_isHost && (liveInfo.join_room_prompt == 1 || [[IMAPlatform sharedInstance].host getUserRank] >= self.BuguLive.appModel.jr_user_level))
  306. {
  307. SendCustomMsgModel *sendCustomMsgModel = [[SendCustomMsgModel alloc] init];
  308. sendCustomMsgModel.msgType = MSG_VIEWER_JOIN;
  309. sendCustomMsgModel.chatGroupID = [self.liveItem liveIMChatRoomId];
  310. sendCustomMsgModel.is_guardian = liveInfo.is_guardian;
  311. sendCustomMsgModel.noble_icon = liveInfo.noble_icon;
  312. sendCustomMsgModel.guardianModel = [GlobalVariables sharedInstance].guardianModel;
  313. // liveInfo.is_guardian;
  314. [_iMMsgHandler sendCustomGroupMsg:sendCustomMsgModel succ:nil fail:nil];
  315. }
  316. }];
  317. }
  318. #pragma mark 加入聊天组:为了防止加入聊天组出错的几率,所以这边做进入聊天失败的_enterChatGroupTimes次加入尝试
  319. - (void)startEnterChatGroup:(NSString *)chatGroupID succ:(FWVoidBlock)succ failed:(FWErrorBlock)failed
  320. {
  321. _hasEnterChatGroup = YES;
  322. if (![BGUtils isBlankString:chatGroupID])
  323. {
  324. [self.liveItem setLiveIMChatRoomId:chatGroupID];
  325. }
  326. // if ([BGUtils isBlankString:[self.liveItem liveIMChatRoomId]])
  327. // {
  328. // return;
  329. // }
  330. FWWeakify(self)
  331. [[IMAPlatform sharedInstance] asyncEnterAVChatRoom:self.liveItem isHost:_isReEnterChatGroup ? NO : _isHost succ:^(id<AVRoomAble> room) {
  332. FWStrongify(self)
  333. if (self.liveInfo)
  334. {
  335. [self enterChatGroupSucc:self.liveInfo];
  336. }
  337. [self.liveItem setLiveIMChatRoomId:[room liveIMChatRoomId]];
  338. [self addPhoneListener];
  339. [self performSelector:@selector(addNetListener) withObject:nil afterDelay:3];
  340. if (succ)
  341. {
  342. succ();
  343. }
  344. } fail:^(int code, NSString *msg) {
  345. FWStrongify(self)
  346. self.enterChatGroupTimes --;
  347. if (self.enterChatGroupTimes)
  348. {
  349. [self startEnterChatGroup:@"" succ:succ failed:failed];
  350. }
  351. else
  352. {
  353. if (failed)
  354. {
  355. failed(code, msg);
  356. }
  357. [BGHUDHelper alert:ASLocalizedString(@"加入聊天室失败,请稍候尝试") action:^{
  358. // [self onExitLiveUI];
  359. }];
  360. DebugLog(@"=========加入直播聊天室失败 code: %d , msg = %@", code, msg);
  361. }
  362. }];
  363. }
  364. #pragma mark 业务上退出直播:退出的时候分SDK退出和业务退出,减少退出等待时间
  365. - (void)onServiceExitLive:(BOOL)isDirectCloseLive succ:(FWVoidBlock)succ failed:(FWErrorBlock)failed
  366. {
  367. // 供子类重写
  368. }
  369. #pragma mark 退出直播界面
  370. - (void)onExitLiveUI
  371. {
  372. _iMMsgHandler.isExitRooming = NO;
  373. _iMMsgHandler.isEnterRooming = NO;
  374. self.BuguLive.liveState = nil;
  375. [[NSNotificationCenter defaultCenter] removeObserver:self];
  376. AVAudioSession *aSession = [AVAudioSession sharedInstance];
  377. [aSession setMode:_audioSesstionMode error:nil];
  378. // 用于控制自动锁屏
  379. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
  380. // 参数也处理
  381. [SuspenionWindow resetSusWindowPramaWhenLiveClosedComplete:nil];
  382. }
  383. #pragma mark - ----------------------- 网络、电话、进入前后台监听 -----------------------
  384. #pragma mark 加入直播前先判断网络环境
  385. - (void)checkNetWorkBeforeLive
  386. {
  387. __weak typeof(self) ws = self;
  388. __weak BGIMMsgHandler *msgHandler = _iMMsgHandler;
  389. switch ([AppDelegate sharedAppDelegate].reachabilityStatus)
  390. {
  391. case AFNetworkReachabilityStatusReachableViaWWAN:
  392. {
  393. [self addAVSDKObservers];
  394. //#if TARGET_IPHONE_SIMULATOR
  395. //#else
  396. msgHandler.isEnterRooming = YES;
  397. [ws startEnterChatGroup:@"" succ:nil failed:nil];
  398. // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  399. //
  400. //
  401. // NSString *ac = _isHost ?ASLocalizedString( @"创建") :ASLocalizedString( @"加入");
  402. // NSString *tip = [NSString stringWithFormat:ASLocalizedString(@"当前是移动网络,是否继续%@直播?"), ac];
  403. //
  404. // FWWeakify(self)
  405. // [FanweMessage alert:ASLocalizedString(@"网络提示") message:tip destructiveAction:^{
  406. //
  407. // FWStrongify(self)
  408. //
  409. // [self addAVSDKObservers];
  410. //
  411. ////#if TARGET_IPHONE_SIMULATOR
  412. ////#else
  413. // msgHandler.isEnterRooming = YES;
  414. // [ws startEnterChatGroup:@"" succ:nil failed:nil];
  415. ////#endif
  416. //
  417. // } cancelAction:^{
  418. //
  419. // FWStrongify(self)
  420. //
  421. // [self tipMessage:ASLocalizedString(@"退出成功") delay:2 completion:^{
  422. // [ws onExitLiveUI];
  423. // }];
  424. //
  425. // }];
  426. // });
  427. }
  428. break;
  429. case AFNetworkReachabilityStatusReachableViaWiFi:
  430. {
  431. [self addAVSDKObservers];
  432. //#if TARGET_IPHONE_SIMULATOR
  433. //#else
  434. msgHandler.isEnterRooming = YES;
  435. [ws startEnterChatGroup:@"" succ:nil failed:nil];
  436. //#endif
  437. }
  438. break;
  439. case AFNetworkReachabilityStatusUnknown:
  440. case AFNetworkReachabilityStatusNotReachable:
  441. default:
  442. {
  443. // 当前无网络
  444. NSString *tip = [NSString stringWithFormat:ASLocalizedString(@"当前无网络,无法%@直播"), _isHost ?ASLocalizedString( @"创建") :ASLocalizedString( @"加入")];
  445. [self tipMessage:tip delay:2 completion:^{
  446. [self onExitLiveUI];
  447. }];
  448. }
  449. break;
  450. }
  451. }
  452. #pragma mark 监听网络
  453. - (void)addNetListener
  454. {
  455. [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(ReachabilityDidChange:) name:AFNetworkingReachabilityDidChangeNotification object:nil];
  456. }
  457. - (void)ReachabilityDidChange:(NSNotification *)not
  458. {
  459. __weak typeof(self) ws = self;
  460. NSDictionary *userInfo = not.userInfo;
  461. AFNetworkReachabilityStatus reachabilityStatus = [userInfo[AFNetworkingReachabilityNotificationStatusItem] integerValue];
  462. switch (reachabilityStatus)
  463. {
  464. case AFNetworkReachabilityStatusReachableViaWWAN:
  465. {
  466. if (_isHost)
  467. {
  468. // 变成移动网络
  469. // FWWeakify(self)
  470. // [FanweMessage alert:nil message:ASLocalizedString(@"当前是移动网络,是否继续直播?") destructiveAction:^{
  471. //
  472. // } cancelAction:^{
  473. //
  474. // FWStrongify(self)
  475. //
  476. // [self alertExitLive:NO isHostShowAlert:NO succ:nil failed:nil];
  477. //
  478. // }];
  479. }
  480. else
  481. {
  482. // 网络变差
  483. FWWeakify(self)
  484. // [FanweMessage alert:nil message:ASLocalizedString(@"当前是移动网络,是否继续观看直播?") destructiveAction:^{
  485. //
  486. // } cancelAction:^{
  487. //
  488. // FWStrongify(self)
  489. //
  490. // [self alertExitLive:NO isHostShowAlert:NO succ:nil failed:nil];
  491. //
  492. // }];
  493. }
  494. }
  495. break;
  496. case AFNetworkReachabilityStatusReachableViaWiFi:
  497. {
  498. // 网络变好,不处理
  499. }
  500. break;
  501. case AFNetworkReachabilityStatusUnknown:
  502. case AFNetworkReachabilityStatusNotReachable:
  503. default:
  504. {
  505. // 网络不可用
  506. [FanweMessage alert:[NSString stringWithFormat:ASLocalizedString(@"当前无网络,无法继续%@直播!"), _isHost ? @"" :ASLocalizedString( @"观看")]];
  507. }
  508. break;
  509. }
  510. }
  511. #pragma mark 添加电话监听: 进入直播成功后监听
  512. - (void)addPhoneListener
  513. {
  514. if (!_callCenter)
  515. {
  516. _callCenter = [[CTCallCenter alloc] init];
  517. __weak BGLiveBaseController *ws = self;
  518. _callCenter.callEventHandler = ^(CTCall *call) {
  519. // 需要在主线程执行
  520. [ws performSelectorOnMainThread:@selector(handlePhostEvent:) withObject:call waitUntilDone:YES];
  521. };
  522. }
  523. }
  524. #pragma mark 移除电话监听:退出直播后监听
  525. - (void)removePhoneListener
  526. {
  527. _callCenter.callEventHandler = nil;
  528. _callCenter = nil;
  529. }
  530. - (void)handlePhostEvent:(CTCall *)call
  531. {
  532. DebugLog(@"电话中断处理:电话状态为call.callState = %@", call.callState);
  533. if ([call.callState isEqualToString:CTCallStateDisconnected])
  534. {
  535. // 电话已结束
  536. if (_hasHandleCall)
  537. {
  538. // 说明在前的时候接通过电话
  539. DebugLog(@"电话中断处理:在前如的时候处理的电话,挂断后,立即回到前台");
  540. [self phoneInterruptioning:NO];
  541. }
  542. else
  543. {
  544. DebugLog(@"电话中断处理:退到后台接话:不处理");
  545. }
  546. }
  547. else
  548. {
  549. if (!_isPhoneInterupt && _isAtForeground)
  550. {
  551. DebugLog(@"电话中断处理:退到后台接话:不处理");
  552. // 首次收到,并且在前台
  553. _isPhoneInterupt = YES;
  554. _hasHandleCall = YES;
  555. [self phoneInterruptioning:YES];
  556. }
  557. else
  558. {
  559. DebugLog(@"电话中断处理:已在后台接电话话:不处理");
  560. }
  561. }
  562. }
  563. #pragma mark 视频是否需要中断
  564. - (void)isInterruptioning:(BOOL)interruptioning
  565. {
  566. if (interruptioning)
  567. {
  568. [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
  569. }];
  570. if (_isAtForeground)
  571. {
  572. _isAtForeground = NO;
  573. _backGroundTime = [[NSDate date] timeIntervalSince1970];
  574. if (_liveType == FW_LIVE_TYPE_HOST) // 主播
  575. {
  576. SendCustomMsgModel *sendCustomMsgModel = [[SendCustomMsgModel alloc] init];
  577. sendCustomMsgModel.msgType = MSG_ANCHOR_LEAVE;
  578. sendCustomMsgModel.msg =ASLocalizedString( @"主播离开一下,精彩不中断,不要走开哦");
  579. sendCustomMsgModel.chatGroupID = [self.liveItem liveIMChatRoomId];
  580. [_iMMsgHandler sendCustomGroupMsg:sendCustomMsgModel succ:nil fail:nil];
  581. }
  582. }
  583. }
  584. else
  585. {
  586. if (!_isAtForeground)
  587. {
  588. _isAtForeground = YES;
  589. _foreGroundTime = [[NSDate date] timeIntervalSince1970];
  590. if (_liveType == FW_LIVE_TYPE_HOST) // 主播
  591. {
  592. [self hostBackTip];
  593. }
  594. }
  595. }
  596. }
  597. #pragma mark app进入前台
  598. - (void)onAppEnterForeground
  599. {
  600. [self isInterruptioning:NO];
  601. }
  602. #pragma mark app进入后台
  603. - (void)onAppEnterBackground
  604. {
  605. [self isInterruptioning:YES];
  606. }
  607. #pragma mark 是否正在被电话打断
  608. - (void)phoneInterruptioning:(BOOL)interruptioning
  609. {
  610. [self isInterruptioning:interruptioning];
  611. if (!interruptioning)
  612. {
  613. _hasHandleCall = NO;
  614. _isPhoneInterupt = NO;
  615. }
  616. }
  617. #pragma mark 声音打断监听
  618. - (void)onAudioInterruption:(NSNotification *)notification
  619. {
  620. NSDictionary *interuptionDict = notification.userInfo;
  621. NSNumber* interuptionType = [interuptionDict valueForKey:AVAudioSessionInterruptionTypeKey];
  622. if(interuptionType.intValue == AVAudioSessionInterruptionTypeBegan)
  623. {
  624. DebugLog(@"初中断");
  625. }
  626. else if (interuptionType.intValue == AVAudioSessionInterruptionTypeEnded)
  627. {
  628. // siri输入
  629. [[AVAudioSession sharedInstance] setActive:YES error: nil];
  630. }
  631. }
  632. #pragma mark 关注和取消关注要做UI处理以及关注做IM发通知
  633. - (void)isShowFollow:(NSNotification *)notification
  634. {
  635. }
  636. #pragma mark 监听耳机插入和拔出
  637. - (void)audioRouteChangeListenerCallback:(NSNotification*)notification
  638. {
  639. // 供子类重写
  640. }
  641. - (void)tipMessage:(NSString *)msg delay:(CGFloat)seconds completion:(void (^)())completion
  642. {
  643. [[BGHUDHelper sharedInstance] tipMessage:msg delay:seconds completion:completion];
  644. }
  645. - (UIImageView *)otherPushBgView{
  646. if (!_otherPushBgView) {
  647. _otherPushBgView = [[UIImageView alloc]initWithFrame:self.view.bounds];
  648. _otherPushBgView.image = [UIImage imageNamed:@"外设直播_背景图"];
  649. _otherPushBgView.contentMode = UIViewContentModeScaleAspectFill;
  650. }
  651. return _otherPushBgView;
  652. }
  653. - (UILabel *)otherPushLabel{
  654. if (!_otherPushLabel) {
  655. _otherPushLabel = [[UILabel alloc]initWithFrame:self.view.bounds];
  656. _otherPushLabel.text =ASLocalizedString( @"其他设备推流中");
  657. _otherPushLabel.textColor = kWhiteColor;
  658. _otherPushLabel.font = [UIFont systemFontOfSize:18];
  659. _otherPushLabel.textAlignment = NSTextAlignmentCenter;
  660. }
  661. return _otherPushLabel;
  662. }
  663. @end