iOS技术收藏收藏ios

利用voip push实现类似微信(QQ)电话连续响铃效果

2019-03-12  本文已影响22人  dandelionYD

前言

本文大部分参考 iOS利用voip push实现类似微信(QQ)电话连续响铃效果 有兴趣的可以多参考它下
自己代码:gitHubDemo


最近客户要求需要做出类似微信的 视频拉起的呼叫的功能,开始使用的是mqtt的方式来发起的消息拉起,

结果:发现 app退到后台、或者app杀死了,就不会收到了(也就拉起不了了)

试了:APNs的方式,结果APNs根本实现不了连续通知,而且它也不会实现像本地通知那样会有连续响铃的效果(微信一般大概30s左右)

为了实现类似微信的方式,最终:我们通过 voip的方式来实现app的视频的拉起

下面是我项目里面的代码:(本人亲用有效)

RingCall.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface RingCall : NSObject
+ (instancetype)sharedMCCall;
- (void)regsionPush;
@end
NS_ASSUME_NONNULL_END

RingCall.m
#import "RingCall.h"
#import "TalkVideoManager.h"
#import <UserNotifications/UserNotifications.h>
#import <AudioToolbox/AudioToolbox.h>

@interface RingCall ()<VideoCallbackDelegate>{
    UILocalNotification *callNotification;
    UNNotificationRequest *request;//ios 10
    NSTimer *_vibrationTimer;
}
@end

@implementation RingCall
+ (instancetype)sharedMCCall {
    static  RingCall *callInstane;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (callInstane == nil) {
            callInstane = [[RingCall alloc] init];
            [[TalkVideoManager sharedClient] setDelegate:callInstane];
        }
    });
    return callInstane;
}

- (void)regsionPush {
    //iOS 10
    if(@available(iOS 10.0, *)){
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (!error) {
                NSLog(@"request authorization succeeded!");
            }
        }];
        [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
            NSLog(@"%@",settings);
        }];
    }
}

#pragma mark-VideoCallbackDelegate
- (void)onCallRing:(NSString *)CallerName withInfo:(NSDictionary *)info{
    if (@available(iOS 10.0, *)) {
        UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
        UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
        content.body =[NSString localizedUserNotificationStringForKey:[NSString
                                                                       stringWithFormat:@"%@%@", CallerName,
                                                                       @"邀请你进行通话。。。。"] arguments:nil];
        content.userInfo = info;
        UNNotificationSound *customSound = [UNNotificationSound soundNamed:@"weixin.m4a"];
        content.sound = customSound;
        UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger
                                                      triggerWithTimeInterval:1 repeats:NO];
        request = [UNNotificationRequest requestWithIdentifier:@"Voip_Push"
                                                       content:content trigger:trigger];
        [self playShake];
        [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
            
        }];
    }else {
        callNotification = [[UILocalNotification alloc] init];
        callNotification.userInfo = info;
        callNotification.alertBody = [NSString
                                      stringWithFormat:@"%@%@", CallerName,
                                      @"邀请你进行通话。。。。"];
        callNotification.soundName = @"weixin.m4a";
        [self playShake];
        [[UIApplication sharedApplication] presentLocalNotificationNow:callNotification]; 
    }  
}

- (void)onCancelRing {
    //取消通知栏
    if (@available(iOS 10.0, *)) {
        NSMutableArray *arraylist = [[NSMutableArray alloc]init];
        [arraylist addObject:@"Voip_Push"];
        [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:arraylist];
    }else {
        [[UIApplication sharedApplication] cancelLocalNotification:callNotification];
    }
    [_vibrationTimer invalidate];
}

-(void)playShake{
    if(_vibrationTimer){
        [_vibrationTimer invalidate];
        _vibrationTimer = nil;
    }else{
        _vibrationTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(playkSystemSound) userInfo:nil repeats:YES];
    }
}
//振动
- (void)playkSystemSound{
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
@end


TalkVideoManager.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol VideoCallbackDelegate <NSObject>
/**
 *  当APP收到呼叫、处于后台时调用、用来处理通知栏类型和铃声。
 *
 *  @param name 呼叫者的名字
 */
- (void)onCallRing:(NSString*)name withInfo:(NSDictionary*)info;
/**
 *  呼叫取消调用、取消通知栏
 */
- (void)onCancelRing;
@end

@interface TalkVideoManager : NSObject
+ (TalkVideoManager *)sharedClient;
- (void)initWithSever;
- (void)setDelegate:(id<VideoCallbackDelegate>)delegate;
//用户挂断/接听  停止震动
-(void)cancleCall;
@end

TalkVideoManager.m
#import "TalkVideoManager.h"
#import <PushKit/PushKit.h>
#import "RingCall.h"
@interface TalkVideoManager ()<PKPushRegistryDelegate>{
    NSString *token;
}

@property (nonatomic,weak)id<VideoCallbackDelegate>mydelegate;
@end

@implementation TalkVideoManager
static TalkVideoManager *instance = nil;
+ (TalkVideoManager *)sharedClient {
    if (instance == nil) {
        instance = [[super allocWithZone:NULL] init];
    }
    return instance;
}

-(void)initWithSever {
    //voip delegate
    PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
    pushRegistry.delegate = self;
    pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
    //ios10注册本地通知
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        [[RingCall sharedMCCall] regsionPush];
    }
}

- (void)setDelegate:(id<VideoCallbackDelegate>)delegate {
    self.mydelegate = delegate;
}

#pragma mark -pushkitDelegate
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{
    if([credentials.token length] == 0) {
        NSLog(@"voip token NULL");
        return;
    }
    //应用启动获取token,并上传服务器
    token = [[[[credentials.token description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
              stringByReplacingOccurrencesOfString:@">" withString:@""]
             stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"token:%@",token);
    //token上传服务器
    [[ACCacheTool shareACCacheTool] setObjectForKey:token key:@"deviceToken"];
}

- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type{
    BOOL isCalling = false;
    switch ([UIApplication sharedApplication].applicationState) {
        case UIApplicationStateActive: {
            isCalling = false;
        }
            break;
        case UIApplicationStateInactive: {
            isCalling = false;
        }
            break;
        case UIApplicationStateBackground: {
            isCalling = true;
        }
            break;
        default:
            isCalling = true;
            break;
    }
    NSLog(@"payload==%@",payload.dictionaryPayload);
    if (isCalling){
        //获取推送的内容
        NSString *callerStr = payload.dictionaryPayload[@"aps"][@"alert"];
        //本地通知,实现响铃效果
        [self.mydelegate onCallRing:callerStr withInfo:payload.dictionaryPayload];
        
    }
}

-(void)cancleCall{
    [self.mydelegate onCancelRing];
}
@end

--------------------------------------------------
使用:
在appdelegate.m里面
导入 #import "TalkVideoManager.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
  ......
    //配置voIP
    [[TalkVideoManager sharedClient] initWithSever];
    return YES;
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
   NSLog(@"点击了本地通知进来了---%@",notification.userInfo);
   [[TalkVideoManager sharedClient] cancleCall];
   
   .......//处理数据
}

说白了:就是通过voip发的消息回调,来进行发送本地通知,然后点击本地通知,再做相应的数据逻辑处理。

上一篇下一篇

猜你喜欢

热点阅读