I am trying to allow the user to pick a song from their library and play it across different view controllers. I am able to pick songs currently and play them, but I don't know how to play them in the background. Thanks!
class ViewController: UIViewController,
MPMediaPickerControllerDelegate, AVAudioPlayerDelegate {
var myMusicPlayer: MPMusicPlayerController?
var mediaPicker: MPMediaPickerController?
var backgroundMusicPlayer:AVAudioPlayer = AVAudioPlayer()
@IBAction func musicBtn(sender: AnyObject) {
displayMediaPickerAndPlayItem()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
func musicPlayerStateChanged(notification: NSNotification){
print("Player State Changed")
/* Let's get the state of the player */
let stateAsObject =
notification.userInfo!["MPMusicPlayerControllerPlaybackStateKey"]
as? NSNumber
if let state = stateAsObject{
/* Make your decision based on the state of the player */
switch MPMusicPlaybackState(rawValue: state.integerValue)!{
case .Stopped:
/* Here the media player has stopped playing the queue. */
print("Stopped")
case .Playing:
/* The media player is playing the queue. Perhaps you
can reduce some processing that your application
that is using to give more processing power
to the media player */
print("Paused")
case .Paused:
/* The media playback is paused here. You might want
to indicate by showing graphics to the user */
print("Paused")
case .Interrupted:
/* An interruption stopped the playback of the media queue */
print("Interrupted")
case .SeekingForward:
/* The user is seeking forward in the queue */
print("Seeking Forward")
case .SeekingBackward:
/* The user is seeking backward in the queue */
print("Seeking Backward")
}
}
}
func nowPlayingItemIsChanged(notification: NSNotification){
print("Playing Item Is Changed")
let key = "MPMusicPlayerControllerNowPlayingItemPersistentIDKey"
let persistentID =
notification.userInfo![key] as? NSString
if let id = persistentID{
/* Do something with Persistent ID */
print("Persistent ID = \(id)")
}
}
func volumeIsChanged(notification: NSNotification){
print("Volume Is Changed")
/* The userInfo dictionary of this notification is normally empty */
}
func mediaPicker(mediaPicker: MPMediaPickerController,
didPickMediaItems mediaItemCollection: MPMediaItemCollection){
print("Media Picker returned")
/* Instantiate the music player */
myMusicPlayer = MPMusicPlayerController()
if let player = myMusicPlayer{
player.beginGeneratingPlaybackNotifications()
/* Get notified when the state of the playback changes */
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "musicPlayerStateChanged:",
name: MPMusicPlayerControllerPlaybackStateDidChangeNotification,
object: nil)
/* Get notified when the playback moves from one item
to the other. In this recipe, we are only going to allow
our user to pick one music file */
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "nowPlayingItemIsChanged:",
name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification,
object: nil)
/* And also get notified when the volume of the
music player is changed */
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "volumeIsChanged:",
name: MPMusicPlayerControllerVolumeDidChangeNotification,
object: nil)
/* Start playing the items in the collection */
player.setQueueWithItemCollection(mediaItemCollection)
player.play()
/* Finally dismiss the media picker controller */
mediaPicker.dismissViewControllerAnimated(true, completion: nil)
}
}
func mediaPickerDidCancel(mediaPicker: MPMediaPickerController) {
/* The media picker was cancelled */
print("Media Picker was cancelled")
mediaPicker.dismissViewControllerAnimated(true, completion: nil)
}
func stopPlayingAudio(){
NSNotificationCenter.defaultCenter().removeObserver(self)
if let player = myMusicPlayer{
player.stop()
}
}
func displayMediaPickerAndPlayItem(){
mediaPicker = MPMediaPickerController(mediaTypes: .AnyAudio)
if let picker = mediaPicker{
print("Successfully instantiated a media picker")
picker.delegate = self
picker.allowsPickingMultipleItems = true
picker.showsCloudItems = true
picker.prompt = "Pick a song please..."
view.addSubview(picker.view)
presentViewController(picker, animated: true, completion: nil)
} else {
print("Could not instantiate a media picker")
}
}
}
You can use singleton to achieve it like this:
import AVFoundation
class MusicHelper {
static let sharedHelper = MusicHelper()
var audioPlayer: AVAudioPlayer?
func playBackgroundMusic() {
let pickedSong = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("userPickedSong", ofType: "mp3")!)
do {
audioPlayer = try AVAudioPlayer(contentsOfURL:aSound)
audioPlayer!.numberOfLoops = -1
audioPlayer!.prepareToPlay()
audioPlayer!.play()
} catch {
print("Cannot play the file")
}
}
}
And you can use it like this:
MusicHelper.sharedHelper.playBackgroundMusic()
This is just one example how you can do it. Actually there are more and there are already answers on StackOverflow
. But with the way I showed you can call it in any class.