fix: 多层播放页快速返回首页致后台播放、通知未消失

This commit is contained in:
orz12
2024-06-01 12:06:50 +08:00
parent 8df87556b7
commit 62e0a0c588
4 changed files with 113 additions and 35 deletions

View File

@@ -282,6 +282,41 @@ class PlPlayerController {
} }
} }
static bool instanceExists() {
return _instance != null;
}
static Future<void> playIfExists(
{bool repeat = false, bool hideControls = true, dynamic duration}) async {
await _instance?.play(
repeat: repeat, hideControls: hideControls, duration: duration);
}
// try to get PlayerStatus
static PlayerStatus? getPlayerStatusIfExists() {
return _instance?.playerStatus.status.value;
}
static Future<void> pauseIfExists(
{bool notify = true, bool isInterrupt = false}) async {
if (_instance?.playerStatus.status.value == PlayerStatus.playing) {
await _instance?.pause(notify: notify, isInterrupt: isInterrupt);
}
}
static Future<void> seekToIfExists(Duration position, {type = 'seek'}) async {
await _instance?.seekTo(position, type: type);
}
static double? getVolumeIfExists() {
return _instance?.volume.value;
}
static Future<void> setVolumeIfExists(double volumeNew,
{bool videoPlayerVolume = false}) async {
await _instance?.setVolume(volumeNew, videoPlayerVolume: videoPlayerVolume);
}
// 添加一个私有构造函数 // 添加一个私有构造函数
PlPlayerController._() { PlPlayerController._() {
_videoType = videoType; _videoType = videoType;
@@ -439,8 +474,9 @@ class PlPlayerController {
} }
}); });
} }
} catch (err) { } catch (err, stackTrace) {
dataStatus.status.value = DataStatus.error; dataStatus.status.value = DataStatus.error;
debugPrint(stackTrace.toString());
print('plPlayer err: $err'); print('plPlayer err: $err');
} }
} }
@@ -564,6 +600,7 @@ class PlPlayerController {
Duration seekTo = Duration.zero, Duration seekTo = Duration.zero,
Duration? duration, Duration? duration,
}) async { }) async {
if (_instance == null) return;
// 设置倍速 // 设置倍速
if (videoType.value == 'live') { if (videoType.value == 'live') {
await setPlaybackSpeed(1.0); await setPlaybackSpeed(1.0);
@@ -586,7 +623,8 @@ class PlPlayerController {
// 自动播放 // 自动播放
if (_autoPlay) { if (_autoPlay) {
await play(duration: duration); await playIfExists(duration: duration);
// await play(duration: duration);
} }
} }
@@ -781,6 +819,7 @@ class PlPlayerController {
/// TODO _duration.value丢失 /// TODO _duration.value丢失
Future<void> play( Future<void> play(
{bool repeat = false, bool hideControls = true, dynamic duration}) async { {bool repeat = false, bool hideControls = true, dynamic duration}) async {
if (_playerCount.value == 0) return;
// 播放时自动隐藏控制条 // 播放时自动隐藏控制条
controls = !hideControls; controls = !hideControls;
// repeat为true将从头播放 // repeat为true将从头播放
@@ -1237,10 +1276,12 @@ class PlPlayerController {
return; return;
} }
Map<String, String> s = _vttSubtitles[index]; Map<String, String> s = _vttSubtitles[index];
debugPrint(s['text']);
_videoPlayerController?.setSubtitleTrack(SubtitleTrack.data( _videoPlayerController?.setSubtitleTrack(SubtitleTrack.data(
s['text']!, s['text']!,
title: s['title']!, title: s['title']!,
language: s['language']!, language: s['language']!,
)); ));
_vttSubtitlesIndex.value = index;
} }
} }

View File

