Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get my AVPlayer to play while app is in background?

I've done my homework... been reading here, the docs, googling, stackoverflowing... but still no luck in making my sound stick when the user makes the app go into the background.

What I have done so far: Added the UIBackgroundModes, audio to the plist-file.

First this code:

radioAudio = [[AVAudioSession alloc] init]; [radioAudio setCategory:AVAudioSessionCategoryPlayback error:nil]; [radioAudio setActive:YES error:nil]; 

Then this:

NSString *radioURL = @"http://xxx.xxx.xxx/radio.m3u"; radioPlayer = [[AVPlayer playerWithURL:[NSURL URLWithString:radioURL]] retain]; 

But as soon as the user hits the home-button, my sound dies.

I also found this, but not added yet cuase some stuff I've read says it is not needed;

newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];      if (newTaskId != UIBackgroundTaskInvalid && bgTaskId != UIBackgroundTaskInvalid)         [[UIApplication sharedApplication] endBackgroundTask: bgTaskId]; bgTaskId = newTaskId; 

Right now I have no idea where I should go to make my AVPlayer let the radio sing while the user does other stuff on the phone. I am testing this on an iPhone 4 with 4.2. Building it for 4.0.

Anyone have any suggestions what I should do?

like image 469
swe_mattias Avatar asked Jan 22 '11 22:01

swe_mattias


People also ask

How do I make my iPhone apps play in the background?

Under the Capabilities tab, set the Background Modes switch to ON and select the “Audio, AirPlay, and Picture in Picture” option under the list of available modes. With this mode enabled and your audio session configured, your app is ready to play background audio.

How do I get Apple music to play in the background?

Go to Settings > Accessibility > Audio/Visual > Background Sounds, then turn on Background Sounds. Set any of the following: Sound: Choose a sound; the audio file downloads to your iPhone.


2 Answers

UPDATE IOS 11.2 with Swift 4:

Now if you are using AVPlayer to play music files you should also configure MPNowPlayingInfoCenter.default() to show now playing info on the lock screen.

Below code will show now playing controls on the screen but it won't be able to respond any commands.

If you also want to controls to work you should check apple's sample project here: https://developer.apple.com/library/content/samplecode/MPRemoteCommandSample/Introduction/Intro.html#//apple_ref/doc/uid/TP40017322

Apple sample code covers all but i find it confusing.

If you want to play sound and show controls on the lock screen these steps will do just fine.

IMPORTANT NOTE: If you are NOT using AVPlayer to play sound. If you are using some third party libraries to generate sound or playback a sound file you should read comments inside the code. Also if you are using ios simulator 11.2 you won't be able to see any controls on lock screen. You should use a device to see it work.


1- Select project -> capabilites -> set background modes ON -> tick Audio, AirPlay and Picture in Picture

ios 11 background audio setting

2- AppDelegate.swift file should look like this :

import UIKit  import AVFoundation  @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {      var window: UIWindow?      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool     {         // Override point for customization after application launch.          do         {             try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)             try AVAudioSession.sharedInstance().setActive(true)           //!! IMPORTANT !!          /*          If you're using 3rd party libraries to play sound or generate sound you should          set sample rate manually here.          Otherwise you wont be able to hear any sound when you lock screen          */             //try AVAudioSession.sharedInstance().setPreferredSampleRate(4096)         }         catch         {             print(error)         }         // This will enable to show nowplaying controls on lock screen         application.beginReceivingRemoteControlEvents()          return true     } } 

3- ViewController.swift should look like this:

import UIKit  import AVFoundation import MediaPlayer  class ViewController: UIViewController {      var player : AVPlayer = AVPlayer()      override func viewDidLoad()     {         super.viewDidLoad()           let path = Bundle.main.path(forResource: "music", ofType: "mp3")         let url = URL(fileURLWithPath: path!)          // !! IMPORTANT !!         /*             If you are using 3rd party libraries to play sound              or generate sound you should always setNowPlayingInfo              before you create your player object.              right:             self.setNowPlayingInfo()             let notAVPlayer = SomePlayer()              wrong(You won't be able to see any controls on lock screen.):             let notAVPlayer = SomePlayer()             self.setNowPlayingInfo()          */          self.setNowPlayingInfo()         self.player = AVPlayer(url: url)      }       func setNowPlayingInfo()     {         let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()         var nowPlayingInfo = nowPlayingInfoCenter.nowPlayingInfo ?? [String: Any]()          let title = "title"         let album = "album"         let artworkData = Data()         let image = UIImage(data: artworkData) ?? UIImage()         let artwork = MPMediaItemArtwork(boundsSize: image.size, requestHandler: {  (_) -> UIImage in             return image         })          nowPlayingInfo[MPMediaItemPropertyTitle] = title         nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = album         nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork          nowPlayingInfoCenter.nowPlayingInfo = nowPlayingInfo     }      @IBAction func startPlayingButtonPressed(_ sender: Any)     {         self.player.play()     } 

OLD ANSWER IOS 8.2:

Patrick's answer is totally right.

But i'm gonna write what i do for ios 8.2:

I add my app's info.plist required background modes like below:

enter image description here

And in my AppDelegate.h i add these imports:

#import <AVFoundation/AVFoundation.h> #import <AudioToolbox/AudioToolbox.h> 

Then in my AppDelegate.m i wrote application didFinishLaunchingWithOptionsthis exactly like below:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {     // Override point for customization after application launch.      [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];      return YES; } 

Now App keeps playing music even if screen is locked :)

like image 140
EFE Avatar answered Oct 14 '22 18:10

EFE


Had the same problem, but found a solution for this..

Look here: https://devforums.apple.com/message/395049#395049

The content of the above link:


Replace APPNAME with your own app name!

Im on iOS 4.2.1

EDIT: Working with iOS5 + 6 + 7 beta so far

Add UIBackgroundModes in the APPNAME-Info.plist, with the selection App plays audio

Then add the AudioToolBox framework to the folder frameworks.

In the APPNAMEAppDelegate.h add:

#import <AVFoundation/AVFoundation.h> #import <AudioToolbox/AudioToolbox.h> 

so it look like this:

... #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> #import <AudioToolbox/AudioToolbox.h> ... 

In the APPNAMEAppDelegate.m add the following:

// Set AudioSession NSError *sessionError = nil; [[AVAudioSession sharedInstance] setDelegate:self]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];  /* Pick any one of them */ // 1. Overriding the output audio route //UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; //AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);  // 2. Changing the default output audio route UInt32 doChangeDefaultRoute = 1; AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute); 

into the

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

but before the two lines:

[self.window addSubview:viewController.view]; [self.window makeKeyAndVisible]; 

Build your project and see if theres any error, If not, try debug on Device insted of the Simulator, it CAN bug on simulator.

Hope this helps others with same problem..

like image 45
Patrick R Avatar answered Oct 14 '22 16:10

Patrick R