后台播放能力已调通,介入部分细节优化
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
// lib/services/app_lifecycle_manager.dart
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
|
||||
/// App 生命周期状态(扩展了 Flutter 原生状态)
|
||||
enum AppLifecycleStatus {
|
||||
/// 应用正在启动(初始化阶段)
|
||||
launching,
|
||||
|
||||
/// 应用在前台,用户可交互
|
||||
resumed,
|
||||
|
||||
/// 应用在前台但不可交互(如:来电、系统弹窗)
|
||||
inactive,
|
||||
|
||||
/// 应用在后台
|
||||
paused,
|
||||
|
||||
/// 应用即将被销毁
|
||||
detached,
|
||||
|
||||
/// 应用已进入后台且播放停止(自定义,用于播放策略)
|
||||
backgroundIdle,
|
||||
}
|
||||
|
||||
/// App 生命周期管理器
|
||||
///
|
||||
/// 职责:
|
||||
/// 1. 统一监听 Flutter 的 AppLifecycleState
|
||||
/// 2. 管理播放器在前后台的行为
|
||||
/// 3. 管理渲染调度器的运行状态
|
||||
/// 4. 管理 WebDAV 的缓存策略
|
||||
class AppLifecycleManager extends ChangeNotifier {
|
||||
static final AppLifecycleManager _instance = AppLifecycleManager._internal();
|
||||
factory AppLifecycleManager() => _instance;
|
||||
AppLifecycleManager._internal();
|
||||
|
||||
// ---- 当前状态 ----
|
||||
AppLifecycleStatus _status = AppLifecycleStatus.launching;
|
||||
AppLifecycleStatus get status => _status;
|
||||
|
||||
// ---- 上次进入后台的时间 ----
|
||||
DateTime? _backgroundedAt;
|
||||
DateTime? get backgroundedAt => _backgroundedAt;
|
||||
|
||||
// ---- 是否在后台 ----
|
||||
bool get isInBackground =>
|
||||
_status == AppLifecycleStatus.paused ||
|
||||
_status == AppLifecycleStatus.inactive ||
|
||||
_status == AppLifecycleStatus.detached;
|
||||
|
||||
bool get isInForeground => _status == AppLifecycleStatus.resumed;
|
||||
|
||||
// ---- 后台时长 ----
|
||||
Duration get backgroundDuration {
|
||||
if (_backgroundedAt == null) return Duration.zero;
|
||||
return DateTime.now().difference(_backgroundedAt!);
|
||||
}
|
||||
|
||||
// ---- 是否处于"长后台"(超过 5 分钟) ----
|
||||
bool get isLongBackground => backgroundDuration > const Duration(minutes: 5);
|
||||
|
||||
// ---- 监听器 ----
|
||||
final List<void Function(AppLifecycleStatus)> _listeners = [];
|
||||
|
||||
// ---- Flutter 原生生命周期订阅 ----
|
||||
late final WidgetsBindingObserver _observer;
|
||||
bool _isObserving = false;
|
||||
|
||||
// ---- 初始化 ----
|
||||
void init() {
|
||||
if (_isObserving) return;
|
||||
_isObserving = true;
|
||||
|
||||
_observer = _AppLifecycleObserver(this);
|
||||
WidgetsBinding.instance.addObserver(_observer);
|
||||
|
||||
// 获取初始状态
|
||||
_updateStatus(AppLifecycleStatus.resumed);
|
||||
|
||||
debugPrint('📱 AppLifecycleManager 已初始化');
|
||||
}
|
||||
|
||||
// ---- 状态更新 ----
|
||||
void _handleNativeState(AppLifecycleState state) {
|
||||
final newStatus = _convertNativeState(state);
|
||||
|
||||
// 状态变化时更新
|
||||
if (newStatus != _status) {
|
||||
_updateStatus(newStatus);
|
||||
}
|
||||
|
||||
// 记录进入后台的时间
|
||||
if (newStatus == AppLifecycleStatus.paused ||
|
||||
newStatus == AppLifecycleStatus.inactive) {
|
||||
if (_backgroundedAt == null) {
|
||||
_backgroundedAt = DateTime.now();
|
||||
debugPrint('📱 App 进入后台: ${_backgroundedAt}');
|
||||
}
|
||||
}
|
||||
|
||||
// 回到前台时,如果是长后台,触发通知
|
||||
if (newStatus == AppLifecycleStatus.resumed) {
|
||||
if (_backgroundedAt != null) {
|
||||
final duration = backgroundDuration;
|
||||
debugPrint('📱 App 回到前台,后台时长: ${duration.inMinutes}分钟');
|
||||
_backgroundedAt = null;
|
||||
|
||||
// 如果是长后台,通知监听器做重连等操作
|
||||
if (duration > const Duration(minutes: 5)) {
|
||||
_notifyListeners(AppLifecycleStatus.backgroundIdle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _updateStatus(AppLifecycleStatus newStatus) {
|
||||
final oldStatus = _status;
|
||||
_status = newStatus;
|
||||
debugPrint('📱 生命周期状态变化: $oldStatus → $newStatus');
|
||||
notifyListeners();
|
||||
_notifyListeners(newStatus);
|
||||
}
|
||||
|
||||
AppLifecycleStatus _convertNativeState(AppLifecycleState state) {
|
||||
switch (state) {
|
||||
case AppLifecycleState.resumed:
|
||||
return AppLifecycleStatus.resumed;
|
||||
case AppLifecycleState.inactive:
|
||||
return AppLifecycleStatus.inactive;
|
||||
case AppLifecycleState.paused:
|
||||
return AppLifecycleStatus.paused;
|
||||
case AppLifecycleState.detached:
|
||||
return AppLifecycleStatus.detached;
|
||||
default:
|
||||
return AppLifecycleStatus.paused;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 自定义监听器管理 ----
|
||||
void addListenerToManager(void Function(AppLifecycleStatus) listener) {
|
||||
_listeners.add(listener);
|
||||
}
|
||||
|
||||
void removeListenerFromManager(void Function(AppLifecycleStatus) listener) {
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
void _notifyListeners(AppLifecycleStatus status) {
|
||||
for (final listener in _listeners) {
|
||||
try {
|
||||
listener(status);
|
||||
} catch (e) {
|
||||
debugPrint('❌ 生命周期监听器执行失败: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 检查是否需要重新连接 WebDAV ----
|
||||
bool get shouldRecheckWebDAV {
|
||||
if (!isInForeground) return false;
|
||||
if (_backgroundedAt == null) return false;
|
||||
return isLongBackground;
|
||||
}
|
||||
|
||||
// ---- 释放 ----
|
||||
void dispose() {
|
||||
if (_isObserving) {
|
||||
WidgetsBinding.instance.removeObserver(_observer);
|
||||
_isObserving = false;
|
||||
}
|
||||
_listeners.clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// 内部观察者(绑定 WidgetsBinding)
|
||||
class _AppLifecycleObserver extends WidgetsBindingObserver {
|
||||
final AppLifecycleManager _manager;
|
||||
|
||||
_AppLifecycleObserver(this._manager);
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
_manager._handleNativeState(state);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user