@@ -1,4 +1,6 @@
import 'package:PiliPalaX/models/danmaku/dm.pb.dart';
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:PiliPalaX/models/bangumi/info.dart'; import 'package:PiliPalaX/models/bangumi/info.dart';
import 'package:PiliPalaX/models/video_detail_res.dart'; import 'package:PiliPalaX/models/video_detail_res.dart';
@@ -26,7 +28,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
static final List<MediaItem> _item = []; static final List<MediaItem> _item = [];
Box setting = GStrorage.setting; Box setting = GStrorage.setting;
bool enableBackgroundPlay = true; bool enableBackgroundPlay = true;
PlPlayerController player = PlPlayerController.getInstance(); // PlPlayerController player = PlPlayerController.getInstance();
VideoPlayerServiceHandler() { VideoPlayerServiceHandler() {
revalidateSetting(); revalidateSetting();
@@ -39,12 +41,14 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
@override @override
Future<void> play() async { Future<void> play() async {
player.play(); await PlPlayerController.playIfExists();
// player.play();
} }
@override @override
Future<void> pause() async { Future<void> pause() async {
player.pause(); await PlPlayerController.pauseIfExists();
// player.pause();
} }
@override @override
@@ -52,12 +56,17 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
playbackState.add(playbackState.value.copyWith( playbackState.add(playbackState.value.copyWith(
updatePosition: position, updatePosition: position,
)); ));
await player.seekTo(position); await PlPlayerController.seekToIfExists(position);
// await player.seekTo(position);
} }
Future<void> setMediaItem(MediaItem newMediaItem) async { Future<void> setMediaItem(MediaItem newMediaItem) async {
if (!enableBackgroundPlay) return; if (!enableBackgroundPlay) return;
mediaItem.add(newMediaItem); // print("此时调用栈为:");
// print(newMediaItem);
// print(newMediaItem.title);
// debugPrint(StackTrace.current.toString());
if(!mediaItem.isClosed) mediaItem.add(newMediaItem);
} }
Future<void> setPlaybackState(PlayerStatus status, bool isBuffering) async { Future<void> setPlaybackState(PlayerStatus status, bool isBuffering) async {
@@ -99,9 +108,11 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
onVideoDetailChange(dynamic data, int cid) { onVideoDetailChange(dynamic data, int cid) {
if (!enableBackgroundPlay) return; if (!enableBackgroundPlay) return;
// print('当前调用栈为:');
// print(StackTrace.current);
if (!PlPlayerController.instanceExists()) return;
if (data == null) return; if (data == null) return;
if (Get.arguments == null) return; if (Get.arguments == null || Get.arguments['heroTag'] == null) return;
final heroTag = Get.arguments['heroTag']; final heroTag = Get.arguments['heroTag'];
late MediaItem? mediaItem; late MediaItem? mediaItem;
@@ -137,6 +148,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
); );
} }
if (mediaItem == null) return; if (mediaItem == null) return;
print("exist: ${PlPlayerController.instanceExists()}");
if (!PlPlayerController.instanceExists()) return;
setMediaItem(mediaItem); setMediaItem(mediaItem);
_item.add(mediaItem); _item.add(mediaItem);
} }
@@ -153,10 +166,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
} }
if (_item.isNotEmpty) { if (_item.isNotEmpty) {
setMediaItem(_item.last); setMediaItem(_item.last);
} } else {
if (_item.isEmpty) { mediaItem?.close();
playbackState
.add(playbackState.value.copyWith(updatePosition: Duration.zero));
} }
stop(); stop();
} }

View File

