snapshot: 存档 flutter create 模板覆盖后的现场,作为多实例修复前的基线
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: "ad70ec4617166f1c38e5d2bfd388af71fda14f06"
|
revision: "d3b14c876900e553bc736ca19295fc09e3853e8e"
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@@ -13,26 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
create_revision: d3b14c876900e553bc736ca19295fc09e3853e8e
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
base_revision: d3b14c876900e553bc736ca19295fc09e3853e8e
|
||||||
- platform: android
|
- platform: android
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
create_revision: d3b14c876900e553bc736ca19295fc09e3853e8e
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
base_revision: d3b14c876900e553bc736ca19295fc09e3853e8e
|
||||||
- platform: ios
|
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
- platform: linux
|
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
- platform: macos
|
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
- platform: web
|
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
- platform: windows
|
|
||||||
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
|
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -8,11 +8,10 @@ GeneratedPluginRegistrant.java
|
|||||||
.cxx/
|
.cxx/
|
||||||
.kotlin
|
.kotlin
|
||||||
/build
|
/build
|
||||||
|
.settings
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/to/reference-keystore
|
# See https://flutter.dev/to/reference-keystore
|
||||||
key.properties
|
key.properties
|
||||||
**/*.keystore
|
**/*.keystore
|
||||||
**/*.jks
|
**/*.jks
|
||||||
.settings
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.lxh.qingting_player"
|
namespace = "com.lxh.qingting_player"
|
||||||
compileSdk = 36
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -14,49 +15,25 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId = "com.lxh.qingting_player"
|
applicationId = "com.lxh.qingting_player"
|
||||||
|
// You can update the following values to match your application needs.
|
||||||
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdk = 34
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = flutter.versionCode
|
// Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
|
||||||
versionName = flutter.versionName
|
// is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
|
||||||
|
// You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
|
||||||
// 仅打包 arm64-v8a
|
// flag during build.
|
||||||
ndk {
|
versionCode = 1
|
||||||
abiFilters.addAll(listOf("arm64-v8a"))
|
versionName = "1.0.0"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显式指定 jniLibs 源目录
|
|
||||||
sourceSets {
|
|
||||||
getByName("main") {
|
|
||||||
jniLibs.srcDirs("src/main/jniLibs")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<Copy> {
|
|
||||||
if (name.startsWith("merge") && name.endsWith("JniLibFolders")) {
|
|
||||||
from("src/main/jniLibs")
|
|
||||||
into("$buildDir/intermediates/merged_jni_libs/debug/out")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 打包配置
|
|
||||||
packagingOptions {
|
|
||||||
jniLibs {
|
|
||||||
useLegacyPackaging = true
|
|
||||||
}
|
|
||||||
pickFirsts += "**/*.so"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
|
||||||
}
|
|
||||||
|
|
||||||
release {
|
release {
|
||||||
|
// TODO: Add your own signing config for the release build.
|
||||||
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
proguardFiles(
|
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
||||||
"proguard-rules.pro"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-45
@@ -1,45 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# media_kit 核心
|
|
||||||
# ============================================================
|
|
||||||
-keep class com.media_kit.** { *; }
|
|
||||||
-keep class com.alexmercerind.** { *; }
|
|
||||||
-keep class org.mozilla.** { *; }
|
|
||||||
|
|
||||||
# 保留所有 native 方法
|
|
||||||
-keepclasseswithmembernames class * {
|
|
||||||
native <methods>;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 保留所有 JNI 相关
|
|
||||||
-keep class * implements java.lang.reflect.Method { *; }
|
|
||||||
-keep class * extends java.lang.reflect.Method { *; }
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# audio_service 插件
|
|
||||||
# ============================================================
|
|
||||||
-keep class com.ryanheise.audioservice.** { *; }
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# Flutter 核心
|
|
||||||
# ============================================================
|
|
||||||
-keep class io.flutter.** { *; }
|
|
||||||
-keep class io.flutter.plugin.** { *; }
|
|
||||||
-keep class io.flutter.embedding.** { *; }
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# 忽略 Google Play Core 缺失类(如果不想添加依赖)
|
|
||||||
# ============================================================
|
|
||||||
-dontwarn com.google.android.play.core.**
|
|
||||||
-keep class com.google.android.play.core.** { *; }
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# 保留 Serializable 支持
|
|
||||||
# ============================================================
|
|
||||||
-keepclassmembers class * implements java.io.Serializable {
|
|
||||||
static final long serialVersionUID;
|
|
||||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
|
||||||
private void writeObject(java.io.ObjectOutputStream);
|
|
||||||
private void readObject(java.io.ObjectInputStream);
|
|
||||||
java.lang.Object writeReplace();
|
|
||||||
java.lang.Object readResolve();
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.lxh.qingting_player">
|
package="com.lxh.qingting_player"> <!-- ⭐ 改这里 -->
|
||||||
|
<!-- 权限 -->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
@@ -15,8 +15,7 @@
|
|||||||
android:label="清听"
|
android:label="清听"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:foregroundServiceType="mediaPlayback"
|
android:foregroundServiceType="mediaPlayback"
|
||||||
android:extractNativeLibs="true"> <!-- ⭐ 强制提取 .so,避免压缩后加载失败 -->
|
android:extractNativeLibs="true">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
@@ -34,8 +33,7 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<!-- ⭐ AudioService(不加 meta-data) -->
|
||||||
<!-- AudioService -->
|
|
||||||
<service
|
<service
|
||||||
android:name="com.ryanheise.audioservice.AudioService"
|
android:name="com.ryanheise.audioservice.AudioService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
@@ -45,8 +43,9 @@
|
|||||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
<!-- Don't delete the meta-data below.
|
||||||
<!-- MediaButtonReceiver -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
<!-- ⭐ MediaButtonReceiver -->
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
@@ -55,7 +54,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<!-- FileProvider for artwork(已配置,保持不变) -->
|
<!-- ⭐ FileProvider -->
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.fileprovider"
|
android:authorities="${applicationId}.fileprovider"
|
||||||
@@ -70,12 +69,15 @@
|
|||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
|
<!-- Required to query activities that can process text, see:
|
||||||
|
https://developer.android.com/training/package-visibility and
|
||||||
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
|
|
||||||
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -16,26 +16,8 @@ class MainActivity : FlutterActivity() {
|
|||||||
private val CHANNEL = "com.lxh.qingting_player/file_provider"
|
private val CHANNEL = "com.lxh.qingting_player/file_provider"
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
// ⭐ 强制加载 libmediakitandroidhelper.so,触发 JNI_OnLoad,缓存 JavaVM
|
|
||||||
try {
|
|
||||||
System.loadLibrary("mediakitandroidhelper")
|
|
||||||
Log.d("MainActivity", "✅ libmediakitandroidhelper loaded")
|
|
||||||
} catch (e: UnsatisfiedLinkError) {
|
|
||||||
Log.e("MainActivity", "❌ libmediakitandroidhelper load failed", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ⭐ 可选:预加载 libmpv.so(让系统 linker 也可见,增强兼容性)
|
|
||||||
try {
|
|
||||||
System.loadLibrary("mpv")
|
|
||||||
Log.d("MainActivity", "✅ libmpv loaded")
|
|
||||||
} catch (e: UnsatisfiedLinkError) {
|
|
||||||
Log.e("MainActivity", "❌ libmpv load failed", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
requestAudioFocus()
|
requestAudioFocus()
|
||||||
|
|
||||||
setHighRefreshRate()
|
setHighRefreshRate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +45,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
super.configureFlutterEngine(flutterEngine)
|
super.configureFlutterEngine(flutterEngine)
|
||||||
|
|
||||||
// FileProvider MethodChannel for sharing artwork via content:// URI
|
// FileProvider MethodChannel
|
||||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
|
||||||
.setMethodCallHandler { call, result ->
|
.setMethodCallHandler { call, result ->
|
||||||
if (call.method == "getContentUri") {
|
if (call.method == "getContentUri") {
|
||||||
|
|||||||
@@ -3,6 +3,4 @@ android.useAndroidX=true
|
|||||||
# This newDsl flag was added by the Flutter template
|
# This newDsl flag was added by the Flutter template
|
||||||
android.newDsl=false
|
android.newDsl=false
|
||||||
# This builtInKotlin flag was added by the Flutter template
|
# This builtInKotlin flag was added by the Flutter template
|
||||||
kotlin.incremental=false
|
|
||||||
kotlin.parallel.tasks.in.project=false
|
|
||||||
android.builtInKotlin=false
|
android.builtInKotlin=false
|
||||||
|
|||||||
+1
-1
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.1.0-all.zip
|
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.3.1-all.zip
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="android" name="Android">
|
|
||||||
<configuration>
|
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
|
||||||
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
|
|
||||||
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
|
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" />
|
|
||||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" />
|
|
||||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" />
|
|
||||||
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" />
|
|
||||||
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/kotlin" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
|
||||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
@@ -19,8 +19,8 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "9.0.1" apply false
|
id("com.android.application") version "9.1.0" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "2.3.20" apply false
|
id("org.jetbrains.kotlin.android") version "2.4.0" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
// lib/services/playback_service.dart
|
// lib/services/playback_service.dart
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// PlaybackService - 播放引擎封装
|
|
||||||
// 职责:管理 Player 生命周期,不涉及业务逻辑
|
|
||||||
// ============================================================
|
|
||||||
class PlaybackService {
|
class PlaybackService {
|
||||||
static final PlaybackService _instance = PlaybackService._internal();
|
static final PlaybackService _instance = PlaybackService._internal();
|
||||||
factory PlaybackService() => _instance;
|
factory PlaybackService() => _instance;
|
||||||
PlaybackService._internal();
|
PlaybackService._internal() {
|
||||||
|
// ⭐ 给单例本身打上 ID
|
||||||
|
_serviceId = DateTime.now().microsecondsSinceEpoch.toString();
|
||||||
|
debugPrint('🎯 [PlaybackService] 单例创建, serviceId=$_serviceId');
|
||||||
|
}
|
||||||
|
|
||||||
Player? _player;
|
Player? _player;
|
||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
|
late final String _serviceId; // ⭐ 服务实例 ID
|
||||||
|
|
||||||
// ---------- Getter ----------
|
// ---------- Getter ----------
|
||||||
Player get player {
|
Player get player {
|
||||||
|
debugPrint(
|
||||||
|
'🎯 [PlaybackService] get player called, serviceId=$_serviceId, initialized=$_initialized, player=${_player?.hashCode}');
|
||||||
if (!_initialized) init();
|
if (!_initialized) init();
|
||||||
return _player!;
|
return _player!;
|
||||||
}
|
}
|
||||||
@@ -23,16 +27,21 @@ class PlaybackService {
|
|||||||
|
|
||||||
// ---------- 初始化 ----------
|
// ---------- 初始化 ----------
|
||||||
void init() {
|
void init() {
|
||||||
if (_initialized) return;
|
if (_initialized) {
|
||||||
|
debugPrint(
|
||||||
|
'⚠️ [PlaybackService] init() 被重复调用, 跳过, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
_player = Player();
|
_player = Player();
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
debugPrint(
|
||||||
// 可以在这里配置初始参数
|
'✅ [PlaybackService] Player 已创建, serviceId=$_serviceId, player=${_player.hashCode}');
|
||||||
// _player.setVolume(1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- 播放 ----------
|
// ---------- 播放 ----------
|
||||||
Future<void> play(String url, {Map<String, String>? headers}) async {
|
Future<void> play(String url, {Map<String, String>? headers}) async {
|
||||||
|
debugPrint(
|
||||||
|
'▶️ [PlaybackService] play() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (!_initialized) init();
|
if (!_initialized) init();
|
||||||
|
|
||||||
final media = (headers != null && headers.isNotEmpty)
|
final media = (headers != null && headers.isNotEmpty)
|
||||||
@@ -45,24 +54,32 @@ class PlaybackService {
|
|||||||
|
|
||||||
// ---------- 控制 ----------
|
// ---------- 控制 ----------
|
||||||
Future<void> pause() async {
|
Future<void> pause() async {
|
||||||
|
debugPrint(
|
||||||
|
'⏸️ [PlaybackService] pause() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (_initialized && _player != null) {
|
if (_initialized && _player != null) {
|
||||||
await _player!.pause();
|
await _player!.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> resume() async {
|
Future<void> resume() async {
|
||||||
|
debugPrint(
|
||||||
|
'▶️ [PlaybackService] resume() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (_initialized && _player != null) {
|
if (_initialized && _player != null) {
|
||||||
await _player!.play();
|
await _player!.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> stop() async {
|
Future<void> stop() async {
|
||||||
|
debugPrint(
|
||||||
|
'⏹️ [PlaybackService] stop() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (_initialized && _player != null) {
|
if (_initialized && _player != null) {
|
||||||
await _player!.stop();
|
await _player!.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> seek(Duration position) async {
|
Future<void> seek(Duration position) async {
|
||||||
|
debugPrint(
|
||||||
|
'⏩ [PlaybackService] seek() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (_initialized && _player != null) {
|
if (_initialized && _player != null) {
|
||||||
await _player!.seek(position);
|
await _player!.seek(position);
|
||||||
}
|
}
|
||||||
@@ -76,6 +93,8 @@ class PlaybackService {
|
|||||||
|
|
||||||
// ---------- 释放 ----------
|
// ---------- 释放 ----------
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
debugPrint(
|
||||||
|
'🗑️ [PlaybackService] dispose() called, serviceId=$_serviceId, player=${_player?.hashCode}');
|
||||||
if (_initialized && _player != null) {
|
if (_initialized && _player != null) {
|
||||||
_player!.dispose();
|
_player!.dispose();
|
||||||
_player = null;
|
_player = null;
|
||||||
@@ -83,8 +102,10 @@ class PlaybackService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- 重新初始化(用于 Hot Restart 场景) ----------
|
// ---------- 重新初始化 ----------
|
||||||
void reinitialize() {
|
void reinitialize() {
|
||||||
|
debugPrint(
|
||||||
|
'🔄 [PlaybackService] reinitialize() called, serviceId=$_serviceId');
|
||||||
dispose();
|
dispose();
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import 'package:media_kit/media_kit.dart';
|
|
||||||
|
|
||||||
class PlayerService {
|
|
||||||
static final PlayerService _instance = PlayerService._internal();
|
|
||||||
|
|
||||||
factory PlayerService() => _instance;
|
|
||||||
|
|
||||||
PlayerService._internal();
|
|
||||||
|
|
||||||
Player? _player;
|
|
||||||
|
|
||||||
Player get player {
|
|
||||||
return _player ??= Player();
|
|
||||||
}
|
|
||||||
|
|
||||||
void play(String url) {
|
|
||||||
player.open(Media(url));
|
|
||||||
}
|
|
||||||
|
|
||||||
void pause() => player.pause();
|
|
||||||
|
|
||||||
void resume() => player.play();
|
|
||||||
|
|
||||||
void stop() => player.stop();
|
|
||||||
|
|
||||||
void dispose() {
|
|
||||||
_player?.dispose();
|
|
||||||
_player = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 状态监听...
|
|
||||||
}
|
|
||||||
+32
-32
@@ -13,10 +13,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff
|
sha256: ace891da0862b0e4cabbb064ee3fd87b2728b898949fdb366d83fe98342c9f19
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.9"
|
version: "4.2.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -101,18 +101,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.3"
|
||||||
code_assets:
|
code_assets:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: code_assets
|
name: code_assets
|
||||||
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
|
sha256: cfd4f5f575a49c5f10ca856e9846073f1e6c3ee94912377eea5f6cefc5272941
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "2.0.0"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -220,10 +220,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: hooks
|
name: hooks
|
||||||
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
|
sha256: eaac480a35ec0814146c2c48d96aaa829e0e44a7662c88ae84c9edf4bc35651f
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.2.0"
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -244,10 +244,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce
|
sha256: "1976370a4df3091bb0f72409c187ad1f9132a818bc6b95ca59c0bae1c75c688e"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.0"
|
version: "4.9.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -268,10 +268,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: jni_flutter
|
name: jni_flutter
|
||||||
sha256: "7b717011ea40d04fd47c2731d3d1d36eb99eba3435c2753d62489e8c3c9991d5"
|
sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.3"
|
||||||
jni_util:
|
jni_util:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -284,10 +284,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.7"
|
version: "0.7.2"
|
||||||
leak_tracker:
|
leak_tracker:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -412,10 +412,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
sha256: bd47de35f07e27267e69c8c8b22edf9473bfee170a60d60fcc93730c5144b7f6
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.1.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -428,10 +428,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: objective_c
|
name: objective_c
|
||||||
sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e
|
sha256: ad56fd53a78ff6b1472fa59ff2a4e8b8ccabafc586fc263a1dfad0b99b5553e3
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.5.0"
|
version: "9.6.0"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -588,18 +588,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pub_semver
|
name: pub_semver
|
||||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.1"
|
||||||
record_use:
|
record_use:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_use
|
name: record_use
|
||||||
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
|
sha256: "1cb8564af8d43b464294411db9217f5ec04891c6f22ee2c32d73ae05e88a6bd2"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "1.1.1"
|
||||||
rxdart:
|
rxdart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -628,18 +628,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "0634e64bd719f89c012f392938e173521f535d3ecaf66558fa94a056d22b5cc7"
|
sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.27"
|
version: "2.4.28"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_foundation
|
||||||
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.6"
|
version: "2.5.7"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -729,10 +729,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.1"
|
version: "1.12.2"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -817,10 +817,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.2.0"
|
version: "15.3.0"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -849,10 +849,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.4"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.12.0 <4.0.0"
|
dart: ">=3.12.0 <4.0.0"
|
||||||
flutter: ">=3.44.0"
|
flutter: ">=3.44.0"
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ dependencies:
|
|||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
dio: ^5.4.0 # HTTP 客户端
|
dio: ^5.4.0 # HTTP 客户端
|
||||||
xml: ^6.5.0
|
xml: ^6.5.0
|
||||||
audio_service: ^0.18.19
|
audio_service: 0.18.19
|
||||||
audio_session: ^0.1.21
|
audio_session: ^0.1.21
|
||||||
permission_handler: ^11.3.1
|
permission_handler: ^11.3.1
|
||||||
flutter_cache_manager: ^3.3.1
|
flutter_cache_manager: ^3.3.1
|
||||||
|
|||||||
Reference in New Issue
Block a user