有没有办法在VoIP应用程序中永远持续响铃?

时间:2013-10-22 12:08:44

标签: ios background voip

我正在研究基于VoIP的IOS应用程序。

有两种播放声音的方法可以在来电时通知用户:

  1. 发送UILocalNotification声音。声音将持续最多30秒;
  2. setKeepAliveTimeout:handler:功能中播放本地音乐素材。但系统只给我10秒的时间来进行操作。
  3. 有没有办法像本机手机应用程序一样永久播放声音?

2 个答案:

答案 0 :(得分:1)

我害怕@Dan2552是正确的。

这是Apple states

的内容
  

不支持持续时间超过30秒的声音。如果你   指定一个播放超过30秒的声音的文件,默认值   而是播放声音。


修改

使用AVAudioPlayer

中的AVFoundation,可以播放音频文件超过30秒(或永远,为此)
@import AVFoundation;  // module -> no need to link the framework
// #import <AVFoundation/AVFoundation.h> // old style

- (void)playAudio
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp3"];
    NSError *error = nil;
    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
    if (!error) {
        player.numberOfLoops = -1; // infinite loop
        [player play];
    } else {
        NSLog(@"Audio player init error: %@", error.localizedDescription);
    }
}

然后,必须主线程上调用此方法,而不是设置本地通知的soundName属性:

[self performSelectorOnMainThread:@selector(playAudio) withObject:nil waitUntilDone:NO];

答案 1 :(得分:1)

伊斯兰问答问题的答案是,AVAudioPlayer无法处理通知,因为当您不使用该应用时,应用会被静音。只有UILocalNotification可以让您的应用在未激活时发出声音。 30秒的限制是真实的。应该通过另外30秒通知重复通知来完成。我不知道其他VOIP应用程序会持续响多长时间,但即使使用传统手机,通常也会有限制,例如一分钟。

我的策略是:

  • 发送有人试过的29秒报警的初始通知 联系
  • 在您即将错过呼叫的40秒后发送带有不同29秒警报的第二通知
  • 发送第三个通知,表示您在100秒后错过了一个电话

这将允许用户1:40的时间来响应呼叫。

您的代码看起来像这样:

UILocalNotification* notification = [[UILocalNotification alloc] init];
notification.alertBody = NSLocalizedString(@"FIRST_CALL", @"%@ is calling you!");
notification.soundName = @"normal_ring.mp3";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(40 * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    if (!phone.isRinging)
    {
        // Somebody picked it up already in the mean time
        return;
    }    

    UILocalNotification* notification = [[UILocalNotification alloc] init];
    notification.alertBody = NSLocalizedString(@"HURRY_CALL", @"Hurry, you are about to miss a call from %@!");
    notification.soundName = @"hurry_ring.mp3";
    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];

    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        if (!phone.isRinging)
        {
            // Somebody picked it up already in the mean time
            return;
        }  

        UILocalNotification* notification = [[UILocalNotification alloc] init];
        notification.alertBody = NSLocalizedString(@"MISSED_CALL", @"You've just missed a call from %@");
        notification.soundName = @"missed_call.mp3";
        [[UIApplication sharedApplication] presentLocalNotificationNow:notification];

    });
});

如果您使用该代码,请记住您首先需要确保该应用程序在后台,因此UILocalNotification将是您唯一的选择。当它在前台时使用普通的AVAudioPlayer,更加灵活。第二件事是当用户响应呼叫时应用程序成为前台,因此它应该使警报静音并让AVAudioPlayer接管。

您希望警报和应用内声音之间或多或少平滑过渡,以便为您的用户提供完美的体验,因此最好的办法是测量响铃之间的时间,让AVAudioPlayer完全正确启动新循环开始时的时间。

您的第二个问题是让应用程序在后台运行。这个简单的代码将一直用于轮询应用程序,然后保持活着。它直接来自一个正常工作的应用程序,此代码轮询定时器是否仍在运行并在以下时间内休眠五秒钟:

UIBackgroundTaskIdentifier backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
}];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [timerExecuted timerUpdate];

    while (!timerExecuted.isStopped)
    {
        [NSThread sleepForTimeInterval:5];
    }

    [application endBackgroundTask:backgroundTask];
});