iOS仿微信語音來電持續(xù)震鈴

如題:要想達(dá)到微信收到語音震鈴效果需要用到UNNotificationServiceExtension,關(guān)于UNNotificationServiceExtension的使用可以參考iOS 10通知擴(kuò)展-通知服務(wù)擴(kuò)展這篇文章。

整體流程圖如下:

圖片.png

知識點

UNNotificationServiceExtension、App Groups、UNUserNotificationCenter

代碼實現(xiàn)

整體代碼
- (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];
        // 結(jié)束定時器
        [self endVibrationTimer];
        
        [self removeAllNotification];
        self.bestAttemptContent.body = [NSString stringWithFormat:@"%@,請盡快打開APP接聽!", self.bestAttemptContent.body];
        self.contentHandler(self.bestAttemptContent);
    });
    
    // 持續(xù)震動
    [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];
            // 結(jié)束響鈴
            AudioServicesDisposeSystemSoundID(soundID);
            // 結(jié)束定時器
            [self endVibrationTimer];
            
            [self removeAllNotification];
            self.contentHandler(self.bestAttemptContent);
        }
    });
    dispatch_resume(self.vibrationTimer);
}
創(chuàng)建本地推送
/// 創(chuàng)建本地推送
- (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,是否重復(fù),如果重復(fù)的話時間必須大于60s,要不會報錯
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:NO];
        // 添加通知的標(biāo)識符,可以用于移除,更新等操作
        NSString *identifier = @"noticeId";
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
        
        [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
            NSLog(@"成功添加推送");
        }];
    }
}

這里的isForegroundIncoming方法涉及到Extension和主項目數(shù)據(jù)通信,這里使用到了App Groups 。具體可參考ios UNNotificationServiceExtension app和extension的通信這篇文章。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容