美文网首页
iOS仿微信语音来电持续震铃

iOS仿微信语音来电持续震铃

作者: 落寞绅士 | 来源:发表于2023-07-31 10:51 被阅读0次

    如题:要想达到微信收到语音震铃效果需要用到UNNotificationServiceExtension,关于UNNotificationServiceExtension的使用可以参考iOS 10通知扩展-通知服务扩展这篇文章。

    整体流程图如下:

    图片.png

    知识点

    UNNotificationServiceExtensionApp GroupsUNUserNotificationCenter

    代码实现

    整体代码
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {   
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        NSDictionary *apns = self.bestAttemptContent.userInfo[@"aps"];
        NSLog(@"didReceiveNotificationRequest:withContentHandler: -- apns = %@", apns);
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        
        NSString *sound = apns ? [apns objectForKey:@"sound"] : nil;
        // 来电推送
        if (sound && [sound isEqualToString:@"incoming.wav"]) {
            // 删除推送本身的铃声
            self.bestAttemptContent.sound = nil;
            [self incomingNotification];
        }
        // 其他推送
        else {
            self.contentHandler(self.bestAttemptContent);
        }
    }
    
    来电推送
    /// 来电推送
    - (void)incomingNotification
    {
        // 前台来电
        if ([self isForegroundIncoming]) {
            return;
        }
        
        [self addLocalNotice:self.bestAttemptContent.title body:self.bestAttemptContent.body];
        
        // 播放声音
        NSString *path = [[NSBundle mainBundle] pathForResource:@"incoming.wav" ofType:nil];
        static SystemSoundID soundID = 0;
        NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
        [[AVAudioSession sharedInstance] setActive:YES error:NULL];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:NULL];
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)filePath, &soundID);
        AudioServicesPlayAlertSoundWithCompletion(soundID, ^{
            NSLog(@"didReceiveNotificationRequest:withContentHandler: -- 播报完成");
            [self setAppGroupsIncoming:NO];
            // 结束定时器
            [self endVibrationTimer];
            
            [self removeAllNotification];
            self.bestAttemptContent.body = [NSString stringWithFormat:@"%@,请尽快打开APP接听!", self.bestAttemptContent.body];
            self.contentHandler(self.bestAttemptContent);
        });
        
        // 持续震动
        [self destroyVibrationTimer];
        self.vibrationTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
        dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
        dispatch_source_set_timer(self.vibrationTimer, start, 1 * NSEC_PER_SEC, 0);
        dispatch_source_set_event_handler(self.vibrationTimer, ^{
            // 震动
            AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
            
            // 是否前台来电
            if ([self isForegroundIncoming]) {
                [self setAppGroupsIncoming:NO];
                // 结束响铃
                AudioServicesDisposeSystemSoundID(soundID);
                // 结束定时器
                [self endVibrationTimer];
                
                [self removeAllNotification];
                self.contentHandler(self.bestAttemptContent);
            }
        });
        dispatch_resume(self.vibrationTimer);
    }
    
    创建本地推送
    /// 创建本地推送
    - (void)addLocalNotice:(NSString *)title body:(NSString *)body
    {
        if (@available(iOS 10.0, *)) {
            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
            UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
            content.title = title;
            content.body = body;
            content.sound = nil;
            content.badge = @1;
            NSTimeInterval time = [[NSDate dateWithTimeIntervalSinceNow:1] timeIntervalSinceNow];
            // repeats,是否重复,如果重复的话时间必须大于60s,要不会报错
            UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:NO];
            // 添加通知的标识符,可以用于移除,更新等操作
            NSString *identifier = @"noticeId";
            UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
            
            [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
                NSLog(@"成功添加推送");
            }];
        }
    }
    

    这里的isForegroundIncoming方法涉及到Extension和主项目数据通信,这里使用到了App Groups 。具体可参考ios UNNotificationServiceExtension app和extension的通信这篇文章。

    相关文章

      网友评论

          本文标题:iOS仿微信语音来电持续震铃

          本文链接:https://www.haomeiwen.com/subject/cosepdtx.html