// // NTESNotificationCenter.m // NIM // // Created by Xuhui on 15/3/25. // Copyright (c) 2015年 Netease. All rights reserved. // #import "NTESNotificationCenter.h" #import "NTESVideoChatViewController.h" #import "NTESAudioChatViewController.h" //#import "NTESMainTabController.h" //#import "NTESSessionViewController.h" #import "IfishSessionViewController.h" #import "IfishMianTabViewController.h" #import "NSDictionary+NTESJson.h" #import "NTESCustomNotificationDB.h" #import "NTESCustomNotificationObject.h" #import "Toast+UIView.h" #import "NTESWhiteboardViewController.h" #import "NTESCustomSysNotificationSender.h" #import "NTESGlobalMacro.h" #import #import "NTESLiveViewController.h" #import "NTESSessionMsgConverter.h" #import "NTESSessionUtil.h" NSString *NTESCustomNotificationCountChanged = @"NTESCustomNotificationCountChanged"; @interface NTESNotificationCenter () @property (nonatomic,strong) AVAudioPlayer *player; //播放提示音 @end @implementation NTESNotificationCenter + (instancetype)sharedCenter { static NTESNotificationCenter *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[NTESNotificationCenter alloc] init]; }); return instance; } - (void)start { } - (instancetype)init { self = [super init]; if(self) { NSURL *url = [[NSBundle mainBundle] URLForResource:@"message" withExtension:@"wav"]; _player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [[NIMSDK sharedSDK].systemNotificationManager addDelegate:self]; [[NIMAVChatSDK sharedSDK].netCallManager addDelegate:self]; [[NIMAVChatSDK sharedSDK].rtsManager addDelegate:self]; [[NIMSDK sharedSDK].chatManager addDelegate:self]; } return self; } - (void)dealloc{ [[NIMSDK sharedSDK].systemNotificationManager removeDelegate:self]; [[NIMAVChatSDK sharedSDK].netCallManager removeDelegate:self]; [[NIMAVChatSDK sharedSDK].rtsManager removeDelegate:self]; [[NIMSDK sharedSDK].chatManager removeDelegate:self]; } #pragma mark - NIMChatManagerDelegate - (void)onRecvMessages:(NSArray *)messages { static BOOL isPlaying = NO; if (isPlaying) { return; } isPlaying = YES; [self playMessageAudioTip]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ isPlaying = NO; }); } - (void)playMessageAudioTip { UINavigationController *nav = [IfishMianTabViewController instance].selectedViewController; BOOL needPlay = YES; for (UIViewController *vc in nav.viewControllers) { if ([vc isKindOfClass:[NIMSessionViewController class]] || [vc isKindOfClass:[NTESLiveViewController class]]) { needPlay = NO; break; } } if (needPlay) { [self.player stop]; [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error:nil]; [self.player play]; } } - (void)onMessageRevoked:(NIMMessage *)message { NIMMessage *tip = [NTESSessionMsgConverter msgWithTip:[NTESSessionUtil tipOnMessageRevoked:message]]; NIMMessageSetting *setting = [[NIMMessageSetting alloc] init]; setting.shouldBeCounted = NO; tip.setting = setting; IfishMianTabViewController *tabVC = [IfishMianTabViewController instance]; UINavigationController *nav = tabVC.selectedViewController; for (IfishSessionViewController *vc in nav.viewControllers) { if ([vc isKindOfClass:[IfishSessionViewController class]] && [vc.session.sessionId isEqualToString:message.session.sessionId]) { NIMMessageModel *model = [vc uiDeleteMessage:message]; tip.timestamp = model.messageTime; [vc uiAddMessages:@[tip]]; break; } } tip.timestamp = message.timestamp; // saveMessage 方法执行成功后会触发 onRecvMessages: 回调,但是这个回调上来的 NIMMessage 时间为服务器时间,和界面上的时间有一定出入,所以要提前先在界面上插入一个和被删消息的界面时间相符的 Tip, 当触发 onRecvMessages: 回调时,组件判断这条消息已经被插入过了,就会忽略掉。 [[NIMSDK sharedSDK].conversationManager saveMessage:tip forSession:message.session completion:nil]; } #pragma mark - NIMSystemNotificationManagerDelegate - (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification{ NSString *content = notification.content; NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding]; if (data) { NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; if ([dict isKindOfClass:[NSDictionary class]]) { if ([dict jsonInteger:NTESNotifyID] == NTESCustom) { //SDK并不会存储自定义的系统通知,需要上层结合业务逻辑考虑是否做存储。这里给出一个存储的例子。 NTESCustomNotificationObject *object = [[NTESCustomNotificationObject alloc] initWithNotification:notification]; //这里只负责存储可离线的自定义通知,推荐上层应用也这么处理,需要持久化的通知都走可离线通知 if (!notification.sendToOnlineUsersOnly) { [[NTESCustomNotificationDB sharedInstance] saveNotification:object]; } if (notification.setting.shouldBeCounted) { [[NSNotificationCenter defaultCenter] postNotificationName:NTESCustomNotificationCountChanged object:nil]; } NSString *content = [dict jsonString:NTESCustomContent]; [[IfishMianTabViewController instance].selectedViewController.view makeToast:content]; } } } } #pragma mark - NIMNetCallManagerDelegate - (void)onReceive:(UInt64)callID from:(NSString *)caller type:(NIMNetCallType)type message:(NSString *)extendMessage{ IfishMianTabViewController *tabVC = [IfishMianTabViewController instance]; [tabVC.view endEditing:YES]; UINavigationController *nav = tabVC.selectedViewController; if ([self shouldResponseBusy]){ [[NIMAVChatSDK sharedSDK].netCallManager control:callID type:NIMNetCallControlTypeBusyLine]; } else { UIViewController *vc; switch (type) { case NIMNetCallTypeVideo:{ vc = [[NTESVideoChatViewController alloc] initWithCaller:caller callId:callID]; } break; case NIMNetCallTypeAudio:{ vc = [[NTESAudioChatViewController alloc] initWithCaller:caller callId:callID]; } break; default: break; } if (!vc) { return; } //由于音视频聊天里头有音频和视频聊天界面的切换,直接用present的话页面过渡会不太自然,这里还是用push,然后做出present的效果 CATransition *transition = [CATransition animation]; transition.duration = 0.25; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromTop; transition.delegate = self; [nav.view.layer addAnimation:transition forKey:nil]; nav.navigationBarHidden = YES; [nav pushViewController:vc animated:NO]; } } - (void)onRTSRequest:(NSString *)sessionID from:(NSString *)caller services:(NSUInteger)types message:(NSString *)info { IfishMianTabViewController *tabVC = [IfishMianTabViewController instance]; [tabVC.view endEditing:YES]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if ([self shouldResponseBusy]) { [[NIMAVChatSDK sharedSDK].rtsManager responseRTS:sessionID accept:NO option:nil completion:nil]; } else { NTESWhiteboardViewController *vc = [[NTESWhiteboardViewController alloc] initWithSessionID:sessionID peerID:caller types:types info:info]; if (tabVC.presentedViewController) { __weak IfishMianTabViewController *wtabVC = (IfishMianTabViewController *)tabVC; [tabVC.presentedViewController dismissViewControllerAnimated:NO completion:^{ [wtabVC presentViewController:vc animated:NO completion:nil]; }]; }else{ [tabVC presentViewController:vc animated:NO completion:nil]; } } }); } - (BOOL)shouldResponseBusy { IfishMianTabViewController *tabVC = [IfishMianTabViewController instance]; UINavigationController *nav = tabVC.selectedViewController; return [nav.topViewController isKindOfClass:[NTESNetChatViewController class]] || [tabVC.presentedViewController isKindOfClass:[NTESWhiteboardViewController class]]; } @end