How to stream remote audio in iOS 13? (SwiftUI)
In SwiftUI, Views are value types. They are only data that describe the things on screen. They can be created or destroyed or copied at any time. AVPlayer is a reference to a specific player object. You're assuming here that it will continue to exist, and there will only be one of them. That's not something that a SwiftUI View provides.
You need to move your AVPlayer outside of the View (into Model objects), and just bind UI actions to it.
How to play audio using AVAudioPlayer in SwiftUI project
Is the audiofile there? Please select the project, go to Build Phases tab and under 'Copy Bundle Resources' you must see the audio file. If it is there then the problem is this.
I tried your code, it played the sound and then crashed. i changed it like this to make it work
@State var audioPlayer:AVAudioPlayer?
@State var isPlaying : Bool = false
var body: some View {
Button(action: {
if let path = Bundle.main.path(forResource: "a", ofType: ".mp3") {
self.audioPlayer = AVAudioPlayer()
self.isPlaying.toggle()
let url = URL(fileURLWithPath: path)
do {
self.audioPlayer = try AVAudioPlayer(contentsOf: url)
self.audioPlayer?.prepareToPlay()
self.audioPlayer?.play()
}catch {
print("Error")
}
}
}, label: {
----
Have you considered separating your Audio model from your UI? It would make your code much clearer if you put it into separate Swift file
import AVFoundation
class Sounds {
static var audioPlayer:AVAudioPlayer?
static func playSounds(soundfile: String) {
if let path = Bundle.main.path(forResource: soundfile, ofType: nil){
do{
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
}catch {
print("Error")
}
}
}
}
And just one line to use it in UI
var body: some View {
Button(action: {
self.isPlaying.toggle()
Sounds.playSounds(soundfile: "0.wav")
}, label: {
How to play mp3 audio from URL in iOS Swift?
I tried the following:-
let urlstring = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tailtoddle_lo4.mp3"
let url = NSURL(string: urlstring)
print("the url = \(url!)")
downloadFileFromURL(url!)
Add the below methods:-
func downloadFileFromURL(url:NSURL){
var downloadTask:NSURLSessionDownloadTask
downloadTask = NSURLSession.sharedSession().downloadTaskWithURL(url, completionHandler: { [weak self](URL, response, error) -> Void in
self?.play(URL)
})
downloadTask.resume()
}
And your play method as it is:-
func play(url:NSURL) {
print("playing \(url)")
do {
self.player = try AVAudioPlayer(contentsOfURL: url)
player.prepareToPlay()
player.volume = 1.0
player.play()
} catch let error as NSError {
//self.player = nil
print(error.localizedDescription)
} catch {
print("AVAudioPlayer init failed")
}
}
Download the mp3 file and then try to play it, somehow AVAudioPlayer does not download your mp3 file for you. I am able to download the audio file and player plays it.
Remember to add this in your info.plist since you are loading from a http source and you need the below to be set for iOS 9+
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</plist>
Using AVAudioPlayer to play remote mp3 file in Swift
Try this code :
You need to add AVKit
& AVFoundation
to your frameworks
path and import them :
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
var player = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func localPress(_ sender: Any) {
let path = Bundle.main.resourcePath!+"/sound.mp3"
print(path)
let url = URL(fileURLWithPath: path)
let playerItem = AVPlayerItem(url: url)
player = AVPlayer(playerItem: playerItem)
player.play()
}// i have created a btn for playing a local file, this is it's action
@IBAction func urlPressed(_ sender: Any) {
let playerItem = AVPlayerItem(url: URL(string: "https://yourURL.mp3")!)
player = AVPlayer(playerItem: playerItem)
player.play()
}// i have created another btn for playing a URL file, this is it's action
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
How to play audio from an http data stream in swiftUI?
Use https instead of the http you are using, because:
"iOS 9.0 and macOS 10.11 and later use App Transport Security (ATS)
for all HTTP connections made with URLSession. ATS requires that HTTP connections use HTTPS (RFC 2818)."
however;
"You can circumvent or augment these protections by adding the
NSAppTransportSecurity key to your app’s Information Property List
file and providing an ATS configuration dictionary as the value."
That is adding exceptions in the Info.plist file.
see "https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity"
playing a url link instead of a .mp3 file in swiftui
You can use AVPlayer
to stream resources from a URL like this. I'd also move the streaming/async logic into an ObservableObject
:
class SoundManager : ObservableObject {
var audioPlayer: AVPlayer?
func playSound(sound: String){
if let url = URL(string: sound) {
self.audioPlayer = AVPlayer(url: url)
}
}
}
struct ContentView: View {
@State var song1 = false
@StateObject private var soundManager = SoundManager()
var body: some View {
Image(systemName: song1 ? "pause.circle.fill": "play.circle.fill")
.font(.system(size: 25))
.padding(.trailing)
.onTapGesture {
soundManager.playSound(sound: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3")
song1.toggle()
if song1{
soundManager.audioPlayer?.play()
} else {
soundManager.audioPlayer?.pause()
}
}
}
}
Related Topics
How to Manage Swiftui State with Nested Structs
Create View Based Nstableview Programmatically Using Bindings in Swift
Lazy Property Initialization in Swift
Sktextureatlas No Longer Sharing Textures in iOS 10
Wrapping a Generic Method in a Class Extension
Using Compiler Variables in Swift
Firebasefirestoreswift Won't Install (Cocoapods)
Swift Encode Tuple Using Nscoding
Split Uint32 into [Uint8] in Swift
Function That Takes a Protocol and a Conforming Class (!) Instance as Parameters
Swift/Firebase - Sort Posts in Tableview by Date
Retrieve Multiple Photos Under a Node from Firebase Storage
Nsimage Getting Resized When I Draw Text on It
Difference Between Nsrange and Nsmakerange
Making Parts of Text Bold in Swiftui
Session.Datataskwithurl Completionhandler Never Called
Filter Realm Objects to Only Get One (Distinct) Object by Attribute