これに対する答えを得るためにSOや他のWebサイトで何日も調査しましたが、運がありませんでした.
基本的に、私が自分自身に設定した課題は、ユーザーがどこにいても (フォアグラウンドまたはバックグラウンド) 鳴る iOS 用の目覚まし時計アプリを作成することです。これは、AVAudioPlayer インスタンスを使用して、ユーザーがアラームを設定したときに空のサウンド ファイルの再生を開始して、アプリがバックグラウンドで実行され続けるようにすることで、既に達成しています。アラームが鳴る時間になると (つまり、NSTimer が起動されると)、既に開始されて再生の準備ができている 2 番目のプレーヤーが、ユーザーが目覚める着信音の再生を開始します。
また、AVAudioSessionDelegate メソッドの beginInterruption と endInterruptionWithFlags を実装することで、通話、システム タイマー、または目覚まし時計による割り込みを処理することができました。バックグラウンド モードとフォアグラウンド モードの両方で動作しますが、最も奇妙なことが起こります。
中断が終了すると、AVAudioPlayer は再生を再開しますが、アプリを再びフォアグラウンドにしない限り、アプリで他のコードを実行することはできません。
この問題の根底にたどり着くために、私は以下に投稿しているより単純なプロジェクトを試しました。このアプリが行うことは、アプリに入るとすぐに、AVAudioPlayer クラスのインスタンスが特定のサウンドのループを開始することです。その後、バックグラウンドに移動すると、プレーヤーはサウンドをループし続けます。中断が発生するとプレーヤーを一時停止し、プレーヤーが終了したらディスパッチを使用して数秒待機してから、ファイルの再生を再開するコードを含むメソッド (void)playPlayer と (void)tester の 2 つのメソッドを呼び出します。は、中断の 5 秒後 (正確には 7 秒後) にプレーヤーを停止するように設定されたタイマーを含むメソッドです。私が両方に入れた NSLogs によって示されるように、両方のメソッドが呼び出されますが、タイマーが起動されることはなく、プレーヤーは無期限に再生を続けます。
.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 メソッドで何かを設定する必要がありますか?
事前にどうもありがとうございました!