4

これに対する答えを得るために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 メソッドで何かを設定する必要がありますか?

事前にどうもありがとうございました!

4

2 に答える 2

0

「[NSTimer scheduleTimerWithTimeInterval:5.0 target:myPlayer selector:@selector(stop) userInfo:nil repeats:NO]」を使用してください。

于 2012-05-02T03:44:56.683 に答える
0

質問を避けるわけではありませんが、バックグラウンドで空の音を再生するビットはハックです。バックグラウンドでサウンドを再生する機能は、バックグラウンド プロセスを維持するためではなく、ユーザーの利益のために音楽やその他のサウンドを再生できるようにするために提供されています。

音を鳴らしたり、特定の時間にユーザーに警告したりする場合は、代わりにローカル通知を使用することを検討してください。

アプリがバックグラウンドにあるときに中断後にタイマーが起動されないのはなぜですか?

私の記憶が正しければ、アプリがバックグラウンドに入ると、タイマーは一時停止またはキャンセルされます。ドキュメントには、アプリが中断されたとき、つまりバックグラウンドに送信されたときに、「タイマーやその他の定期的なタスクを停止する」必要があると明示的に記載されています。

于 2012-05-02T03:54:32.427 に答える