Swift 5中如何通过Google Drive API在AVPlayer播放受限音频文件
解决Google Drive受限音频文件的播放问题
好问题!要播放Google Drive中「受限」权限的音频文件,核心是让AVPlayer的资源请求带上有效的OAuth 2.0授权凭证——毕竟受限文件需要验证用户身份,而你已经通过API拿到了用户的授权,只需要把凭证注入到播放请求里就行。
实现思路
AVPlayer本身不支持直接给请求添加自定义HTTP头(比如Authorization),所以我们需要用AVAssetResourceLoaderDelegate来拦截AVPlayer的资源加载请求,手动添加上授权Token,再转发给Google Drive的媒体接口。
具体代码实现
1. 自定义资源加载代理类
这个类负责拦截AVPlayer的请求,添加授权头后再发起实际的网络请求:
import AVKit class DriveAudioResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate { private let authToken: String init(authToken: String) { self.authToken = authToken super.init() } func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool { guard let requestUrl = loadingRequest.request.url else { let error = NSError(domain: "DriveAudioError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求URL"]) loadingRequest.finishLoading(with: error) return false } // 构造带授权头的请求 var authorizedRequest = URLRequest(url: requestUrl) authorizedRequest.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") // 发起网络请求获取音频数据 let task = URLSession.shared.dataTask(with: authorizedRequest) { data, response, error in defer { loadingRequest.finishLoading() } if let error = error { loadingRequest.finishLoading(with: error) return } guard let httpResponse = response as? HTTPURLResponse, let data = data else { let error = NSError(domain: "DriveAudioError", code: -2, userInfo: [NSLocalizedDescriptionKey: "未获取到有效数据或响应"]) loadingRequest.finishLoading(with: error) return } // 把响应信息和数据返回给AVPlayer loadingRequest.contentInformationRequest?.contentType = httpResponse.mimeType loadingRequest.contentInformationRequest?.contentLength = httpResponse.expectedContentLength loadingRequest.dataRequest?.respond(with: data) } task.resume() return true } }
2. 修改播放方法
在你的ViewController中,使用上面的代理类来处理受限文件的播放:
private func playRestrictedTrack(fileId: String, authToken: String) { // 构造Google Drive媒体文件的请求URL(用files.get接口+alt=media参数获取原始媒体数据) guard let mediaUrl = URL(string: "https://www.googleapis.com/drive/v3/files/\(fileId)?alt=media") else { print("无效的文件ID") return } // 创建带资源加载代理的AVURLAsset let asset = AVURLAsset(url: mediaUrl) let resourceDelegate = DriveAudioResourceLoaderDelegate(authToken: authToken) asset.resourceLoader.setDelegate(resourceDelegate, queue: DispatchQueue.global()) // 初始化播放器并开始播放 let playerItem = AVPlayerItem(asset: asset) player = AVPlayer(playerItem: playerItem) player.play() }
关键注意事项
- 权限范围:确保你的OAuth 2.0请求申请了
https://www.googleapis.com/auth/drive.readonly权限(足够访问用户的受限文件),不需要更宽泛的权限。 - Token过期处理:OAuth Token会过期,你需要监听Token的有效期,在过期前完成刷新,避免播放时出现授权失败。
- 错误处理:代码里的错误处理可以根据你的App需求优化,比如弹出提示告知用户授权失效或网络异常。
- 流式播放:这个方案支持流式播放,不需要下载完整音频文件,节省用户流量和设备内存。
内容的提问来源于stack exchange,提问作者Oranutachi
相关产品推荐
相关产品推荐

