iOS app does not play audio while background [duplicate] - ios

This question already has answers here:
How to handle background audio playing while iOS device is locked or on another application?
(6 answers)
Closed 2 years ago.
I've created an app for playing radio stream from URL, but it is not playing audio when app is on background. I checked audio and airplay in background modes in app settings but still it does not work. Do I need to add some permissions in appdelegate? Any ideas? Thank you in advance for your help. Here is my code:
import UIKit
import AVKit
class ViewController: UIViewController {
var player : AVPlayer!
var dict = NSDictionary()
#IBOutlet weak var ArtistLabel: UILabel!
#IBAction func playButtonPressed(_ sender: UIButton){
let url = "https://test.com/stream.mp3"
player = AVPlayer(url: URL(string: url)!)
player.volume = 1.0
player.rate = 1.0
player.play()
}
#IBAction func stopButtonStopped(sender: UIButton) {
player.pause()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
overrideUserInterfaceStyle = .light
}
}

You need to set your app Capabilities Background Modes (Audio and AirPlay) and set your AVAudioSession category to AVAudioSessionCategoryPlayback and set it active.
Please Refer to this link below :
How to play audio in background with Swift?

Related

How to turn off audio from a video using AVAudioPlayer?

I have a simple camera that records a video then transitions to a videoPreview. In it there is a button that hwne presses segues back to the camera. However hwen I do this the video audio does not stop. How can I delete it (not mute) so that a new vid can be taken?
Bellow is my Video preview code with what I have attempted
class VideoPlayback: UIViewController {
//receives url video value from VideoViewController
var videoURL: URL!
//place where video gets displayed
#IBOutlet weak var videoView: UIView!
var avPlayer = AVPlayer()
private var playerQueue: AVQueuePlayer!
private var playerItem1: AVPlayerItem!
private var playerLooper: AVPlayerLooper!
private var playerLayer: AVPlayerLayer!
override func viewDidLoad() {
super.viewDidLoad()
print(avPlayer, "avPlayer")
print("videoURL", videoURL)
playerItem1 = AVPlayerItem(url: videoURL as URL)
print(playerItem1, "playerItem1")
playerQueue = AVQueuePlayer(playerItem: playerItem1)
print(playerQueue, "player queue")
playerLayer = AVPlayerLayer(player: playerQueue)
print(playerLayer, "playerLayer")
playerLooper = AVPlayerLooper(player: playerQueue, templateItem: playerItem1)
print(playerLooper, "player looper")
playerLayer.frame = view.bounds
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
print(videoView, "yruewioq")
videoView.layer.insertSublayer(playerLayer, at: 0)
view.layoutIfNeeded()
self.playerQueue?.play()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//attempt at turing audio off
playerQueue = nil
}
#IBAction func cancelVidPreviewButton(_ sender: Any) {
performSegue(withIdentifier: "cancelVideo", sender: self)
}
}
Update:
I have also tried playerLayer.isMuted = true
But I get that it has no member isMuted
If I understand correctly you need to make sure audio session has ended before segue. Setting volume to zero might affect audio session though.
You can use the AVPlayer's volume property to control the volume of AVPlayer.
Setting volume to 0 can mute the audio.
According to the Documentation:
A value of 0.0 indicates silence; a value of 1.0 (the default)
indicates full audio volume for the player instance.
Hope this helps
So I see that actually what needs to be done here is all the video data which has audio needs to be removed as seen bellow
self.playerQueue?.removeAllItems()
But if you want to get rid of audio you just need to do .pause() and then remove the data. here is docs

iOS Local notifications - sound not playing

My local notifications are working, and the alert is showing, however the sound is not playing. I am testing on a device as I know it won't play in the simulator.
let notificationAlert = UILocalNotification()
class DailyAlarmViewController: UIViewController {
#IBOutlet weak var timePicker: UIDatePicker!
#IBAction func alarmSetButton(sender: AnyObject) {
notificationAlert.fireDate = timePicker.date
notificationAlert.timeZone = NSTimeZone.defaultTimeZone()
notificationAlert.repeatInterval = NSCalendarUnit.Day
notificationAlert.alertAction = "Open Survive to Thrive Nation!"
notificationAlert.alertBody = "Time to wake up and complete your Journal!"
notificationAlert.soundName = "Alarm_Clock.wav"
UIApplication.sharedApplication().scheduleLocalNotification(notificationAlert)
}
#IBAction func cancelAlarm(sender: AnyObject) {
UIApplication.sharedApplication().cancelLocalNotification(notificationAlert)
}
Do I need to add Background Mode or Inter App Audio? Any thoughts would be appreciated.
You must check the .wav file had add to the reaource of the app.
Can you try instead of Alarm_Clock.wav to use the default alarm sound UILocalNotificationDefaultSoundName. If it works, then may be the problem is with the Alarm_Clock.wav.

