简体   繁体   中英

How to correctly handle AVPlayer HTTP error?

When requesting to play a mp3 file from a web server, if that server returns a 403 forbidden it is not clear how to handle the error when examining the AVPlayer current item error.

Error message from AVPlayer doesn't indicate that it is a 403...

2019-01-05 13:08:33.908316-0500 Runner[84043:3269818] Optional(Error Domain=AVFoundationErrorDomain Code=-11828 "Cannot Open" UserInfo={NSLocalizedFailureReason=This media format is not supported., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x600000781290 {Error Domain=NSOSStatusErrorDomain Code=-12847 "(null)"}})

The error says the media isn't supported, but the media was never even reached. Is there anyway to see the HTTP error code from AVPlayer requests?

When testing the same file on Android, I am able to correctly see a 403 error code from Android native MediaPlayer (the error from Android is better and more useful than iOS's AVPlayer).

This lack of proper error messaging makes it very difficult to gracefully display an accurate error to the user.

Arbitrary Code sample:

    let url = URL(string: "some 403 server url")
    let playerItem:AVPlayerItem = AVPlayerItem(url: url!)
    player = AVPlayer(playerItem: playerItem)
    player.play()

Checking the error will print the above quoted message.

NSLog("\(String(describing: player.currentItem?.error))")

Use KVO to Observe the playItem's status like this:

self.playItem.addObserver(self, forKeyPath: "status", options: .new, context: nil)

Then in the method :

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let playerItem = object as! AVPlayerItem
        if keyPath == "status", playerItem.status == .failed{
            if let error = playerItem.error as NSError? {
                let errorCode = error.code
            }
        }
}

You can find the codes defines here: documentation

Here's a possible solution, Rather than initializing the AVPlayerItem with a url

You can try this approach

  1. Use AVURLAsset and set the AVAssetResourceLoaderDelegate

  2. Use the delegate method func resourceLoader(_ resourceLoader:AVAssetResourceLoader, didCancel authenticationChallenge: URLAuthenticationChallenge)

  3. Proceed to create the player and play audio, The delegate method will let you know when there is a 403 error.

Here's the sample code

class ResourceLoadingDelegate:NSObject, AVAssetResourceLoaderDelegate {
      func resourceLoader(_ resourceLoader: AVAssetResourceLoader,
                    didCancel authenticationChallenge:  URLAuthenticationChallenge) {
    /// handle the authentication challenge
    print(authenticationChallenge.error.debugDescription)
   }
}

   let asset = AVURLAsset(url: URL(string: "some 403 url")!)

   asset.resourceLoader.setDelegate(ResourceLoadingDelegate(), queue:  DispatchQueue.global(qos: .userInitiated))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM