From 56c26e2fd5fcd638b724fa0e02c08441ba8a7818 Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Thu, 22 Oct 2026 21:59:09 +0800 Subject: [PATCH] =?UTF-8?q?snapshot:=20=E5=AD=98=E6=A1=A3=20flutter=20crea?= =?UTF-8?q?te=20=E6=A8=A1=E6=9D=BF=E8=A6=86=E7=9B=96=E5=90=8E=E7=9A=84?= =?UTF-8?q?=E7=8E=B0=E5=9C=BA=EF=BC=8C=E4=BD=9C=E4=B8=BA=E5=A4=9A=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E4=BF=AE=E5=A4=8D=E5=89=8D=E7=9A=84=E5=9F=BA=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .metadata | 25 ++------ android/.gitignore | 3 +- android/app/build.gradle.kts | 53 +++++---------- android/app/proguard-rules.pro | 45 ------------- android/app/src/main/AndroidManifest.xml | 28 ++++---- .../example/qingting_player/MainActivity.kt | 20 +----- android/gradle.properties | 2 - .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/qt_player_android.iml | 29 --------- android/settings.gradle.kts | 4 +- lib/services/playback_service.dart | 41 +++++++++--- lib/services/player_service.dart | 32 ---------- pubspec.lock | 64 +++++++++---------- pubspec.yaml | 2 +- 14 files changed, 104 insertions(+), 246 deletions(-) delete mode 100644 android/app/proguard-rules.pro delete mode 100644 android/qt_player_android.iml delete mode 100644 lib/services/player_service.dart diff --git a/.metadata b/.metadata index 2459a95..f3fac87 100644 --- a/.metadata +++ b/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "ad70ec4617166f1c38e5d2bfd388af71fda14f06" + revision: "d3b14c876900e553bc736ca19295fc09e3853e8e" channel: "stable" project_type: app @@ -13,26 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06 - base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06 + create_revision: d3b14c876900e553bc736ca19295fc09e3853e8e + base_revision: d3b14c876900e553bc736ca19295fc09e3853e8e - platform: android - create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06 - base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06 - - 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 + create_revision: d3b14c876900e553bc736ca19295fc09e3853e8e + base_revision: d3b14c876900e553bc736ca19295fc09e3853e8e # User provided section diff --git a/android/.gitignore b/android/.gitignore index af2ddcd..513d70b 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -8,11 +8,10 @@ GeneratedPluginRegistrant.java .cxx/ .kotlin /build - +.settings # Remember to never publicly share your keystore. # See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks -.settings diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 5e4f79a..f494b5b 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,11 +1,12 @@ plugins { id("com.android.application") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") } android { namespace = "com.lxh.qingting_player" - compileSdk = 36 + compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion compileOptions { @@ -14,49 +15,25 @@ android { } defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 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 - targetSdk = 34 - versionCode = flutter.versionCode - versionName = flutter.versionName - - // 仅打包 arm64-v8a - ndk { - abiFilters.addAll(listOf("arm64-v8a")) - } - } - - // 显式指定 jniLibs 源目录 - sourceSets { - getByName("main") { - jniLibs.srcDirs("src/main/jniLibs") - } - } - - tasks.withType { - 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" + targetSdk = flutter.targetSdkVersion + // Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION + // 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` + // flag during build. + versionCode = 1 + versionName = "1.0.0" } buildTypes { - debug { - } - 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") - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) } } } @@ -69,4 +46,4 @@ kotlin { flutter { source = "../.." -} \ No newline at end of file +} diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro deleted file mode 100644 index 3adde53..0000000 --- a/android/app/proguard-rules.pro +++ /dev/null @@ -1,45 +0,0 @@ -# ============================================================ -# media_kit 核心 -# ============================================================ --keep class com.media_kit.** { *; } --keep class com.alexmercerind.** { *; } --keep class org.mozilla.** { *; } - -# 保留所有 native 方法 --keepclasseswithmembernames class * { - native ; -} - -# 保留所有 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(); -} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 903d1fe..15d5279 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - + package="com.lxh.qingting_player"> + @@ -15,8 +15,7 @@ android:label="清听" android:usesCleartextTraffic="true" android:foregroundServiceType="mediaPlayback" - android:extractNativeLibs="true"> - + android:extractNativeLibs="true"> - - + - - + + @@ -55,7 +54,7 @@ - + + - - + + - - \ No newline at end of file + diff --git a/android/app/src/main/kotlin/com/example/qingting_player/MainActivity.kt b/android/app/src/main/kotlin/com/example/qingting_player/MainActivity.kt index 0698e6a..817e08c 100644 --- a/android/app/src/main/kotlin/com/example/qingting_player/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/qingting_player/MainActivity.kt @@ -16,26 +16,8 @@ class MainActivity : FlutterActivity() { private val CHANNEL = "com.lxh.qingting_player/file_provider" 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) - requestAudioFocus() - setHighRefreshRate() } @@ -63,7 +45,7 @@ class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) - // FileProvider MethodChannel for sharing artwork via content:// URI + // FileProvider MethodChannel MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) .setMethodCallHandler { call, result -> if (call.method == "getContentUri") { diff --git a/android/gradle.properties b/android/gradle.properties index f445ec2..e96108c 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -3,6 +3,4 @@ android.useAndroidX=true # This newDsl flag was added by the Flutter template android.newDsl=false # This builtInKotlin flag was added by the Flutter template -kotlin.incremental=false -kotlin.parallel.tasks.in.project=false android.builtInKotlin=false diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 81daf92..f8deb6c 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME 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 diff --git a/android/qt_player_android.iml b/android/qt_player_android.iml deleted file mode 100644 index 3bc4b3b..0000000 --- a/android/qt_player_android.iml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index c21f0c5..b28021a 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,8 +19,8 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "9.0.1" apply false - id("org.jetbrains.kotlin.android") version "2.3.20" apply false + id("com.android.application") version "9.1.0" apply false + id("org.jetbrains.kotlin.android") version "2.4.0" apply false } include(":app") diff --git a/lib/services/playback_service.dart b/lib/services/playback_service.dart index 02674c3..b5e160f 100644 --- a/lib/services/playback_service.dart +++ b/lib/services/playback_service.dart @@ -1,20 +1,24 @@ // lib/services/playback_service.dart import 'package:media_kit/media_kit.dart'; +import 'package:flutter/foundation.dart'; -// ============================================================ -// PlaybackService - 播放引擎封装 -// 职责:管理 Player 生命周期,不涉及业务逻辑 -// ============================================================ class PlaybackService { static final PlaybackService _instance = PlaybackService._internal(); factory PlaybackService() => _instance; - PlaybackService._internal(); + PlaybackService._internal() { + // ⭐ 给单例本身打上 ID + _serviceId = DateTime.now().microsecondsSinceEpoch.toString(); + debugPrint('🎯 [PlaybackService] 单例创建, serviceId=$_serviceId'); + } Player? _player; bool _initialized = false; + late final String _serviceId; // ⭐ 服务实例 ID // ---------- Getter ---------- Player get player { + debugPrint( + '🎯 [PlaybackService] get player called, serviceId=$_serviceId, initialized=$_initialized, player=${_player?.hashCode}'); if (!_initialized) init(); return _player!; } @@ -23,16 +27,21 @@ class PlaybackService { // ---------- 初始化 ---------- void init() { - if (_initialized) return; + if (_initialized) { + debugPrint( + '⚠️ [PlaybackService] init() 被重复调用, 跳过, serviceId=$_serviceId, player=${_player?.hashCode}'); + return; + } _player = Player(); _initialized = true; - - // 可以在这里配置初始参数 - // _player.setVolume(1.0); + debugPrint( + '✅ [PlaybackService] Player 已创建, serviceId=$_serviceId, player=${_player.hashCode}'); } // ---------- 播放 ---------- Future play(String url, {Map? headers}) async { + debugPrint( + '▶️ [PlaybackService] play() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (!_initialized) init(); final media = (headers != null && headers.isNotEmpty) @@ -45,24 +54,32 @@ class PlaybackService { // ---------- 控制 ---------- Future pause() async { + debugPrint( + '⏸️ [PlaybackService] pause() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (_initialized && _player != null) { await _player!.pause(); } } Future resume() async { + debugPrint( + '▶️ [PlaybackService] resume() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (_initialized && _player != null) { await _player!.play(); } } Future stop() async { + debugPrint( + '⏹️ [PlaybackService] stop() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (_initialized && _player != null) { await _player!.stop(); } } Future seek(Duration position) async { + debugPrint( + '⏩ [PlaybackService] seek() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (_initialized && _player != null) { await _player!.seek(position); } @@ -76,6 +93,8 @@ class PlaybackService { // ---------- 释放 ---------- void dispose() { + debugPrint( + '🗑️ [PlaybackService] dispose() called, serviceId=$_serviceId, player=${_player?.hashCode}'); if (_initialized && _player != null) { _player!.dispose(); _player = null; @@ -83,8 +102,10 @@ class PlaybackService { } } - // ---------- 重新初始化(用于 Hot Restart 场景) ---------- + // ---------- 重新初始化 ---------- void reinitialize() { + debugPrint( + '🔄 [PlaybackService] reinitialize() called, serviceId=$_serviceId'); dispose(); init(); } diff --git a/lib/services/player_service.dart b/lib/services/player_service.dart deleted file mode 100644 index b4c77ee..0000000 --- a/lib/services/player_service.dart +++ /dev/null @@ -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; - } - - // 状态监听... -} diff --git a/pubspec.lock b/pubspec.lock index e46fe66..f66c551 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: archive - sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff + sha256: ace891da0862b0e4cabbb064ee3fd87b2728b898949fdb366d83fe98342c9f19 url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.9" + version: "4.2.0" args: dependency: transitive description: @@ -101,18 +101,18 @@ packages: dependency: transitive description: name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.2" + version: "1.1.3" code_assets: dependency: transitive description: name: code_assets - sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + sha256: cfd4f5f575a49c5f10ca856e9846073f1e6c3ee94912377eea5f6cefc5272941 url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "2.0.0" collection: dependency: transitive description: @@ -220,10 +220,10 @@ packages: dependency: transitive description: name: hooks - sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" + sha256: eaac480a35ec0814146c2c48d96aaa829e0e44a7662c88ae84c9edf4bc35651f url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.2" + version: "2.2.0" http: dependency: transitive description: @@ -244,10 +244,10 @@ packages: dependency: transitive description: name: image - sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce + sha256: "1976370a4df3091bb0f72409c187ad1f9132a818bc6b95ca59c0bae1c75c688e" url: "https://pub.flutter-io.cn" source: hosted - version: "4.8.0" + version: "4.9.2" intl: dependency: transitive description: @@ -268,10 +268,10 @@ packages: dependency: transitive description: name: jni_flutter - sha256: "7b717011ea40d04fd47c2731d3d1d36eb99eba3435c2753d62489e8c3c9991d5" + sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351 url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.2" + version: "1.0.3" jni_util: dependency: transitive description: @@ -284,10 +284,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.7" + version: "0.7.2" leak_tracker: dependency: transitive description: @@ -412,10 +412,10 @@ packages: dependency: transitive description: name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + sha256: bd47de35f07e27267e69c8c8b22edf9473bfee170a60d60fcc93730c5144b7f6 url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.1.0" nested: dependency: transitive description: @@ -428,10 +428,10 @@ packages: dependency: transitive description: name: objective_c - sha256: b7fb95a6d9a4f009edd63dc5ac69f07420b23a16161c6dd8660290b59c602e8e + sha256: ad56fd53a78ff6b1472fa59ff2a4e8b8ccabafc586fc263a1dfad0b99b5553e3 url: "https://pub.flutter-io.cn" source: hosted - version: "9.5.0" + version: "9.6.0" package_config: dependency: transitive description: @@ -588,18 +588,18 @@ packages: dependency: transitive description: name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.2.1" record_use: dependency: transitive description: name: record_use - sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + sha256: "1cb8564af8d43b464294411db9217f5ec04891c6f22ee2c32d73ae05e88a6bd2" url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.0" + version: "1.1.1" rxdart: dependency: transitive description: @@ -628,18 +628,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "0634e64bd719f89c012f392938e173521f535d3ecaf66558fa94a056d22b5cc7" + sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399" url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.27" + version: "2.4.28" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea" url: "https://pub.flutter-io.cn" source: hosted - version: "2.5.6" + version: "2.5.7" shared_preferences_linux: dependency: transitive description: @@ -729,10 +729,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" url: "https://pub.flutter-io.cn" source: hosted - version: "1.12.1" + version: "1.12.2" stream_channel: dependency: transitive description: @@ -817,10 +817,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0" url: "https://pub.flutter-io.cn" source: hosted - version: "15.2.0" + version: "15.3.0" web: dependency: transitive description: @@ -849,10 +849,10 @@ packages: dependency: transitive description: name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.3" + version: "3.1.4" sdks: dart: ">=3.12.0 <4.0.0" flutter: ">=3.44.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9fb2399..03afda5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: provider: ^6.1.2 dio: ^5.4.0 # HTTP 客户端 xml: ^6.5.0 - audio_service: ^0.18.19 + audio_service: 0.18.19 audio_session: ^0.1.21 permission_handler: ^11.3.1 flutter_cache_manager: ^3.3.1