AppDelegate applicationDidEnterBackground: で AVAudioSession を非アクティブ化することがすべてであることがわかりましたが、多くの場合、エラーで失敗します (非アクティブ化は有効ではありません):
Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)
それでもここで説明されているクラッシュにつながります: Spritekit crashes when enter background。
したがって、setActive:NO を設定するだけでは十分ではありません。(エラーなしで) 効果的に非アクティブ化する必要があります。エラーがない限り AVAudioSession を無効にする専用のインスタンス メソッドを AppDelegate に追加することで、簡単な解決策を作成しました。
要するに、次のようになります。
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"%s", __FUNCTION__);
[self stopAudio];
}
- (void)stopAudio {
NSError *error = nil;
[[AVAudioSession sharedInstance] setActive:NO error:&error];
NSLog(@"%s AudioSession Error: %@", __FUNCTION__, error);
if (error) [self stopAudio];
}
NSLog 証明:
2014-01-25 11:41:48.426 MyApp[1957:60b] -[ATWAppDelegate applicationDidEnterBackground:]
2014-01-25 11:41:48.431 MyApp[1957:60b] -[ATWAppDelegate stopAudio] AudioSession Error: Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)"
2014-01-25 11:41:48.434 MyApp[1957:60b] -[ATWAppDelegate stopAudio] AudioSession Error: Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)"
2014-01-25 11:41:48.454 MyApp[1957:60b] -[ATWAppDelegate stopAudio] AudioSession Error: Error Domain=NSOSStatusErrorDomain Code=560030580 "The operation couldn’t be completed. (OSStatus error 560030580.)"
2014-01-25 11:41:49.751 MyApp[1957:60b] -[ATWAppDelegate stopAudio] AudioSession Error: (null)
これは、stackoverflow を気にしないため、非常に短いです :) AVAudioSession が数千回の試行後に閉じたくない場合 (クラッシュは避けられません)。したがって、これは Apple が修正するまではハッキングとしか考えられません。ところで、AVAudioSession の開始を制御することも価値があります。
完全なソリューションは次のようになります。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"%s", __FUNCTION__);
[self startAudio];
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"%s", __FUNCTION__);
// SpriteKit uses AVAudioSession for [SKAction playSoundFileNamed:]
// AVAudioSession cannot be active while the application is in the background,
// so we have to stop it when going in to background
// and reactivate it when entering foreground.
// This prevents audio crash.
[self stopAudio];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"%s", __FUNCTION__);
[self startAudio];
}
- (void)applicationWillTerminate:(UIApplication *)application {
NSLog(@"%s", __FUNCTION__);
[self stopAudio];
}
static BOOL isAudioSessionActive = NO;
- (void)startAudio {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
if (audioSession.otherAudioPlaying) {
[audioSession setCategory: AVAudioSessionCategoryAmbient error:&error];
} else {
[audioSession setCategory: AVAudioSessionCategorySoloAmbient error:&error];
}
if (!error) {
[audioSession setActive:YES error:&error];
isAudioSessionActive = YES;
}
NSLog(@"%s AVAudioSession Category: %@ Error: %@", __FUNCTION__, [audioSession category], error);
}
- (void)stopAudio {
// Prevent background apps from duplicate entering if terminating an app.
if (!isAudioSessionActive) return;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error = nil;
[audioSession setActive:NO error:&error];
NSLog(@"%s AVAudioSession Error: %@", __FUNCTION__, error);
if (error) {
// It's not enough to setActive:NO
// We have to deactivate it effectively (without that error),
// so try again (and again... until success).
[self stopAudio];
} else {
isAudioSessionActive = NO;
}
}
ただし、この問題は、SpriteKit app での AVAudioSession の中断に比べれば簡単です。SpriteKit は頑固で、"再生できなくても再生します:)
私が見つけた限り、最も簡単な方法は setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers. 他の AVAudioSession カテゴリは、 playFileNamed: をまったく避ける必要があると思います。これは、独自の SKNode runAction: サウンド メソッドを再生するためのカテゴリ (AVAudioPlayer など) を作成することで実行できます。しかし、これは別のトピックです。
AVAudioPlayer 実装を備えた私の完全なオールインワン ソリューションはこちら: http://iknowsomething.com/ios-sdk-spritekit-sound/
編集:不足している括弧を修正しました。