NTESNotificationCenter.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //
  2. // NTESNotificationCenter.m
  3. // NIM
  4. //
  5. // Created by Xuhui on 15/3/25.
  6. // Copyright (c) 2015年 Netease. All rights reserved.
  7. //
  8. #import "NTESNotificationCenter.h"
  9. #import "NTESVideoChatViewController.h"
  10. //#import "NTESAudioChatViewController.h"
  11. //#import "NTESMainTabController.h"
  12. #import "MessageViewController.h"
  13. #import "NSDictionary+NTESJson.h"
  14. //#import "NTESCustomNotificationDB.h"
  15. //#import "NTESCustomNotificationObject.h"
  16. //#import "UIView+Toast.h"
  17. //#import "NTESWhiteboardViewController.h"
  18. //#import "NTESCustomSysNotificationSender.h"
  19. //#import "NTESGlobalMacro.h"
  20. #import <AVFoundation/AVFoundation.h>
  21. //#import "NTESLiveViewController.h"
  22. //#import "NTESSessionMsgConverter.h"
  23. #import "NTESSessionUtil.h"
  24. #import "NTESAVNotifier.h"
  25. //#import "NTESRedPacketTipAttachment.h"
  26. #import "ModelRootViewController.h"
  27. #import "MessageViewController.h"
  28. #import "NTESNetChatViewController.h"
  29. NSString *NTESCustomNotificationCountChanged = @"NTESCustomNotificationCountChanged";
  30. @interface NTESNotificationCenter () <NIMSystemNotificationManagerDelegate, NIMNetCallManagerDelegate,
  31. NIMRTSManagerDelegate, NIMChatManagerDelegate, NIMBroadcastManagerDelegate>
  32. @property(nonatomic, strong) AVAudioPlayer *player; //播放提示音
  33. @property(nonatomic, strong) NTESAVNotifier *notifier;
  34. @end
  35. @implementation NTESNotificationCenter
  36. + (instancetype)sharedCenter {
  37. static NTESNotificationCenter *instance = nil;
  38. static dispatch_once_t onceToken;
  39. dispatch_once(&onceToken, ^{
  40. instance = [[NTESNotificationCenter alloc] init];
  41. });
  42. return instance;
  43. }
  44. - (void)start {
  45. NSLog(@"Notification Center Setup");
  46. }
  47. - (instancetype)init {
  48. self = [super init];
  49. if (self) {
  50. NSURL *url = [[NSBundle mainBundle] URLForResource:@"message" withExtension:@"wav"];
  51. _player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
  52. _notifier = [[NTESAVNotifier alloc] init];
  53. [[NIMSDK sharedSDK].systemNotificationManager addDelegate:self];
  54. [[NIMAVChatSDK sharedSDK].netCallManager addDelegate:self];
  55. [[NIMAVChatSDK sharedSDK].rtsManager addDelegate:self];
  56. [[NIMSDK sharedSDK].chatManager addDelegate:self];
  57. [[NIMSDK sharedSDK].broadcastManager addDelegate:self];
  58. }
  59. return self;
  60. }
  61. - (void)dealloc {
  62. [[NIMSDK sharedSDK].systemNotificationManager removeDelegate:self];
  63. [[NIMAVChatSDK sharedSDK].netCallManager removeDelegate:self];
  64. [[NIMAVChatSDK sharedSDK].rtsManager removeDelegate:self];
  65. [[NIMSDK sharedSDK].chatManager removeDelegate:self];
  66. [[NIMSDK sharedSDK].broadcastManager removeDelegate:self];
  67. }
  68. #pragma mark - NIMChatManagerDelegate
  69. - (void)onRecvMessages:(NSArray *)recvMessages {
  70. NSArray *messages = [self filterMessages:recvMessages];
  71. if (messages.count) {
  72. static BOOL isPlaying = NO;
  73. if (isPlaying) {
  74. return;
  75. }
  76. isPlaying = YES;
  77. [self playMessageAudioTip];
  78. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  79. isPlaying = NO;
  80. });
  81. [self checkMessageAt:messages];
  82. }
  83. }
  84. - (void)playMessageAudioTip {
  85. UINavigationController *nav = [ModelRootViewController instance].selectedViewController;
  86. BOOL needPlay = YES;
  87. for (UIViewController *vc in nav.viewControllers) {
  88. if ([vc isKindOfClass:[MessageViewController class]] || [vc isKindOfClass:[NTESNetChatViewController class]]) {
  89. needPlay = NO;
  90. break;
  91. }
  92. }
  93. if (needPlay) {
  94. [self.player stop];
  95. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
  96. [self.player play];
  97. }
  98. }
  99. - (void)checkMessageAt:(NSArray<NIMMessage *> *)messages {
  100. //一定是同个 session 的消息
  101. NIMSession *session = [messages.firstObject session];
  102. if ([self.currentSessionViewController.session isEqual:session]) {
  103. //只有在@所属会话页外面才需要标记有人@你
  104. return;
  105. }
  106. NSString *me = [[NIMSDK sharedSDK].loginManager currentAccount];
  107. for (NIMMessage *message in messages) {
  108. if ([message.apnsMemberOption.userIds containsObject:me]) {
  109. [NTESSessionUtil addRecentSessionMark:session type:NTESRecentSessionMarkTypeAt];
  110. return;
  111. }
  112. }
  113. }
  114. - (NSArray *)filterMessages:(NSArray *)messages {
  115. NSMutableArray *array = [[NSMutableArray alloc] init];
  116. for (NIMMessage *message in messages) {
  117. // if ([self checkRedPacketTip:message] && ![self canSaveMessageRedPacketTip:message])
  118. // {
  119. // [[NIMSDK sharedSDK].conversationManager deleteMessage:message];
  120. // [self.currentSessionViewController uiDeleteMessage:message];
  121. // continue;
  122. // }
  123. [array addObject:message];
  124. }
  125. return [NSArray arrayWithArray:array];
  126. }
  127. //- (BOOL)checkRedPacketTip:(NIMMessage *)message
  128. //{
  129. // NIMCustomObject *object = message.messageObject;
  130. // if ([object isKindOfClass:[NIMCustomObject class]] && [object.attachment isKindOfClass:[NTESRedPacketTipAttachment class]])
  131. // {
  132. // return YES;
  133. // }
  134. // return NO;
  135. //}
  136. //
  137. //- (BOOL)canSaveMessageRedPacketTip:(NIMMessage *)message
  138. //{
  139. // NIMCustomObject *object = message.messageObject;
  140. // NTESRedPacketTipAttachment *attach = (NTESRedPacketTipAttachment *)object.attachment;
  141. // NSString *me = [NIMSDK sharedSDK].loginManager.currentAccount;
  142. // return [attach.sendPacketId isEqualToString:me] || [attach.openPacketId isEqualToString:me];
  143. //}
  144. //- (void)onRecvRevokeMessageNotification:(NIMRevokeMessageNotification *)notification
  145. //{
  146. // NIMMessage *tipMessage = [NTESSessionMsgConverter msgWithTip:[NTESSessionUtil tipOnMessageRevoked:notification]];
  147. // NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
  148. // setting.shouldBeCounted = NO;
  149. // tipMessage.setting = setting;
  150. // tipMessage.timestamp = notification.timestamp;
  151. //
  152. // NTESMainTabController *tabVC = [NTESMainTabController instance];
  153. // UINavigationController *nav = tabVC.selectedViewController;
  154. //
  155. // for (NTESSessionViewController *vc in nav.viewControllers) {
  156. // if ([vc isKindOfClass:[NTESSessionViewController class]]
  157. // && [vc.session.sessionId isEqualToString:notification.session.sessionId]) {
  158. // NIMMessageModel *model = [vc uiDeleteMessage:notification.message];
  159. // if (model) {
  160. // [vc uiInsertMessages:@[tipMessage]];
  161. // }
  162. // break;
  163. // }
  164. // }
  165. //
  166. // // saveMessage 方法执行成功后会触发 onRecvMessages: 回调,但是这个回调上来的 NIMMessage 时间为服务器时间,和界面上的时间有一定出入,所以要提前先在界面上插入一个和被删消息的界面时间相符的 Tip, 当触发 onRecvMessages: 回调时,组件判断这条消息已经被插入过了,就会忽略掉。
  167. // [[NIMSDK sharedSDK].conversationManager saveMessage:tipMessage
  168. // forSession:notification.session
  169. // completion:nil];
  170. //}
  171. #pragma mark - NIMSystemNotificationManagerDelegate
  172. - (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification {
  173. NSString *content = notification.content;
  174. if ([content isEqualToString:@"恭喜,您有新的订单"]) {
  175. NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
  176. [[NSNotificationCenter defaultCenter] postNotificationName:NTESCustomNotificationCountChanged object:nil];
  177. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"订单消息"
  178. message:content
  179. delegate:self
  180. cancelButtonTitle:nil
  181. otherButtonTitles:@"去查看", nil];
  182. [alert show];
  183. }
  184. // if (data)
  185. // {
  186. //
  187. // NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
  188. // options:0
  189. // error:nil];
  190. // if ([dict isKindOfClass:[NSDictionary class]])
  191. // {
  192. // switch ([dict jsonInteger:@"id"]) {
  193. // case NTESCustom:{
  194. // //SDK并不会存储自定义的系统通知,需要上层结合业务逻辑考虑是否做存储。这里给出一个存储的例子。
  195. // NTESCustomNotificationObject *object = [[NTESCustomNotificationObject alloc] initWithNotification:notification];
  196. // //这里只负责存储可离线的自定义通知,推荐上层应用也这么处理,需要持久化的通知都走可离线通知
  197. // if (!notification.sendToOnlineUsersOnly) {
  198. // [[NTESCustomNotificationDB sharedInstance] saveNotification:object];
  199. // }
  200. // if (notification.setting.shouldBeCounted) {
  201. // [[NSNotificationCenter defaultCenter] postNotificationName:NTESCustomNotificationCountChanged object:nil];
  202. // }
  203. // NSString *content = [dict jsonString:NTESCustomContent];
  204. // [self makeToast:content];
  205. // }
  206. // break;
  207. // case NTESTeamMeetingCall:{
  208. // if (![self shouldResponseBusy]) {
  209. // //繁忙的话,不回复任何信息,直接丢掉,让呼叫方直接走超时
  210. // NSTimeInterval sendTime = notification.timestamp;
  211. // NSTimeInterval nowTime = [[NSDate date] timeIntervalSince1970];
  212. // if (nowTime - sendTime < 45)
  213. // {
  214. // //60 秒内,认为有效,否则丢弃
  215. // NTESTeamMeetingCalleeInfo *info = [[NTESTeamMeetingCalleeInfo alloc] init];
  216. // info.teamId = [dict jsonString:NTESTeamMeetingTeamId];
  217. // info.members = [dict jsonArray:NTESTeamMeetingMembers];
  218. // info.meetingName = [dict jsonString:NTESTeamMeetingName];
  219. // info.teamName = [dict jsonString:NTESTeamMeetingTeamName];
  220. //
  221. // NTESTeamMeetingCallingViewController *vc = [[NTESTeamMeetingCallingViewController alloc] initWithCalleeInfo:info];
  222. // [self presentModelViewController:vc];
  223. // }
  224. // }
  225. // }
  226. // break;
  227. // default:
  228. // break;
  229. // }
  230. // }
  231. // }
  232. }
  233. #pragma mark - NIMNetCallManagerDelegate
  234. - (void)onReceive:(UInt64)callID from:(NSString *)caller type:(NIMNetCallMediaType)type message:(NSString *)extendMessage {
  235. ModelRootViewController *tabVC = [ModelRootViewController instance];
  236. [tabVC.view endEditing:YES];
  237. UINavigationController *nav = tabVC.selectedViewController;
  238. if ([self shouldResponseBusy]) {
  239. [[NIMAVChatSDK sharedSDK].netCallManager control:callID type:NIMNetCallControlTypeBusyLine];
  240. } else {
  241. if ([self shouldFireNotification:caller]) {
  242. NSString *text = [self textByCaller:caller type:type];
  243. [_notifier start:text];
  244. }
  245. UIViewController *vc;
  246. switch (type) {
  247. case NIMNetCallTypeVideo: {
  248. vc = [[NTESVideoChatViewController alloc] initWithCaller:caller callId:callID];
  249. break;
  250. }
  251. case NIMNetCallTypeAudio: {
  252. // vc = [[NTESAudioChatViewController alloc] initWithCaller:caller callId:callID];
  253. break;
  254. }
  255. default:
  256. break;
  257. }
  258. if (!vc) {
  259. return;
  260. }
  261. [nav presentViewController:vc animated:YES completion:nil];
  262. }
  263. }
  264. - (void)onHangup:(UInt64)callID
  265. by:(NSString *)user {
  266. [_notifier stop];
  267. }
  268. //- (void)onRTSRequest:(NSString *)sessionID
  269. // from:(NSString *)caller
  270. // services:(NSUInteger)types
  271. // message:(NSString *)info
  272. //{
  273. // if ([self shouldResponseBusy]) {
  274. // [[NIMAVChatSDK sharedSDK].rtsManager responseRTS:sessionID accept:NO option:nil completion:nil];
  275. // }
  276. // else {
  277. //
  278. // if ([self shouldFireNotification:caller]) {
  279. // NSString *text = [self textByCaller:caller];
  280. // [_notifier start:text];
  281. // }
  282. // NTESWhiteboardViewController *vc = [[NTESWhiteboardViewController alloc] initWithSessionID:sessionID
  283. // peerID:caller
  284. // types:types
  285. // info:info];
  286. // [self presentModelViewController:vc];
  287. // }
  288. //}
  289. //- (void)presentModelViewController:(UIViewController *)vc
  290. //{
  291. // NTESMainTabController *tab = [NTESMainTabController instance];
  292. // [tab.view endEditing:YES];
  293. // if (tab.presentedViewController) {
  294. // __weak NTESMainTabController *wtabVC = tab;
  295. // [tab.presentedViewController dismissViewControllerAnimated:NO completion:^{
  296. // [wtabVC presentViewController:vc animated:NO completion:nil];
  297. // }];
  298. // }else{
  299. // [tab presentViewController:vc animated:NO completion:nil];
  300. // }
  301. //}
  302. - (void)onRTSTerminate:(NSString *)sessionID
  303. by:(NSString *)user {
  304. [_notifier stop];
  305. }
  306. - (BOOL)shouldResponseBusy {
  307. ModelRootViewController *tabVC = [ModelRootViewController instance];
  308. UINavigationController *nav = tabVC.selectedViewController;
  309. return [nav.topViewController isKindOfClass:[NTESNetChatViewController class]];
  310. // ||
  311. // [tabVC.presentedViewController isKindOfClass:[NTESWhiteboardViewController class]] ||
  312. // [tabVC.presentedViewController isKindOfClass:[NTESTeamMeetingCallingViewController class]] ||
  313. // [tabVC.presentedViewController isKindOfClass:[NTESTeamMeetingViewController class]];
  314. }
  315. #pragma mark - NIMBroadcastManagerDelegate
  316. //- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage
  317. //{
  318. // [self makeToast:broadcastMessage.content];
  319. //}
  320. #pragma mark - format
  321. - (NSString *)textByCaller:(NSString *)caller type:(NIMNetCallMediaType)type {
  322. NSString *action = type == NIMNetCallMediaTypeAudio ? @"音频" : @"视频";
  323. NSString *text = [NSString stringWithFormat:@"你收到了一个%@聊天请求", action];
  324. NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:caller option:nil];
  325. if ([info.showName length]) {
  326. text = [NSString stringWithFormat:@"%@向你发起了一个%@聊天请求", info.showName, action];
  327. }
  328. return text;
  329. }
  330. //- (NSString *)textByCaller:(NSString *)caller
  331. //{
  332. // NSString *text = @"你收到了一个白板请求";
  333. // NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:caller option:nil];
  334. // if ([info.showName length])
  335. // {
  336. // text = [NSString stringWithFormat:@"%@向你发起了一个白板请求",info.showName];
  337. // }
  338. // return text;
  339. //}
  340. - (BOOL)shouldFireNotification:(NSString *)callerId {
  341. //退后台后 APP 存活,然后收到通知
  342. BOOL should = YES;
  343. //消息不提醒
  344. id <NIMUserManager> userManager = [[NIMSDK sharedSDK] userManager];
  345. if (![userManager notifyForNewMsg:callerId]) {
  346. should = NO;
  347. }
  348. //当前在正处于免打扰
  349. id <NIMApnsManager> apnsManager = [[NIMSDK sharedSDK] apnsManager];
  350. NIMPushNotificationSetting *setting = [apnsManager currentSetting];
  351. if (setting.noDisturbing) {
  352. NSDate *date = [NSDate date];
  353. NSCalendar *calendar = [NSCalendar currentCalendar];
  354. NSDateComponents *components = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:date];
  355. NSInteger now = components.hour * 60 + components.minute;
  356. NSInteger start = setting.noDisturbingStartH * 60 + setting.noDisturbingStartM;
  357. NSInteger end = setting.noDisturbingEndH * 60 + setting.noDisturbingEndM;
  358. //当天区间
  359. if (end > start && end >= now && now >= start) {
  360. should = NO;
  361. }
  362. //隔天区间
  363. else if (end < start && (now <= end || now >= start)) {
  364. should = NO;
  365. }
  366. }
  367. return should;
  368. }
  369. #pragma mark - Misc
  370. - (NIMSessionViewController *)currentSessionViewController {
  371. UINavigationController *nav = [ModelRootViewController instance].selectedViewController;
  372. for (UIViewController *vc in nav.viewControllers) {
  373. if ([vc isKindOfClass:[NIMSessionViewController class]]) {
  374. return (NIMSessionViewController *) vc;
  375. }
  376. }
  377. return nil;
  378. }
  379. //- (void)makeToast:(NSString *)content
  380. //{
  381. // [[NTESMainTabController instance].selectedViewController.view makeToast:content duration:2.0 position:CSToastPositionCenter];
  382. //}
  383. @end