バックグラウンドで実行しているとき、私のAVPlayerの実装は、ダウンロードされたオーディオ(例えば、ポッドキャスト)を再生することはできませんが、ローカルに保存されている曲を再生できます。バックグラウンドで再生できないのは、電話機がコンピュータから切断されている場合だけです。私の電話がコンピュータ/デバッガに直接接続されている場合、ローカルまたはダウンロードされたメディアは問題なく再生されます。フォアグラウンドでは、どちらのメディアタイプでも問題はありません。ここでAVPlayerがバックグラウンドでメディアを読み込んでいません
は私の実装です:
AVPlayer *moviePlayer;
AVPlayerItem *playerItem;
NSURL *address = /* the url of either a local song or remote media */
if (moviePlayer != nil) {
NSLog(@"removing rate, playbackBufferEmpty, playbackLikelyToKeepUp observers before creating new player");
[moviePlayer removeObserver:self forKeyPath:@"rate"];
[playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
[playerItem removeObserver:self forKeyPath:@"status"];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:playerItem];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:playerItem];
[self setMoviePlayer:nil]; // release and nilify
}
// The following block of code was an experiment to see if starting a background task would resolve the problem. As implemented, this did not help.
if([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive)
{
NSLog(@"Experiment. Starting background task to keep iOS awake");
task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
}];
}
playerItem = [[AVPlayerItem alloc]initWithURL:address];
moviePlayer = [[AVPlayer alloc]initWithPlayerItem:playerItem];
// Add a notification to make sure that the player starts playing. This is handled by observeValueForKeyPath
[moviePlayer addObserver:self
forKeyPath:@"rate"
options:NSKeyValueObservingOptionNew
context:nil];
[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
// The following 2 notifications handle the end of play
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:playerItem];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:AVPlayerItemFailedToPlayToEndTimeNotification
object:playerItem];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackStalled:)
name:AVPlayerItemPlaybackStalledNotification
object:playerItem];
// Indicate the action the player should take when it finishes playing.
moviePlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause;
moviePlayer.automaticallyWaitsToMinimizeStalling = NO;
はUPDATE:上記の実装では、私はまた、バックグラウンドでポッドキャストを再生するためにAVPlayerを有効にすることを希望してバックグラウンドタスクを開始するための実験的な試みを示しています。これは助けにはならなかったが、私は参照のためにそれを含める。表示されていませんが、AVPlayerItemのplaybackLikelyToKeepUpステータスがTRUEに変更された後、バックグラウンドタスクも終了します。
それから私はキーパスの通知を処理するために、次のコードがあります:切断時に実行をトレースするために、ロギングツールを実装することで
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
NSLog(@"moviePlaybackDidFinish. Time to stopMoviePlayerWithMusicPlayIndication");
[self stopMoviePlayer: YES]; // stop the movie player
}
- (void) moviePlayBackStalled:(NSNotification*)notification {
NSString *debugString = [NSString stringWithFormat: @"In moviePlayBackStalled. Restarting player"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
[moviePlayer play];
}
:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"rate"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: rate"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"playbackBufferEmpty"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: playbackBufferEmpty"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: playbackLikelyToKeepUp"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
else if (object == playerItem && [keyPath isEqualToString:@"status"]) {
NSString *debugString = [NSString stringWithFormat: @"In observeValueForKeyPath: status"];
DLog(@"%@", debugString);
debugString = [self appendAvPlayerStatus: debugString];
[[FileHandler sharedInstance] logDebugString:debugString];
}
}
そして、私は通知を通知センター処理するために、次のしているがコンピュータから、ここに私が観察しているものがあります:
コンピュータから接続されていないバックグラウンドで実行すると、playerItem urlアドレスがロードされ、AVPlayerはplayerItemで初期化されます。これにより、通知observeValueForKeyPath:rateがポストされますが、それは最後に受信された通知です。音声は再生されません。プレーヤーはちょうどハングアップします。次のように様々のMoviePlayerとplayerItemフラグを示す私のログの出力は次のとおりです。ただし
ready to play movie/podcast/song dedication/Song from url: http://feedproxy.google.com/~r/1019TheMix-EricAndKathy/~5/ZZnF09tuxr0/20170309-1_1718764.mp3
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 1, playbackBufferFull: 0, rate: 1.0
、直接コンピュータに接続されているか、フォアグラウンドで実行している場合、あなたは以下のログ出力から見ることができたときに、バックグラウンドで実行している場合urlアドレスがロードされ、AVPlayerがplayerItemで初期化された後、keyPath:rate、playbackBufferEmpty、playbackLikelyToKeepUp、およびstatusの一連の通知がポストされます。オーディオが再生されます。様々のMoviePlayerとplayerItemフラグを示す出力は、次のとおりです。フォアグラウンドまたはバックグラウンドで実行している場合、直接コンピュータ/デバッガに接続している場合ので要約すると、あなたがその上に表示さ
ready to play movie/podcast/song dedication/Song from url: http://feedproxy.google.com/~r/1019TheMix-EricAndKathy/~5/d3w52TBzd88/20170306-1-16_1717980.mp3
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 1, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackBufferEmpty - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackLikelyToKeepUp - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusUnknown, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: status - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 0, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: playbackLikelyToKeepUp - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 1, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
In observeValueForKeyPath: rate - timeCntrlStatus: AVPlayerTimeControlStatusPlaying, itemStatus: AVPlayerItemStatusReadyToPlay, playbackToKeepUp: 1, playbackBufferEmpty: 0, playbackBufferFull: 0, rate: 1.0
、AVPlayerが正常に再生バッファをロードしますオーディオを再生します。しかし、バックグラウンドで実行され、コンピュータ/デバッガに接続されていない場合、プレーヤはメディアをロードしておらず、ハングするだけです。
すべての場合、AVPlayerItemPlaybackStalledNotificationは決して受信されません。
長い説明は申し訳ありません。コンピュータに接続していないときに、プレーヤーがバックグラウンドでハングアップしている原因を誰に見てもらえますか?
再生を開始するときに 'beginBackgroundTask'を呼び出してみましたか?ドキュメントには、バックグラウンドで実行するべきではないと書かれていますが、未完成のビジネスに役立つとも言われています。https://developer.apple.com/reference/uikit/uiapplication/1623031-beginbackgroundtask –
@Rhythmic Fistmanはい、私はそれを試みた。それは助けになりませんでした。また、AVPlayerはバックグラウンドでローカルメディアを再生するのに問題はないので、iOSを私を寝かせる問題のようには見えません。 – JeffB6688
ローカルファイルのタイミングプロパティは異なります。スケジュール解除されるのを避けるため、バックグラウンドオーディオアプリはオーディオを再生している必要があります。あなたの 'AVPlayer 'が再生を開始する前にオーディオデータをストリームする時間が必要だということが問題になります。 –