user user - 1 year ago 149
iOS Question

How to stop audio in background mode?

I want to stop audio in background mode in first controller and play audio in background mode in second controller.

I use this code:

NSString *soundFilePath = [NSString stringWithFormat:@"%@/%@.mp3",[[NSBundle mainBundle] resourcePath], @"sound"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
_player.numberOfLoops = 1000;
[_player play];


To stop audio in background mode I use this code:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive: NO error: nil];


To play audio in background mode I use this code:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];


But my code to stop audio doesn't work...

UPD

-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleForgroundScenario) name:UIApplicationWillEnterForegroundNotification object:nil];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleBackgroundScenario) name:UIApplicationWillResignActiveNotification object:nil];
}

-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[NSNotificationCenter.defaultCenter removeObserver:self];
}

-(void) handleForgroundScenario {
if([self.player rate] == 0) {
[_player play];
}
}

-(void) handleBackgroundScenario {
[_player pause];
}

- (void)viewDidLoad
{
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: nil];

[super viewDidLoad];

NSString *soundFilePath = [NSString stringWithFormat:@"%@/%@.mp3",[[NSBundle mainBundle] resourcePath], @"sound"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
_player.numberOfLoops = 1000;
[_player play];
}

Answer Source

Add ApplicationWillResign notification in ViewWillAppear of ViewController in which you wanna pause player

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        NotificationCenter.default.addObserver(self, selector: #selector(handleBackgroundScenario), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)
   }

Pause player in selector

@objc func handleBackgroundScenario() {
    //pause
}

Finally remove observer in viewWillDisappear

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self)
}

This will make sure that notification will be triggered only when ViewController is loaded and app goes to background.

For all other VC notification will not trigger the selector and hence it will not alter the behavior of player

EDIT:

Code in Objective - C

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleBackgroundScenario) name:UIApplicationWillResignActiveNotification object:nil];
}

-(void) handleBackgroundScenario {
   //pause player
   [_player pause];
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [NSNotificationCenter.defaultCenter removeObserver:self];
}

EDIT:

Where I should call player after app become alive?

By the statement u mean when to start player when app comes to foreground you can use

[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleForgroundScenario) name:UIApplicationDidBecomeActiveNotification object:nil];

Finally implement handleForgroundScenario

-(void) handleForgroundScenario {
    if([self.player rate] == 0) {
        [_player play];
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download