gpt4 book ai didi

objective-c - 应用程序处于后台时中断后恢复执行代码

转载 作者:可可西里 更新时间:2023-11-01 06:16:45 26 4
gpt4 key购买 nike

我花了几天时间在 SO 和其他网站上寻找答案,但没有任何运气。

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

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

当中断结束时,AVAudioPlayer 恢复播放但我无法在我的应用程序中执行任何其他代码,除非我再次将该应用程序置于前台。

为了弄清楚这个问题,我尝试了一个更简单的项目,我在下面发布了这个项目。这个应用程序所做的是,只要你进入应用程序,AVAudioPlayer 类的一个实例就会开始循环播放特定的声音。然后当你把它带到背景时,播放器会继续循环播放声音。当发生中断时,我暂停播放器,当它结束时,我使用分派(dispatch)等待几秒钟,然后它调用两个方法,即 (void)playPlayer,一个包含恢复播放文件的代码的方法和 (void)tester ,一种包含计时器的方法,该计时器设置为在中断结束后 5 秒(或准确地说是 7 秒)停止播放器。这两种方法都按照我放入其中的 NSLog 的指示进行调用,但计时器永远不会被触发,播放器将继续无限期播放。

这是 .h 文件的代码:

#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 文件的代码:

#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 方法中设置一些东西吗?

非常感谢您!

最佳答案

请使用“[NSTimer scheduledTimerWithTimeInterval:5.0 target:myPlayer selector:@selector(stop) userInfo:nil repeats:NO]”;

关于objective-c - 应用程序处于后台时中断后恢复执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10406874/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com