Фоновый звук не возобновляется после вызова
Мой фоновый звук прекрасно работает почти все время. Экран заблокирован или отключен. Но когда пользователь имеет приложение в фоновом режиме и получает вызов, даже если пользователь не отвечает на звонок, фоновый звук не возобновляется после окончания прерывания.
Музыкальное приложение правильно возобновляет фоновый звук, если он был прерван.
Мне не хватает какого-либо свойства или мне нужно иметь обратный вызов или задать фоновую задачу, чтобы продолжить фоновое выполнение звука после прерывания? Или это то, что мы не можем сделать?
Ответы
Ответ 1
Мы возобновляем наш звук после исходящего вызова и входящего вызова, когда приложение находится в фоновом режиме.
Мы воспроизводим аудио с AVAudioPlayer и слушаем AVAudioSessionInterruptionNotification. Apple автоматически приостанавливает работу AVAudioPlayer для вас, и когда вы скажете, что он возобновит работу после того, как вы получили прерывание, Apple снова настроит ваш сеанс. См. Таблицу 3-2 из Обработка прерываний звука по рекомендациям, если вы используете другие типы аудиотехнологий.
Подпишитесь на уведомление:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAudioSessionEvent:) name:AVAudioSessionInterruptionNotification object:nil];
Обработать уведомление:
- (void) onAudioSessionEvent: (NSNotification *) notification
{
//Check the type of notification, especially if you are sending multiple AVAudioSession events here
if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
NSLog(@"Interruption notification received!");
//Check to see if it was a Begin interruption
if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
NSLog(@"Interruption began!");
} else {
NSLog(@"Interruption ended!");
//Resume your audio
}
}
}
Ответ 2
По моему опыту я обнаружил, что мне пришлось "подождать секунду или два", прежде чем пытаться снова открыть аудиоустройство. Я думаю, что после того, как ОС переключится обратно в ваше приложение с помощью вызова, приложение по-прежнему отключается.
что-то вроде этого, когда вы вернетесь на передний план после того, как узнаете, что ваш аудио-сеанс остановлен:
dispatch_time_t restartTime = dispatch_time(DISPATCH_TIME_NOW,
1.5LL * NSEC_PER_SEC);
dispatch_after(restartTime, dispatch_get_global_queue(0, 0), ^{
[audioSystem restart];
});
Ответ 3
Я использую Xamarin, так что это С#, но для меня работает следующий код. Я сначала установил, что мой AppDelegate реализует методы делегирования AVAudioSession, включая IAVAudioSessionDelegate
public partial class AppDelegate: UIApplicationDelegate, IAVAudioSessionDelegate
Я добавил переменную в класс AppDelegate для сеанса аудио
public static AVAudioSession AudioSession;
В переопределении метода FinishedLaunching:
AudioSession = AVAudioSession.SharedInstance();
AudioSession.Delegate = this;
error = AudioSession.SetCategory( AVAudioSessionCategory.Playback, AVAudioSessionCategoryOptions.DuckOthers );
AudioSession.SetMode( new NSString( "AVAudioSessionModeMoviePlayback" ), out error );
Два соответствующих метода делегата в AppDelegate.cs:
[Export( "beginInterruption" )]
public void BeginInterruption()
{
PlayerViewController.BeginSessionInterruption();
}
[Export( "endInterruptionWithFlags:" )]
public void EndInterruption( AVAudioSessionInterruptionFlags flags )
{ // ignore the flags so we're not dependent on the interrupting event saying that we can resume
PlayerViewController.ResumeAfterSessionInterruption();
}
My AppDelegate также имеет переопределение OnActivated для включения видеодорожек, если это видеообъявление, и переопределение DidEnterBackground для отключения дорожек медиа-видео, но все равно воспроизводить аудио.
В методе PlayerViewController.BeginSessionInterruption() я не могу посмотреть на Player.Rate, чтобы проверить, работает ли плеер в то время, потому что прерывание сигнала тревоги или телефонный звонок уже приостановили проигрыватель. В разделе "Ответ на прерывания" руководства по программированию сеансов Apple Audio с добавлением моего внимания:
- Ваше приложение активно, воспроизведение аудио.
- Приходит телефонный звонок. Система активирует сеанс аудиозаписей телефонов.
- Система деактивирует ваш сеанс аудио. На этом этапе воспроизведение * в приложении прекратилось *.
- Система вызывает функцию обратного вызова прослушивателя прерывания, указывающую, что ваш сеанс отключен.
...
Кнопка My PlayerViewController Play имеет свойство Paused для переключения между Play и Pause и рисования соответствующего изображения кнопки. Поэтому вместо проверки Player.Rate, я смотрю, является ли свойство кнопки Paused ложным:
public void BeginSessionInterruption()
{
PlayerWasRunningOnInterruption = !btnPlay.Paused;
TogglePlayPause( true ); // put the Play button into the Paused state to agree with the player being stopped
}
public void ResumeAfterSessionInterruption()
{
NSError error;
AppDelegate.AudioSession.SetActive( true, AVAudioSessionSetActiveOptions.NotifyOthersOnDeactivation, out error ); // always reactivate the audio session
if ( PlayerWasRunningOnInterruption )
{
// rewind a little bit
// call btnPlayClick to resume the playback as if the user pressed the Play button
}
}
Ответ 4
если вы только обнаруживаете статус вызова, вы можете использовать CTCallCenter, но если вы хотите обнаружить прерывание (включая прерывание вызова), вы можете использовать AVAudioSessionInterruptionNotification, и если вы хотите поддержать фон, вы должны добавить такой код:
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
прежде чем вы возобновите воспроизведение музыки в background.hope, это может помочь.
Ответ 5
Для меня работают только два варианта:
-
перезагрузить AVPlayer
или AVAudioPlayer
после завершения прерывания
func interruptionNotification(_ notification: Notification) {
guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt,
let interruption = AVAudioSessionInterruptionType(rawValue: type) else {
return
}
if interruption == .ended && playerWasPlayingBeforeInterruption {
player.replaceCurrentItem(with: AVPlayerItem(url: radioStation.url))
play()
}
}
-
использовать
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
Ответ 6
Я пробовал в течение 3 часов, наконец, получил его, вот что я сделал
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()
@property(strong, nonatomic)AVAudioPlayer *player;
@property(strong)AVAudioSession *session;
@end
@implementation ViewController
- (IBAction)playsound:(id)sender
{
NSURL *url=[[NSURL alloc]initWithString:[[NSBundle mainBundle] pathForResource:@"sound" ofType:@"mp3"]];
NSError *err;
self.player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&err];
[self.player setDelegate:self];
[self.player setVolume:2.5];
self.session=[AVAudioSession sharedInstance];
[self.player prepareToPlay];
[self.player play];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSError *err;
[self.session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&err];
}
@end