I am using this code to play audio. My code works fine on iOS 14 with all headphones model, but when customers have updated their devices to iOS 15 and are using AirPods Pro, no audio files play. On other AirPods models and when playing audio files through the iPhone speaker, everything works. What's happened. How to fix it?
Update:
After a long wait, I was given AirPods Pro. And at first I removed that line setupMediaPlayerNotificationView(true)
and the app played a sound fine. But some of the functions on Lock Screen were removed. And with this line in the app there was no sound. In the App Store, I had 3 apps with the same code. And after ios 15 only one worked. And I did not understand in any way what is the reason if the code is the same. Why aren't the others working? But it turned out that the app that worked had 1 word in its name - Build Settings -> Product Name -> "myAppName"
. And the rest had a few words. And when I renamed them to 1 word everything working fine. Sound play fine. What was it? I still don't understand? If anyone has a version, share it.
code:
let url = Bundle.main.url(forResource: "\(masterIndex)0", withExtension: "m4a")!
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
play(sender:AnyObject.self as AnyObject)
setupMediaPlayerNotificationView(true)
lockScreen()
} catch {
}
other code:
func lockScreen() {
var albumArtwork : MPMediaItemArtwork!
let image:UIImage = UIImage(named: "infoImage")!
albumArtwork = MPMediaItemArtwork.init(boundsSize: image.size, requestHandler: { (size) -> UIImage in
return image
})
let infotitle = "\(firstArray[index])"
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
MPMediaItemPropertyArtist : "",
MPMediaItemPropertyTitle : infotitle,
MPMediaItemPropertyArtwork : albumArtwork,
MPMediaItemPropertyAlbumTitle : "",
MPNowPlayingInfoPropertyElapsedPlaybackTime : Int(audioPlayer.currentTime),
MPMediaItemPropertyPlaybackDuration: Int(audioPlayer.duration)]
}
@objc func lockScreenPlay(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
self.audioPlayer.play()
self.lockScreen()
self.playButton.setImage(UIImage(named: "pause.png"), for: UIControlState.normal)
return .success
}
@objc func lockScreenPause(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
self.audioPlayer.pause()
self.lockScreen()
self.playButton.setImage(UIImage(named: "play.png"), for: UIControlState.normal)
return .success
}
@objc func lockScreenFastForward(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
var time: TimeInterval = audioPlayer.currentTime
time += 15.0
if time > audioPlayer.duration {
audioPlayerDidFinishPlaying(audioPlayer, successfully: true)
} else {
audioPlayer.currentTime = time
updateTime()
}
self.lockScreen()
return .success
}
@objc func lockScreenFastBackward(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
var time: TimeInterval = audioPlayer.currentTime
time -= 15.0
if time < 0 {
audioPlayer.currentTime = 0
updateTime()
} else {
audioPlayer.currentTime = time
updateTime()
}
self.lockScreen()
return .success
}
@objc func changedThumbSlider(_ event: MPChangePlaybackPositionCommandEvent) -> MPRemoteCommandHandlerStatus {
let time = event.positionTime
audioPlayer.currentTime = TimeInterval(time)
self.lockScreen()
return .success
}
func setupMediaPlayerNotificationView(_ enable: Bool) {
let commandCenter = MPRemoteCommandCenter.shared()
if enable {
commandCenter.playCommand.addTarget(self, action: #selector(lockScreenPlay))
commandCenter.pauseCommand.addTarget(self, action: #selector(lockScreenPause))
commandCenter.skipForwardCommand.preferredIntervals = [15]
commandCenter.skipForwardCommand.addTarget(self, action: #selector(lockScreenFastForward))
commandCenter.skipBackwardCommand.preferredIntervals = [15]
commandCenter.skipBackwardCommand.addTarget(self, action: #selector(lockScreenFastBackward))
commandCenter.changePlaybackPositionCommand.addTarget(self, action: #selector(self.changedThumbSlider(_:)))
} else {
commandCenter.playCommand.removeTarget(self, action: #selector(lockScreenPlay))
commandCenter.pauseCommand.removeTarget(self, action: #selector(lockScreenPause))
commandCenter.skipForwardCommand.removeTarget(self, action: #selector(lockScreenFastForward))
commandCenter.skipBackwardCommand.removeTarget(self, action: #selector(lockScreenFastBackward))
commandCenter.changePlaybackPositionCommand.removeTarget(self, action: #selector(self.changedThumbSlider(_:)))
}
}
@IBAction func play(sender: AnyObject) {
if !audioPlayer.isPlaying{
animationStatus()
audioPlayer.play()
slider.maximumValue = Float(audioPlayer.duration)
timer = Timer(timeInterval: 0.1, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)
RunLoop.main.add(timer!, forMode: .commonModes)
restorePlayerCurrentTime()
playButton.setImage(UIImage(named: "pause.png"), for: UIControlState.normal)
} else {
animationStatus()
audioPlayer.pause()
playButton.setImage(UIImage(named: "play.png"), for: UIControlState.normal)
timer?.invalidate()
}
}
@IBAction func fastForward(sender: AnyObject) {
var time: TimeInterval = audioPlayer.currentTime
time += 15.0 // Go Forward by 15 Seconds
if time > audioPlayer.duration {
audioPlayerDidFinishPlaying(audioPlayer, successfully: true)
} else {
audioPlayer.currentTime = time
updateTime()
}
self.lockScreen()
}
@IBAction func fastBackward(sender: AnyObject) {
var time: TimeInterval = audioPlayer.currentTime
time -= 15.0 // Go Back by 15 Seconds
if time < 0 {
audioPlayer.currentTime = 0
updateTime()
} else {
audioPlayer.currentTime = time
updateTime()
}
self.lockScreen()
}
private func restorePlayerCurrentTime() {
let currentTimeFromUserDefaults : Double? = UserDefaults.standard.value(forKey: "currentTime\(masterIndex)\(index)") as! Double?
if let currentTimeFromUserDefaultsValue = currentTimeFromUserDefaults {
audioPlayer.currentTime = currentTimeFromUserDefaultsValue
slider.value = Float.init(audioPlayer.currentTime)
}
}
@objc func updateTime() {
let currentTime = Int(audioPlayer.currentTime)
let minutes = currentTime/60
let seconds = currentTime - minutes * 60
let durationTime = Int(audioPlayer.duration) - Int(audioPlayer.currentTime)
let minutes1 = durationTime/60
let seconds1 = durationTime - minutes1 * 60
timeElapsed.text = NSString(format: "%02d:%02d", minutes,seconds) as String
timeDuration.text = NSString(format: "-%02d:%02d", minutes1,seconds1) as String
UserDefaults.standard.set(currentTime, forKey: "currentTime\(masterIndex)\(index)")
UserDefaults.standard.set(durationTime, forKey: "durationTime\(masterIndex)\(index)")
slider.value = Float.init(audioPlayer.currentTime)
}
func audioPlayerDidFinishPlaying(_ audioPlayer: AVAudioPlayer, successfully flag: Bool) {
let currentTime = 0
let durationTime = 0.1
UserDefaults.standard.set(currentTime, forKey: "currentTime\(masterIndex)\(index)")
UserDefaults.standard.set(durationTime, forKey: "durationTime\(masterIndex)\(index)")
slider.value = Float.init(audioPlayer.currentTime)
timer?.invalidate()
let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = FileManager()
let destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/\(masterIndex)/\(index+1).mp3"))
if fileManager.fileExists(atPath: destinationURLForFile.path){
if endOfChapterSleepTimer == true {
endOfChapterSleepTimer = false
} else {
index = index + 1
viewDidLoad()
}
} else {
}
}
func animationStatus() {
let vinylLayer = vinylView.layer
pause = !pause
if pause {
pauseLayer(layer: vinylLayer)
} else {
if vinylStatus == "true" {
resumeLayer(layer: vinylLayer)
} else {
rotateImageView()
resumeLayer(layer: vinylLayer)
}
}
}
private func rotateImageView() {
vinylStatus = "true"
UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
self.vinylView.transform = self.vinylView.transform.rotated(by: .pi / 2)
}) { (finished) in
if finished {
self.rotateImageView()
}
}
}
play()
,setupMediaPlayerNotificationView()
andlockScreen()
? – Chavannes