In my venture it really works very effectively to play all of the sounds I would like for a Meditation Timer. Now I wish to let the customers select music from their iPhone storage to then play the music when the timer is operating.
I constructed the timer simply utilizing a music file that I dragged into my venture and it really works wonderful as all the time.
Then I attempted placing the URL from the storage file, that the person selected. However nothing is enjoying. The timer runs with none drawback and there are not any errors thrown. Is it even potential to make use of AVAudioPlayer to play media exterior to the venture? I noticed some examples the place individuals used it to play media from a Net URL. So I guessed it ought to work.
Listed here are the required code snippets and likewise a screenshot of the File URL that’s chosen after which saved by the person.
import SwiftUI
import SwiftData
import AVFoundation /// For taking part in any sound
import AVKit /// For the AirPlay Button
import MediaPlayer /// For getting the Quantity Slider hooked up to the units quantity.
import CoreHaptics /// For making vibrations as soon as the timer is run out
struct TimerTapasMusicView: View {
@Setting(.dismiss) var dismiss /// To have the ability to dismiss the view
@State var countdownTimer = 5 * 60 /// The precise seconds of the timer, being counted down/up
@State var timerRunning = true /// Var to set and see if timer is operating
@State var gongSound: AVAudioPlayer? /// The Sound of the timer
**@State var musicSound: AVAudioPlayer? /// The Sound of the music**
@State personal var hours: Int = 0 /// Vars for the picker wheel
@State personal var minutes: Int = 0
@State personal var seconds: Int = 0
@State personal var brightnessLow = false/// Var for saving if the brightness button was used
@State personal var engine: CHHapticEngine? /// The thing creating the vibrations afterward
@Setting(.scenePhase) var scenePhase /// Var to maintain monitor of state of app, to restart HapticEngine
/// Setting Objects
@EnvironmentObject var userStat: StatisticsObject /// Var to maintain monitor of seconds utilizing the Timer
@EnvironmentObject var envObject: EnvObject /// For getting FullDarkness, vibrateTimer
/// Getting the Asana
@State var asana: TapasAsana
**let path = Bundle.predominant.path(forResource: "bell_basu.mp3", ofType:nil)!
let musicPath = Bundle.predominant.path(forResource: "authen.mp3", ofType:nil)!
let volumeView = MPVolumeView()**
var physique: some View {
/// For calculating hours, minutes, seconds
let fashion = Period.TimeFormatStyle(sample: .minuteSecond)
//let formTimer = Period.seconds(countdownTimer).formatted()
let formTimerShort = Period.seconds(countdownTimer).formatted(fashion)
**let url = URL(fileURLWithPath: path)
let musicUrl = asana.musicFile //URL(fileURLWithPath: musicPath)**
VStack {
/// The slider for the system quantity
HStack{
VolumeSliderView()
.body(width: 250, top: 25)
.offset(y: 5)
RouteButtonView()
.body(width: 50, top: 50)
}
.padding(.high, 40)
/// The buttons when the timer is operating
TimerTopButtonsView()
Textual content("(asana.identify)")
.font(.system(measurement: 50))
.padding(.backside, -100)
/// The principle Timer If there are not any hours we disguise the hour quantity and make the timer greater on this approach.
Textual content("(formTimerShort)")
.onAppear(carry out: prepareHaptics) /// Making ready the Vibration Object
.onChange(of: scenePhase) { /// When app will get closed and reopnened, begin Haptic once more
prepareHaptics()
}
.onReceive(Timer.publish(each: 1, on: .predominant, in: .widespread).autoconnect()) { _ in
if countdownTimer > 0 && timerRunning {
countdownTimer -= 1
}
else if countdownTimer == 5 {
gongSound?.prepareToPlay()
} else {
timerRunning = false
}
/// Performs the gong sound when timer hits 0 after operating
if countdownTimer == 0 && timerRunning {
do {
gongSound = strive AVAudioPlayer(contentsOf: url)
gongSound?.play()
envObject.fullDarkness = false
timerRunning = false
timerVibration()
/// Including the seconds of lastTime to the TimerUsed stat
userStat.timerDuration += asana.length
UserDefaults.commonplace.set(userStat.timerDuration, forKey: "TimerDuration")
/// When the Timer is completed we now have performed the Asana and the Timer is dismissed.
asana.doneToday = true
asana.recoupCount = 0
} catch {
//Could not Load File.
}
}
}
.body(width: 500, top: 220)
/// Change the scale relying if it is just minutes after which solely when timer operating
.font(.system(measurement: 140))
.monospacedDigit() /// Makes the numbers mounted in measurement and place.
.onTapGesture { gongSound?.cease() } /// Tapping it stops the sound.
.padding(.high, 30)
.padding(.backside, 30)
/// Prevents gadget from sleep on seem and permits sleep on disappear
.onAppear{
UIApplication.shared.isIdleTimerDisabled = true
if (asana.recoupCount == 0 ) { countdownTimer = asana.length }
else { countdownTimer = asana.length * (asana.recoupCount + 1) }
**do {
musicSound = strive AVAudioPlayer(contentsOf: musicUrl)
musicSound?.play()
musicSound?.numberOfLoops = 10000**
} catch {
}
}
.onDisappear{UIApplication.shared.isIdleTimerDisabled = false}
.toolbar(.hidden, for: .tabBar)
.... And extra Code that I believe just isn't vital right here.
Right here I’m letting the person select a file from their Storage:
} else if asana.executionType == "music" {
Button("Select Music File") {
chooseMusic = true
}
.fileImporter(isPresented: $chooseMusic, allowedContentTypes: [.item]) {end in
swap outcome {
case .success(let Fileurl):
print(Fileurl)
asana.musicFile = Fileurl
case .failure(let error):
print(error)
}
}
Textual content("File Title: (asana.musicFile)")
And it is a Screenshot of the URL, perhaps I’m saving it in a unsuitable approach.