mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
fix: 多层播放页快速返回首页致后台播放、通知未消失
This commit is contained in:
@@ -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._() {
|
||||
_videoType = videoType;
|
||||
@@ -439,8 +474,9 @@ class PlPlayerController {
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err, stackTrace) {
|
||||
dataStatus.status.value = DataStatus.error;
|
||||
debugPrint(stackTrace.toString());
|
||||
print('plPlayer err: $err');
|
||||
}
|
||||
}
|
||||
@@ -564,6 +600,7 @@ class PlPlayerController {
|
||||
Duration seekTo = Duration.zero,
|
||||
Duration? duration,
|
||||
}) async {
|
||||
if (_instance == null) return;
|
||||
// 设置倍速
|
||||
if (videoType.value == 'live') {
|
||||
await setPlaybackSpeed(1.0);
|
||||
@@ -586,7 +623,8 @@ class PlPlayerController {
|
||||
|
||||
// 自动播放
|
||||
if (_autoPlay) {
|
||||
await play(duration: duration);
|
||||
await playIfExists(duration: duration);
|
||||
// await play(duration: duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,6 +819,7 @@ class PlPlayerController {
|
||||
/// TODO _duration.value丢失
|
||||
Future<void> play(
|
||||
{bool repeat = false, bool hideControls = true, dynamic duration}) async {
|
||||
if (_playerCount.value == 0) return;
|
||||
// 播放时自动隐藏控制条
|
||||
controls = !hideControls;
|
||||
// repeat为true,将从头播放
|
||||
@@ -1237,10 +1276,12 @@ class PlPlayerController {
|
||||
return;
|
||||
}
|
||||
Map<String, String> s = _vttSubtitles[index];
|
||||
debugPrint(s['text']);
|
||||
_videoPlayerController?.setSubtitleTrack(SubtitleTrack.data(
|
||||
s['text']!,
|
||||
title: s['title']!,
|
||||
language: s['language']!,
|
||||
));
|
||||
_vttSubtitlesIndex.value = index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import 'package:PiliPalaX/models/danmaku/dm.pb.dart';
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:PiliPalaX/models/bangumi/info.dart';
|
||||
import 'package:PiliPalaX/models/video_detail_res.dart';
|
||||
@@ -26,7 +28,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
static final List<MediaItem> _item = [];
|
||||
Box setting = GStrorage.setting;
|
||||
bool enableBackgroundPlay = true;
|
||||
PlPlayerController player = PlPlayerController.getInstance();
|
||||
// PlPlayerController player = PlPlayerController.getInstance();
|
||||
|
||||
VideoPlayerServiceHandler() {
|
||||
revalidateSetting();
|
||||
@@ -39,12 +41,14 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
|
||||
@override
|
||||
Future<void> play() async {
|
||||
player.play();
|
||||
await PlPlayerController.playIfExists();
|
||||
// player.play();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> pause() async {
|
||||
player.pause();
|
||||
await PlPlayerController.pauseIfExists();
|
||||
// player.pause();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -52,12 +56,17 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
playbackState.add(playbackState.value.copyWith(
|
||||
updatePosition: position,
|
||||
));
|
||||
await player.seekTo(position);
|
||||
await PlPlayerController.seekToIfExists(position);
|
||||
// await player.seekTo(position);
|
||||
}
|
||||
|
||||
Future<void> setMediaItem(MediaItem newMediaItem) async {
|
||||
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 {
|
||||
@@ -99,9 +108,11 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
|
||||
onVideoDetailChange(dynamic data, int cid) {
|
||||
if (!enableBackgroundPlay) return;
|
||||
|
||||
// print('当前调用栈为:');
|
||||
// print(StackTrace.current);
|
||||
if (!PlPlayerController.instanceExists()) return;
|
||||
if (data == null) return;
|
||||
if (Get.arguments == null) return;
|
||||
if (Get.arguments == null || Get.arguments['heroTag'] == null) return;
|
||||
final heroTag = Get.arguments['heroTag'];
|
||||
|
||||
late MediaItem? mediaItem;
|
||||
@@ -137,6 +148,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
);
|
||||
}
|
||||
if (mediaItem == null) return;
|
||||
print("exist: ${PlPlayerController.instanceExists()}");
|
||||
if (!PlPlayerController.instanceExists()) return;
|
||||
setMediaItem(mediaItem);
|
||||
_item.add(mediaItem);
|
||||
}
|
||||
@@ -153,10 +166,8 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler {
|
||||
}
|
||||
if (_item.isNotEmpty) {
|
||||
setMediaItem(_item.last);
|
||||
}
|
||||
if (_item.isEmpty) {
|
||||
playbackState
|
||||
.add(playbackState.value.copyWith(updatePosition: Duration.zero));
|
||||
} else {
|
||||
mediaItem?.close();
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -18,29 +18,38 @@ class AudioSessionHandler {
|
||||
session.configure(const AudioSessionConfiguration.music());
|
||||
|
||||
session.interruptionEventStream.listen((event) {
|
||||
final player = PlPlayerController.getInstance();
|
||||
final playerStatus = PlPlayerController.getPlayerStatusIfExists();
|
||||
// final player = PlPlayerController.getInstance();
|
||||
if (event.begin) {
|
||||
if (!player.playerStatus.playing) return;
|
||||
if (playerStatus != PlayerStatus.playing) return;
|
||||
// if (!player.playerStatus.playing) return;
|
||||
switch (event.type) {
|
||||
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;
|
||||
case AudioInterruptionType.pause:
|
||||
player.pause(isInterrupt: true);
|
||||
PlPlayerController.pauseIfExists(isInterrupt: true);
|
||||
// player.pause(isInterrupt: true);
|
||||
_playInterrupted = true;
|
||||
break;
|
||||
case AudioInterruptionType.unknown:
|
||||
player.pause(isInterrupt: true);
|
||||
PlPlayerController.pauseIfExists(isInterrupt: true);
|
||||
// player.pause(isInterrupt: true);
|
||||
_playInterrupted = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (event.type) {
|
||||
case AudioInterruptionType.duck:
|
||||
player.setVolume(player.volume.value * 2);
|
||||
PlPlayerController.setVolumeIfExists(
|
||||
(PlPlayerController.getVolumeIfExists() ?? 0) * 2);
|
||||
// player.setVolume(player.volume.value * 2);
|
||||
break;
|
||||
case AudioInterruptionType.pause:
|
||||
if (_playInterrupted) player.play();
|
||||
if (_playInterrupted) PlPlayerController.playIfExists();
|
||||
//player.play();
|
||||
break;
|
||||
case AudioInterruptionType.unknown:
|
||||
break;
|
||||
@@ -51,10 +60,11 @@ class AudioSessionHandler {
|
||||
|
||||
// 耳机拔出暂停
|
||||
session.becomingNoisyEventStream.listen((_) {
|
||||
final player = PlPlayerController.getInstance();
|
||||
if (player.playerStatus.playing) {
|
||||
player.pause();
|
||||
}
|
||||
PlPlayerController.pauseIfExists();
|
||||
// final player = PlPlayerController.getInstance();
|
||||
// if (player.playerStatus.playing) {
|
||||
// player.pause();
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 定时关闭服务
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:PiliPalaX/plugin/pl_player/index.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
|
||||
@@ -29,8 +30,8 @@ class ShutdownTimerService {
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭");
|
||||
_shutdownTimer = Timer(Duration(minutes: scheduledExitInMinutes),
|
||||
() => _shutdownDecider());
|
||||
_shutdownTimer = Timer(
|
||||
Duration(minutes: scheduledExitInMinutes), () => _shutdownDecider());
|
||||
}
|
||||
|
||||
void _showTimeUpButPauseDialog() {
|
||||
@@ -59,7 +60,7 @@ class ShutdownTimerService {
|
||||
// Start the 10-second timer to auto close the dialog
|
||||
_autoCloseDialogTimer?.cancel();
|
||||
_autoCloseDialogTimer = Timer(const Duration(seconds: 10), () {
|
||||
SmartDialog.dismiss();// Close the dialog
|
||||
SmartDialog.dismiss(); // Close the dialog
|
||||
_executeShutdown();
|
||||
});
|
||||
return AlertDialog(
|
||||
@@ -88,9 +89,12 @@ class ShutdownTimerService {
|
||||
_showShutdownDialog();
|
||||
return;
|
||||
}
|
||||
PlPlayerController plPlayerController = PlPlayerController.getInstance();
|
||||
// PlPlayerController plPlayerController = PlPlayerController.getInstance();
|
||||
PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists();
|
||||
if (!exitApp && !waitForPlayingCompleted) {
|
||||
if (!plPlayerController.playerStatus.playing) {
|
||||
// if (!plPlayerController.playerStatus.playing) {
|
||||
if (playerStatus == PlayerStatus.paused ||
|
||||
playerStatus == PlayerStatus.completed) {
|
||||
//仅提示用户
|
||||
_showTimeUpButPauseDialog();
|
||||
} else {
|
||||
@@ -99,7 +103,9 @@ class ShutdownTimerService {
|
||||
return;
|
||||
}
|
||||
//waitForPlayingCompleted
|
||||
if (!plPlayerController.playerStatus.playing) {
|
||||
if (playerStatus == PlayerStatus.paused ||
|
||||
playerStatus == PlayerStatus.completed) {
|
||||
// if (!plPlayerController.playerStatus.playing) {
|
||||
_showShutdownDialog();
|
||||
return;
|
||||
}
|
||||
@@ -108,26 +114,36 @@ class ShutdownTimerService {
|
||||
//该方法依赖耦合实现,不够优雅
|
||||
isWaiting = true;
|
||||
}
|
||||
void handleWaitingFinished(){
|
||||
if(isWaiting){
|
||||
|
||||
void handleWaitingFinished() {
|
||||
if (isWaiting) {
|
||||
_showShutdownDialog();
|
||||
isWaiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
void _executeShutdown() {
|
||||
if (exitApp) {
|
||||
//退出app
|
||||
exit(0);
|
||||
} else {
|
||||
//暂停播放
|
||||
PlPlayerController plPlayerController = PlPlayerController.getInstance();
|
||||
if (plPlayerController.playerStatus.playing) {
|
||||
plPlayerController.pause();
|
||||
PlayerStatus? playerStatus = PlPlayerController.getPlayerStatusIfExists();
|
||||
if (playerStatus == PlayerStatus.playing) {
|
||||
PlPlayerController.pauseIfExists();
|
||||
waitForPlayingCompleted = true;
|
||||
SmartDialog.showToast("已暂停播放");
|
||||
} else {
|
||||
SmartDialog.showToast("当前未播放");
|
||||
}
|
||||
// PlPlayerController plPlayerController = PlPlayerController.getInstance();
|
||||
// if (plPlayerController.playerStatus.playing) {
|
||||
// plPlayerController.pause();
|
||||
// waitForPlayingCompleted = true;
|
||||
// SmartDialog.showToast("已暂停播放");
|
||||
// } else {
|
||||
// SmartDialog.showToast("当前未播放");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user