How to stream audio for only a known duration using swift

I'm using AVPlayer (I don't need to, but I wanna stream it and start playing as soon as possible) to play an m4a file (it's an iTunes audio preview). Only I only want it to play a part of that file.
I'm able to set a start time but not an end time.
Using a timer is not working because I'm using URL as a http address. I'm playing as it loads, without downloading the file.
I also saw solutions in Objective-C to use KVO to know when music starts playing but I'm thinking this is not the best approach since I'm using swift and also because of glitches that may occur so the song will not stop at the right moment.
You can add a addBoundaryTimeObserverForTimes to your AVPlayer as follow:
update: Xcode 8.3.2 • Swift 3.1
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVPlayer!
var observer: Any!
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://www.example.com/audio.mp3") else { return }
player = AVPlayer(url: url)
let boundary: TimeInterval = 30
let times = [NSValue(time: CMTimeMake(Int64(boundary), 1))]
observer = player.addBoundaryTimeObserver(forTimes: times, queue: nil) {
[weak self] time in
print("30s reached")
if let observer = self?.observer {
self?.player.removeTimeObserver(observer)
}
self?.player.pause()
}
player.play()
print("started loading")
}
}

Play sound effect without latency

I am trying to make a little app to teach myself some swift and I'm having some problems figuring out how to get my app to function a certain way.
My app should be able to play an airhorn sound just like the way it sounds in this video...
https://www.youtube.com/watch?v=Ks5bzvT-D6I
But each time I tap the screen repeatedly there is a slight delay before the sound is played so it's not sounding like that at all.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
var hornSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("horn", ofType: "mp3")!)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: hornSound, error: &error)
audioPlayer.prepareToPlay()
}
#IBAction func playSound(sender: UIButton) {
audioPlayer.pause()
audioPlayer.currentTime = 0
audioPlayer.play()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have also come across this thread about using spritekit
Creating and playing a sound in swift
And in trying that I got it to play the sound without the delay, but with sprite kit I can't stop the existing sound, so they just overlap which is not the effect I want.
Is there a work around to get this working the way it sounds in the video.
Apple recommends AVAudioPlayer for playback of audio data unless you require very low I/O latency.
So you might want to try another approach.
In one of my apps I play countdown sounds by creating a system sound ID from my wav file. Try this in your class:
import UIKit
import AudioToolbox
class ViewController: UIViewController {
var sound: SystemSoundID = 0
override func viewDidLoad() {
super.viewDidLoad()
var hornSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("horn", ofType: "mp3")!)
AudioServicesCreateSystemSoundID(hornSound!, &self.sound)
}
#IBAction func playSound(sender: UIButton) {
AudioServicesPlaySystemSound(self.sound)
}
...
}

Swift. Playing fine mp3 file on simulator, but no volume while playing on device. AVPlayer

Xcode Version - 6.1.1, IOS Version on Device(IPHONE 4S) - 8.1.2
class ViewController2: UIViewController,AVAudioPlayerDelegate {
var player: AVPlayer! = nil
override func viewDidLoad() {
super.viewDidLoad()
var steamingURL:NSURL! = NSURL(string:"http://yflvr.com:8080/data/songs1/mp3/16287239.mp3")
player = AVPlayer(URL: steamingURL)
player.play()
}
}
Check the spelling of your filename. The device is case-sensitive, the simulator is not... Are you sure it is not just delayed?
Also, check if your ringer is off, you won't hear any sound when it's off. To prevent that, use
var session: AVAudioSession = AVAudioSession.sharedInstance();
session.setCategory(AVAudioSessionCategoryPlayback, error: nil)
from here
You can also set an observer on the AVPlayer.status property to debug its changing status
Here they have used AVAudioPlayer and added a call to prepareToPlay()

Resources