首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >app后台中断后继续执行代码

app后台中断后继续执行代码
EN

Stack Overflow用户
提问于 2012-05-02 10:16:52
回答 2查看 1.7K关注 0票数 4

从本质上讲,我给自己设置的挑战是为iOS创建一个闹钟应用程序,无论用户在哪里(前台或后台),它都能发出声音。我已经通过使用AVAudioPlayer实例并在用户设置闹钟时开始播放一个空的声音文件来实现这一点,以便应用程序继续在后台运行。当闹钟响起的时候(即当NSTimer被触发时),已经启动并准备播放的第二个播放器开始播放用户被唤醒的铃声。

此外,通过实现AVAudioSessionDelegate方法beginInterruption和endInterruptionWithFlags,我成功地处理了电话、系统计时器或闹钟造成的中断。它在背景和前景模式下都有效,但最奇怪的事情发生了:

当中断结束时,AVAudioPlayer继续播放,但我不能在我的应用程序中执行任何其他代码,除非我再次将应用程序带到前台。

为了弄清楚这一点,我尝试了一个更简单的项目,我在下面发布了这个项目。这个应用程序的作用是,只要您进入该应用程序,AVAudioPlayer类的一个实例就会开始循环播放特定的声音。然后,当你把它带到后台,播放器继续循环声音。这两个方法都会被调用,正如我在这两个方法中放入的NSLogs所指示的那样,但是计时器永远不会被触发,玩家会无限期地继续玩下去。

以下是.h文件的代码:

代码语言:javascript
复制
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>

@interface InterruptionTest3ViewController : UIViewController <AVAudioSessionDelegate,      AVAudioPlayerDelegate>
{
    AVAudioSession *mySession;
    AVAudioPlayer *myPlayer;
}

-(void) playPlayer;
-(void) pausePlayer;
-(void) tester;

@end

以下是.m文件的代码:

代码语言:javascript
复制
#import "InterruptionTest3ViewController.h"

@interface InterruptionTest3ViewController ()

@end

@implementation InterruptionTest3ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    mySession = [AVAudioSession sharedInstance];
    NSError *setActiveError = nil;
    [mySession setActive:YES withFlags:AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation error:&setActiveError];
    if (setActiveError) {
        NSLog(@"Session failed to activate within viewDidLoad");
    }
    else {
        NSLog(@"Session was activated within viewDidLoad");
    }
    NSError *setCategoryError = nil;
    [mySession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
    if (setCategoryError) {
        NSLog(@"Category failed to be set");
    }
    else {
        NSLog(@"Category has been set");
    }

    [mySession setDelegate:self];


    NSString *path = [[NSBundle mainBundle] pathForResource:@"headspin" ofType:@"wav"];
    NSError *initMyPlayerError = nil;
    myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]     error:&initMyPlayerError];
    if (initMyPlayerError) {
        NSLog(@"myPlayer failed to initiate");
    }
    else {
        NSLog(@"myPlayer has been initiated");
    }

    [myPlayer prepareToPlay];
    [self playPlayer];

    OSStatus propertySetError = 0;
    UInt32 allowMixing = true;

    propertySetError = AudioSessionSetProperty (
                                                kAudioSessionProperty_OverrideCategoryMixWithOthers, 
                                                sizeof (allowMixing),                                 
                                                &allowMixing                                          
                                                );

    [myPlayer setNumberOfLoops:-1];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}

-(void) beginInterruption
{
    [myPlayer pause];
}

-(void) endInterruptionWithFlags:(NSUInteger)flags
{
    if (flags) {
        if (AVAudioSessionInterruptionFlags_ShouldResume) 
        {
            {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),dispatch_get_main_queue(), ^{

                    [self playPlayer];
                    [self tester];
                });
}
        }
    }
}

-(void) tester
{
    [NSTimer timerWithTimeInterval:5.0 target:self selector:@selector(pausePlayer) userInfo:nil repeats:NO];
    NSLog(@"tester method has been called");
}

-(void) playPlayer
{
    [NSTimer timerWithTimeInterval:5.0 target:myPlayer selector:@selector(stop) userInfo:nil repeats:NO];
    [myPlayer play];
    NSLog(@"playPlayer method has been called");
}

-(void) pausePlayer
{
    [myPlayer pause];
}



//viewDidUnload etc not listed.

所以,就是这样了,伙计们。再说一次,为什么在应用程序处于后台时,计时器在中断后不被触发?我需要在applicationDidEnterBackground方法中设置一些东西吗?

非常感谢您的提前!

EN

回答 2

Stack Overflow用户

发布于 2012-05-02 11:44:57

请使用"NSTimer scheduledTimerWithTimeInterval:5.0目标:myPlayer选择器:@选择器(停止) userInfo:nil重复数:NO“;

票数 0
EN

Stack Overflow用户

发布于 2012-05-02 11:54:32

不是为了避免这个问题,但是背景中播放空声音的部分是一个技巧。提供了在后台播放声音的能力,以便您可以播放音乐或其他声音,以便用户受益,而不是保持后台进程处于活动状态。

如果您想在特定时间播放声音或以其他方式提醒用户,请考虑使用using local notifications

为什么在应用程序处于后台时,计时器在中断后不被触发?

如果我没记错的话,当你的应用程序进入后台时,计时器要么挂起,要么取消。文档明确地说,当你的应用程序被中断时,也就是当它被发送到后台时,你应该使用"stop timers and other periodic tasks"

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10406874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档