From b75ea9e4ce18a0f2210b563c8183b8a5e0b74284 Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Mon, 24 Aug 2026 23:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8E=B0=E5=9C=A8=E7=89=88=E6=9C=AC=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E9=80=9A=E7=9F=A5=E4=B8=AD=E5=BF=83=E7=9A=84=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=9D=A1=E6=8B=96=E5=8A=A8seek=E8=83=BD=E5=8A=9B?= =?UTF-8?q?=E8=BE=B9=E7=95=8C=E9=97=AE=E9=A2=98=E5=B7=B2=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/services/audio_player_handler.dart | 3 +++ lib/services/audio_service.dart | 37 ++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/services/audio_player_handler.dart b/lib/services/audio_player_handler.dart index b516677..f2ba0e9 100644 --- a/lib/services/audio_player_handler.dart +++ b/lib/services/audio_player_handler.dart @@ -78,6 +78,9 @@ class AudioPlayerHandler extends audio_service.BaseAudioHandler { androidCompactActionIndices: state.androidCompactActionIndices, updatePosition: _currentPosition, updateTime: DateTime.now(), + systemActions: const { + audio_service.MediaAction.seek, + }, )); } diff --git a/lib/services/audio_service.dart b/lib/services/audio_service.dart index 329af3e..1bf4d27 100644 --- a/lib/services/audio_service.dart +++ b/lib/services/audio_service.dart @@ -41,7 +41,7 @@ class AudioService extends ChangeNotifier { List _shuffledIndices = []; int _shuffledIndex = -1; - // ---- 高频进度 ---- + // ---- 高频进度(ValueNotifier,不触发全局重建) ---- final ValueNotifier positionNotifier = ValueNotifier(Duration.zero); final ValueNotifier durationNotifier = ValueNotifier(Duration.zero); final ValueNotifier bufferedNotifier = ValueNotifier(Duration.zero); @@ -52,6 +52,9 @@ class AudioService extends ChangeNotifier { bool _handlingCompletion = false; void Function(Song)? _onSongChanged; + // ⭐ 防 seek 覆盖标志 + bool _isUserSeeking = false; + // ---- Getter ---- Song? get currentSong => _currentSong; bool get isPlaying => _isPlaying; @@ -75,10 +78,12 @@ class AudioService extends ChangeNotifier { } } + // ---- 注册回调 ---- void setOnSongChanged(void Function(Song) callback) { _onSongChanged = callback; } + // ---- 切换播放模式 ---- void togglePlayMode() { switch (_playMode) { case PlayMode.sequential: @@ -94,6 +99,7 @@ class AudioService extends ChangeNotifier { notifyListeners(); } + // ---- 设置播放队列 ---- void setQueue(List queue, {int startIndex = 0}) { if (queue.isEmpty) { _clearQueue(); @@ -122,6 +128,7 @@ class AudioService extends ChangeNotifier { stopPlay(); } + // ---- 播放指定歌曲 ---- Future playSong(Song song) async { if (_queue.isEmpty || _queue[_currentIndex].id != song.id) { setQueue([song], startIndex: 0); @@ -130,6 +137,7 @@ class AudioService extends ChangeNotifier { } } + // ---- 核心:播放当前歌曲 ---- void _playCurrent() { if (_currentIndex < 0 || _currentIndex >= _queue.length) { stopPlay(); @@ -148,12 +156,13 @@ class AudioService extends ChangeNotifier { PlaybackService().play(song.url!); - // ⭐ 延迟同步兜底 + // 延迟同步兜底(解决首次加载时 stream 未推送的问题) _syncPlayerStateDelayed(); _loadMetadataForCurrentSong(); } + // ---- 加载 metadata ---- Future _loadMetadataForCurrentSong() async { if (_currentIndex < 0 || _currentIndex >= _queue.length) return; final song = _queue[_currentIndex]; @@ -183,6 +192,7 @@ class AudioService extends ChangeNotifier { } } + // ---- 下一首 ---- void next() { if (_queue.isEmpty) return; @@ -200,6 +210,7 @@ class AudioService extends ChangeNotifier { _playCurrent(); } + // ---- 上一首 ---- void previous() { if (_queue.isEmpty) return; @@ -225,6 +236,7 @@ class AudioService extends ChangeNotifier { _playCurrent(); } + // ---- 播放/暂停 ---- void togglePlay() { if (_currentSong == null) return; @@ -235,6 +247,7 @@ class AudioService extends ChangeNotifier { } } + // ---- 停止播放 ---- void stopPlay() { _currentSong = null; _isPlaying = false; @@ -245,11 +258,19 @@ class AudioService extends ChangeNotifier { notifyListeners(); } + // ---- 跳转 ---- void seekTo(Duration position) { + _isUserSeeking = true; PlaybackService().seek(position); positionNotifier.value = position; + + // 800ms 后重置标志(覆盖 media_kit 的 positionStream 推送窗口) + Future.delayed(const Duration(milliseconds: 800), () { + _isUserSeeking = false; + }); } + // ---- 清空队列 ---- void clearQueue() { _queue.clear(); _currentIndex = -1; @@ -259,7 +280,7 @@ class AudioService extends ChangeNotifier { notifyListeners(); } - // ⭐ 公开方法:供 PlayerPage 主动同步 + // ---- 主动状态同步(供 PlayerPage 调用) ---- void syncPlayerStateNow() { final player = PlaybackService().player; final pos = player.state.position; @@ -269,7 +290,6 @@ class AudioService extends ChangeNotifier { debugPrint( '🎯 [AudioService] syncPlayerStateNow: pos=$pos, dur=$dur, buf=$buf'); - // ⭐ 无条件更新(不要只判断 == 0) if (pos.inMilliseconds >= 0) { positionNotifier.value = pos; } @@ -281,6 +301,7 @@ class AudioService extends ChangeNotifier { } } + // ---- 延迟同步(兜底) ---- void _syncPlayerStateDelayed() { syncPlayerStateNow(); Future.delayed(const Duration(milliseconds: 200), () { @@ -291,7 +312,7 @@ class AudioService extends ChangeNotifier { }); } - // ---- 监听 ---- + // ---- 监听 media_kit 状态 ---- void _startListening() { if (_listening) return; _listening = true; @@ -309,6 +330,11 @@ class AudioService extends ChangeNotifier { _subscriptions.add( player.stream.position.listen((position) { + // ⭐ 如果是用户主动 seek,忽略这次推送(避免覆盖) + if (_isUserSeeking) { + debugPrint('🎯 [AudioService] positionStream ignored: user seeking'); + return; + } positionNotifier.value = position; }), ); @@ -343,6 +369,7 @@ class AudioService extends ChangeNotifier { _subscriptions.clear(); } + // ---- 防重入的完成事件处理 ---- void _onPlaybackCompleted() { if (_handlingCompletion) { debugPrint('⚠️ [service] completed ignored: already handling');