Flutter使用just_audio播放Google Drive音频链接报错求助
解决just_audio播放Google Drive音频的错误问题
问题说明
尝试通过just_audio插件直接播放存储在Google Drive中的音频文件,传入分享链接后持续出现播放错误。
相关代码
// ignore_for_file: library_private_types_in_public_api, avoid_print import 'package:connectivity/connectivity.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; import 'package:fluttertoast/fluttertoast.dart'; class HymnTune extends StatefulWidget { final String hymnMusicPath; const HymnTune({super.key, required this.hymnMusicPath}); @override _HymnTuneState createState() => _HymnTuneState(); } class _HymnTuneState extends State<HymnTune> with SingleTickerProviderStateMixin { late AnimationController iconController; bool isPlaying = false; double iconSize = 30.0; final AudioPlayer hymnTunePlayer = AudioPlayer(); @override void initState() { super.initState(); iconController = AnimationController( vsync: this, duration: const Duration(milliseconds: 100), ); loadMusic(); } Future<void> loadMusic() async { if (widget.hymnMusicPath.isNotEmpty) { try { await hymnTunePlayer.setAudioSource(AudioSource.uri(Uri.parse(widget.hymnMusicPath))); } catch (e) { Fluttertoast.showToast( msg: "Error loading audio source: $e", textColor: Colors.white, backgroundColor: Colors.black45, toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, ); } } } Future<bool> checkInternetConnection() async { var connectivityResult = await Connectivity().checkConnectivity(); return connectivityResult != ConnectivityResult.none; } void showNoInternetToast() { Fluttertoast.showToast( msg: 'No Internet Connection', textColor: Colors.white, backgroundColor: Colors.black45, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, ); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () => animateIcon(), child: AnimatedIcon( icon: AnimatedIcons.play_pause, progress: iconController, size: iconSize, ), ); } void animateIcon() async { if (widget.hymnMusicPath.isNotEmpty) { bool isConnected = await checkInternetConnection(); if (!isConnected) { showNoInternetToast(); return; } setState(() { isPlaying = !isPlaying; }); if (isPlaying) { await iconController.forward(); await hymnTunePlayer.play(); } else { await iconController.reverse(); await hymnTunePlayer.pause(); } } } @override void dispose() { hymnTunePlayer.dispose(); iconController.dispose(); super.dispose(); } }
错误日志
E/ExoPlayerImplInternal( 9612): at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:549) E/ExoPlayerImplInternal( 9612): at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105) E/ExoPlayerImplInternal( 9612): at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:26) E/ExoPlayerImplInternal( 9612): at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:559) E/ExoPlayerImplInternal( 9612): at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:376) E/ExoPlayerImplInternal( 9612): ... 7 more E/ExoPlayerImplInternal( 9612): Caused by: java.net.SocketException: socket is closed E/ExoPlayerImplInternal( 9612): at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:551) E/ExoPlayerImplInternal( 9612): at com.android.okhttp.okio.Okio$2.read(Okio.java:136) E/ExoPlayerImplInternal( 9612): at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211) E/ExoPlayerImplInternal( 9612): ... 21 more E/AudioPlayer( 9612): TYPE_SOURCE: java.net.SocketTimeoutException: timeout I/ExoPlayerImpl( 9612): Release 59b3258 [ExoPlayerLib/2.18.7] [Infinix-X626B, Infinix X626B, INFINIX MOBILITY LIMITED, 28] [goog.exo.core, goog.exo.exoplayer, goog.exo.decoder, goog.exo.datasource] I/ExoPlayerImpl( 9612): Init a576746 [ExoPlayerLib/2.18.7] [Infinix-X626B, Infinix X626B, INFINIX MOBILITY LIMITED, 28] D/ViewRootImplToast: hardware acceleration = true , fakeHwAccelerated = false, sRendererDisabled = false, forceHwAccelerated = false, sSystemRendererDisabled = false D/Surface ( 9612): Surface::allocateBuffers(this=0x72d948e000) D/OpenSSLLib( 9612): OpensslErr:Module:30(110:); file:external/boringssl/src/crypto/fipsmodule/cipher/cipher.c ;Line:563;Function:EVP_CIPHER_CTX_set_key_length W/RenderThread( 9612): type=1400 audit(0.0:1891): avc: denied { search } for name="battery" dev="sysfs" ino=6960 scontext=u:r:untrusted_app:s0:c118,c256,c512,c768 tcontext=u:object_r:sysfs_batteryinfo:s0 tclass=dir permissive=0 D/Surface ( 9612): Surface::connect(this=0x72d948e000,api=1) D/Surface ( 9612): Surface::disconnect(this=0x72d948e000,api=1) D/View ( 9612): [Warning] assignParent to null: this = android.widget.FrameLayout{212b1d2 V.E...... ......ID 0,0-525,73}
解决方案
- 修正Google Drive链接格式:默认的Google Drive分享链接(如
https://drive.google.com/file/d/[FILE_ID]/view)无法直接被音频播放器识别,需要转换为可直接访问的资源链接。将链接替换为:https://drive.google.com/uc?export=open&id=[FILE_ID],其中[FILE_ID]是原链接中/d/和/view之间的字符串。同时确保音频文件的分享权限设置为「任何有链接的人都可以查看」。 - 处理超时问题:错误日志中出现
SocketTimeoutException,可通过配置just_audio的数据源参数延长超时时间。修改loadMusic方法,自定义HttpDataSource:await hymnTunePlayer.setAudioSource( AudioSource.uri( Uri.parse(widget.hymnMusicPath), headers: {}, ), dataSourceResolver: (Uri uri) async { return HttpDataSource( uri, connectTimeout: const Duration(seconds: 10), readTimeout: const Duration(seconds: 10), ); }, ); - 优化音频加载逻辑:避免在
initState中过早加载音频,可改为在用户点击播放按钮时再加载,防止链接过期或网络波动导致的加载失败。修改animateIcon方法,在播放前检查音频是否已加载,未加载则重新加载:void animateIcon() async { if (widget.hymnMusicPath.isNotEmpty) { bool isConnected = await checkInternetConnection(); if (!isConnected) { showNoInternetToast(); return; } setState(() { isPlaying = !isPlaying; }); if (isPlaying) { if (hymnTunePlayer.processingState == ProcessingState.idle) { await loadMusic(); } await iconController.forward(); await hymnTunePlayer.play(); } else { await iconController.reverse(); await hymnTunePlayer.pause(); } } } - 验证链接可用性:在浏览器中打开转换后的链接,确认能直接播放或下载音频,排除链接本身的访问问题。
内容的提问来源于stack exchange,提问作者Igwe Ugochukwu
相关产品推荐
相关产品推荐

