Audio files won't play with AirPods Pro on iOS 15
Asked Answered
R

1

5

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()
            }
        }
    }
Roughandready answered 5/11, 2021 at 10:0 Comment(8)
can you show some more of the code? like play(), setupMediaPlayerNotificationView() and lockScreen()?Chavannes
@RhythmicFistman Do you need even more code? Because I don't understand what the problem is. An internet search also gave no results.Roughandready
@RhythmicFistman Maybe the problem is in "m4a"? Maybe I need to use "mp3"? Unfortunately, I do not have AirPods Pro and cannot test it.Roughandready
are there any error in logs? If not.. apple provides technical support on code. You can try to raise TSI with them using your developer account ( i think 2 TSI are included yearly with your developer account and need to pay addtional fees )Inweave
Breaking only with pro air pods? Definitely get some equipment so you can reproduce.Tureen
@Tureen I am updating the question, please checkRoughandready
@AmodGokhale I am updating the question, please checkRoughandready
@RhythmicFistman I am updating the question, please checkRoughandready
V
1

May be it is a problem of iOS 15?
I've found some papers for search query: "sound doesn't play AirPods Pro on ios 15": one, tow, three .
As I understand, this problem was fixed in iOS 15.1. Sometimes Apple makes mistakes (for example, every updating of Xcode :) )

Veradi answered 14/11, 2021 at 10:49 Comment(8)
I got AirPods Pro. There is a problem. I have 2 applications written according to the template but with different topics. In one there is sound, in the second there is no. Rather, it breaks when I rewind the application.Roughandready
If I delete this line setupMediaPlayerNotificationView(true) all works fine but this removes the rewind function.Roughandready
Did I write this function correctly? setupMediaPlayerNotificationView Roughandready
Update question please checkRoughandready
I think it is correct implementation of the registration method. But try to store instances of MBRemoteCommands into some array. It is strange, but may help. Can you share your example project on Github?Veradi
Do you have airpods pro? I would share two projects. Working and not working. Although the code is the same.Roughandready
No, I do not have AirPods at all.Veradi
I am updating the question, please checkRoughandready

© 2022 - 2024 — McMap. All rights reserved.