@@ -18,29 +18,38 @@ class AudioSessionHandler {
session.configure(const AudioSessionConfiguration.music()); session.configure(const AudioSessionConfiguration.music());
session.interruptionEventStream.listen((event) { session.interruptionEventStream.listen((event) {
final player = PlPlayerController.getInstance(); final playerStatus = PlPlayerController.getPlayerStatusIfExists();
// final player = PlPlayerController.getInstance();
if (event.begin) { if (event.begin) {
if (!player.playerStatus.playing) return; if (playerStatus != PlayerStatus.playing) return;
// if (!player.playerStatus.playing) return;
switch (event.type) { switch (event.type) {
case AudioInterruptionType.duck: case AudioInterruptionType.duck:
player.setVolume(player.volume.value * 0.5); PlPlayerController.setVolumeIfExists(
(PlPlayerController.getVolumeIfExists() ?? 0) * 0.5);
// player.setVolume(player.volume.value * 0.5);
break; break;
case AudioInterruptionType.pause: case AudioInterruptionType.pause:
player.pause(isInterrupt: true); PlPlayerController.pauseIfExists(isInterrupt: true);
// player.pause(isInterrupt: true);
_playInterrupted = true; _playInterrupted = true;
break; break;
case AudioInterruptionType.unknown: case AudioInterruptionType.unknown:
player.pause(isInterrupt: true); PlPlayerController.pauseIfExists(isInterrupt: true);
// player.pause(isInterrupt: true);
_playInterrupted = true; _playInterrupted = true;
break; break;
} }
} else { } else {
switch (event.type) { switch (event.type) {
case AudioInterruptionType.duck: case AudioInterruptionType.duck:
player.setVolume(player.volume.value * 2); PlPlayerController.setVolumeIfExists(
(PlPlayerController.getVolumeIfExists() ?? 0) * 2);
// player.setVolume(player.volume.value * 2);
break; break;
case AudioInterruptionType.pause: case AudioInterruptionType.pause:
if (_playInterrupted) player.play(); if (_playInterrupted) PlPlayerController.playIfExists();
//player.play();
break; break;
case AudioInterruptionType.unknown: case AudioInterruptionType.unknown:
break; break;
@@ -51,10 +60,11 @@ class AudioSessionHandler {
// 耳机拔出暂停 // 耳机拔出暂停
session.becomingNoisyEventStream.listen((_) { session.becomingNoisyEventStream.listen((_) {
final player = PlPlayerController.getInstance(); PlPlayerController.pauseIfExists();
if (player.playerStatus.playing) { // final player = PlPlayerController.getInstance();
player.pause(); // if (player.playerStatus.playing) {
} // player.pause();
// }
}); });
} }
} }

View File

@@ -1,6 +1,7 @@
// 定时关闭服务 // 定时关闭服务
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:PiliPalaX/plugin/pl_player/index.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -29,8 +30,8 @@ class ShutdownTimerService {
return; return;
} }
SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭"); SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭");
_shutdownTimer = Timer(Duration(minutes: scheduledExitInMinutes), _shutdownTimer = Timer(
() => _shutdownDecider()); Duration(minutes: scheduledExitInMinutes), () => _shutdownDecider());
} }
void _showTimeUpButPauseDialog() { void _showTimeUpButPauseDialog() {
@@ -88,9 +89,12 @@ class ShutdownTimerService {
_showShutdownDialog(); _showShutdownDialog();
return; return;
} }
PlPlayerController plPlayerController = PlPlayerController.getInstance(); // PlPlayerController plPlayerController = PlPlayerController.getInstance();
PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists();
if (!exitApp && !waitForPlayingCompleted) { if (!exitApp && !waitForPlayingCompleted) {
if (!plPlayerController.playerStatus.playing) { // if (!plPlayerController.playerStatus.playing) {
if (playerStatus == PlayerStatus.paused ||
playerStatus == PlayerStatus.completed) {
//仅提示用户 //仅提示用户
_showTimeUpButPauseDialog(); _showTimeUpButPauseDialog();
} else { } else {
@@ -99,7 +103,9 @@ class ShutdownTimerService {
return; return;
} }
//waitForPlayingCompleted //waitForPlayingCompleted
if (!plPlayerController.playerStatus.playing) { if (playerStatus == PlayerStatus.paused ||
playerStatus == PlayerStatus.completed) {
// if (!plPlayerController.playerStatus.playing) {
_showShutdownDialog(); _showShutdownDialog();
return; return;
} }
@@ -108,26 +114,36 @@ class ShutdownTimerService {
//该方法依赖耦合实现,不够优雅 //该方法依赖耦合实现,不够优雅
isWaiting = true; isWaiting = true;
} }
void handleWaitingFinished() { void handleWaitingFinished() {
if (isWaiting) { if (isWaiting) {
_showShutdownDialog(); _showShutdownDialog();
isWaiting = false; isWaiting = false;
} }
} }
void _executeShutdown() { void _executeShutdown() {
if (exitApp) { if (exitApp) {
//退出app //退出app
exit(0); exit(0);
} else { } else {
//暂停播放 //暂停播放
PlPlayerController plPlayerController = PlPlayerController.getInstance(); PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists();
if (plPlayerController.playerStatus.playing) { if (playerStatus == PlayerStatus.playing) {
plPlayerController.pause(); PlPlayerController.pauseIfExists();
waitForPlayingCompleted = true; waitForPlayingCompleted = true;
SmartDialog.showToast("已暂停播放"); SmartDialog.showToast("已暂停播放");
} else { } else {
SmartDialog.showToast("当前未播放"); SmartDialog.showToast("当前未播放");
} }
// PlPlayerController plPlayerController = PlPlayerController.getInstance();
// if (plPlayerController.playerStatus.playing) {
// plPlayerController.pause();
// waitForPlayingCompleted = true;
// SmartDialog.showToast("已暂停播放");
// } else {
// SmartDialog.showToast("当前未播放");
// }
} }
} }