Compare commits
2 Commits
v1025
...
feature-au
Author | SHA1 | Date | |
---|---|---|---|
cb3fd24cf7 | |||
3e8216923f |
@ -1,4 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.guozhigq.pilipala">
|
package="com.guozhigq.pilipala">
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
@ -63,6 +64,27 @@
|
|||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
|
<!-- ADD THIS "SERVICE" element -->
|
||||||
|
<service
|
||||||
|
android:name="com.ryanheise.audioservice.AudioService"
|
||||||
|
android:exported="true"
|
||||||
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<!-- ADD THIS "RECEIVER" element -->
|
||||||
|
<receiver
|
||||||
|
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
@ -265,4 +287,8 @@
|
|||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -37,5 +37,11 @@ end
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
|
||||||
|
'$(inherited)',
|
||||||
|
'AUDIO_SESSION_MICROPHONE=0'
|
||||||
|
]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- appscheme (1.0.4):
|
- appscheme (1.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- audio_service (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- audio_session (0.0.1):
|
||||||
|
- Flutter
|
||||||
- connectivity_plus (0.0.1):
|
- connectivity_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- ReachabilitySwift
|
- ReachabilitySwift
|
||||||
@ -14,8 +18,13 @@ PODS:
|
|||||||
- FMDB/standard (2.7.5)
|
- FMDB/standard (2.7.5)
|
||||||
- gt3_flutter_plugin (0.0.8):
|
- gt3_flutter_plugin (0.0.8):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
<<<<<<< HEAD
|
||||||
|
- just_audio (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
=======
|
||||||
- GT3Captcha-iOS
|
- GT3Captcha-iOS
|
||||||
- GT3Captcha-iOS (0.15.8.3)
|
- GT3Captcha-iOS (0.15.8.3)
|
||||||
|
>>>>>>> main
|
||||||
- media_kit_libs_ios_video (1.0.4):
|
- media_kit_libs_ios_video (1.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- media_kit_native_event_loop (1.0.0):
|
- media_kit_native_event_loop (1.0.0):
|
||||||
@ -56,11 +65,18 @@ PODS:
|
|||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- appscheme (from `.symlinks/plugins/appscheme/ios`)
|
- appscheme (from `.symlinks/plugins/appscheme/ios`)
|
||||||
|
- audio_service (from `.symlinks/plugins/audio_service/ios`)
|
||||||
|
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
||||||
|
<<<<<<< HEAD
|
||||||
|
- image_gallery_saver (from `.symlinks/plugins/image_gallery_saver/ios`)
|
||||||
|
- just_audio (from `.symlinks/plugins/just_audio/ios`)
|
||||||
|
=======
|
||||||
- gt3_flutter_plugin (from `.symlinks/plugins/gt3_flutter_plugin/ios`)
|
- gt3_flutter_plugin (from `.symlinks/plugins/gt3_flutter_plugin/ios`)
|
||||||
|
>>>>>>> main
|
||||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||||
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
|
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
|
||||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||||
@ -88,6 +104,10 @@ SPEC REPOS:
|
|||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
appscheme:
|
appscheme:
|
||||||
:path: ".symlinks/plugins/appscheme/ios"
|
:path: ".symlinks/plugins/appscheme/ios"
|
||||||
|
audio_service:
|
||||||
|
:path: ".symlinks/plugins/audio_service/ios"
|
||||||
|
audio_session:
|
||||||
|
:path: ".symlinks/plugins/audio_session/ios"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
@ -96,8 +116,15 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_volume_controller:
|
flutter_volume_controller:
|
||||||
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
||||||
|
<<<<<<< HEAD
|
||||||
|
image_gallery_saver:
|
||||||
|
:path: ".symlinks/plugins/image_gallery_saver/ios"
|
||||||
|
just_audio:
|
||||||
|
:path: ".symlinks/plugins/just_audio/ios"
|
||||||
|
=======
|
||||||
gt3_flutter_plugin:
|
gt3_flutter_plugin:
|
||||||
:path: ".symlinks/plugins/gt3_flutter_plugin/ios"
|
:path: ".symlinks/plugins/gt3_flutter_plugin/ios"
|
||||||
|
>>>>>>> main
|
||||||
media_kit_libs_ios_video:
|
media_kit_libs_ios_video:
|
||||||
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
||||||
media_kit_native_event_loop:
|
media_kit_native_event_loop:
|
||||||
@ -135,13 +162,20 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
appscheme: b1c3f8862331cb20430cf9e0e4af85dbc1572ad8
|
appscheme: b1c3f8862331cb20430cf9e0e4af85dbc1572ad8
|
||||||
|
audio_service: f509d65da41b9521a61f1c404dd58651f265a567
|
||||||
|
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
|
||||||
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
|
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
|
||||||
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
|
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529
|
flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
|
<<<<<<< HEAD
|
||||||
|
image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
|
||||||
|
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
||||||
|
=======
|
||||||
gt3_flutter_plugin: bfa1f26e9a09dc00401514be5ed437f964cabf23
|
gt3_flutter_plugin: bfa1f26e9a09dc00401514be5ed437f964cabf23
|
||||||
GT3Captcha-iOS: 5e3b1077834d8a9d6f4d64a447a30af3e14affe6
|
GT3Captcha-iOS: 5e3b1077834d8a9d6f4d64a447a30af3e14affe6
|
||||||
|
>>>>>>> main
|
||||||
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
|
||||||
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
|
||||||
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
|
||||||
@ -161,6 +195,6 @@ SPEC CHECKSUMS:
|
|||||||
webview_cookie_manager: eaf920722b493bd0f7611b5484771ca53fed03f7
|
webview_cookie_manager: eaf920722b493bd0f7611b5484771ca53fed03f7
|
||||||
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
|
||||||
|
|
||||||
PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b
|
PODFILE CHECKSUM: fc8a34c4ba2e14d31df90bf03cf419a764f2778c
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
COCOAPODS: 1.12.1
|
||||||
|
@ -103,6 +103,10 @@
|
|||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
|
<<<<<<< HEAD
|
||||||
|
<!-- audio service配置 -->
|
||||||
|
=======
|
||||||
|
>>>>>>> main
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>audio</string>
|
<string>audio</string>
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
|
import 'package:audio_service/audio_service.dart';
|
||||||
|
=======
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
>>>>>>> main
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
@ -29,7 +33,22 @@ void main() async {
|
|||||||
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown])
|
||||||
.then((_) async {
|
.then((_) async {
|
||||||
await GStrorage.init();
|
await GStrorage.init();
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
await AudioService.init<AudioHandler>(
|
||||||
|
builder: () => MyAudioHandler(),
|
||||||
|
config: const AudioServiceConfig(
|
||||||
|
androidNotificationChannelId: 'com.guozhigq.pilipala.channel.audio',
|
||||||
|
androidNotificationChannelName: 'Music playback',
|
||||||
|
androidNotificationOngoing: true,
|
||||||
|
androidStopForegroundOnPause: true,
|
||||||
|
androidNotificationIcon: 'drawable/audio_service_icon',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
=======
|
||||||
await setupServiceLocator();
|
await setupServiceLocator();
|
||||||
|
>>>>>>> main
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
// 小白条、导航栏沉浸
|
// 小白条、导航栏沉浸
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||||
@ -157,3 +176,34 @@ class MyApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyAudioHandler extends BaseAudioHandler
|
||||||
|
with
|
||||||
|
QueueHandler, // mix in default queue callback implementations
|
||||||
|
SeekHandler {
|
||||||
|
// mix in default seek callback implementations
|
||||||
|
|
||||||
|
// The most common callbacks:
|
||||||
|
@override
|
||||||
|
Future<void> play() async {
|
||||||
|
print('play');
|
||||||
|
// All 'play' requests from all origins route to here. Implement this
|
||||||
|
// callback to start playing audio appropriate to your app. e.g. music.
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@override
|
||||||
|
Future<void> pause() async {}
|
||||||
|
|
||||||
|
///
|
||||||
|
@override
|
||||||
|
Future<void> stop() async {}
|
||||||
|
|
||||||
|
///
|
||||||
|
@override
|
||||||
|
Future<void> seek(Duration position) async {}
|
||||||
|
|
||||||
|
///
|
||||||
|
@override
|
||||||
|
Future<void> skipToQueueItem(int i) async {}
|
||||||
|
}
|
||||||
|
0
lib/pages/audio/controller.dart
Normal file
0
lib/pages/audio/controller.dart
Normal file
4
lib/pages/audio/index.dart
Normal file
4
lib/pages/audio/index.dart
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
library pl_audio_player;
|
||||||
|
|
||||||
|
export './view.dart';
|
||||||
|
export './controller.dart';
|
539
lib/pages/audio/view.dart
Normal file
539
lib/pages/audio/view.dart
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:audio_service/audio_service.dart';
|
||||||
|
import 'package:audio_session/audio_session.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:just_audio/just_audio.dart';
|
||||||
|
// import 'package:just_audio_background/just_audio_background.dart';
|
||||||
|
|
||||||
|
class AudioPlayerPage extends StatefulWidget {
|
||||||
|
const AudioPlayerPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AudioPlayerPage> createState() => _AudioPlayerPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AudioPlayerPageState extends State<AudioPlayerPage> {
|
||||||
|
static int _nextMediaId = 0;
|
||||||
|
late AudioPlayer _player;
|
||||||
|
final _playlist = ConcatenatingAudioSource(children: [
|
||||||
|
ClippingAudioSource(
|
||||||
|
start: const Duration(seconds: 0),
|
||||||
|
end: const Duration(seconds: 90),
|
||||||
|
child: AudioSource.uri(Uri.parse(
|
||||||
|
"https://s3.amazonaws.com/scifri-episodes/scifri20181123-episode.mp3")),
|
||||||
|
tag: MediaItem(
|
||||||
|
id: '${_nextMediaId++}',
|
||||||
|
album: "Science Friday",
|
||||||
|
title: "A Salute To Head-Scratching Science (30 seconds)",
|
||||||
|
artUri: Uri.parse(
|
||||||
|
"https://media.wnyc.org/i/1400/1400/l/80/1/ScienceFriday_WNYCStudios_1400.jpg"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// AudioSource.uri(
|
||||||
|
// Uri.parse(
|
||||||
|
// "https://upos-sz-mirror08c.bilivideo.com/upgcxcode/05/52/1205825205/1205825205-1-16.mp4?e=ig8euxZM2rNcNbRVhwdVhwdlhWdVhwdVhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1693821903&gen=playurlv2&os=08cbv&oi=1865700872&trid=bfc9c19f85c545dd8f4794ff97f4f57fh&mid=17340771&platform=html5&upsig=9bf98515091bb8a80e1950a03a2a0d68&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,mid,platform&bvc=vod&nettype=0&f=h_0_0&bw=49663&logo=80000000"),
|
||||||
|
// headers: {
|
||||||
|
// 'user-agent':
|
||||||
|
// 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15',
|
||||||
|
// 'referer': 'https://www.bilibili.com'
|
||||||
|
// },
|
||||||
|
// tag: MediaItem(
|
||||||
|
// id: '${_nextMediaId++}',
|
||||||
|
// album: "Science Friday",
|
||||||
|
// title: "A Salute To Head-Scratching Science",
|
||||||
|
// artUri: Uri.parse(
|
||||||
|
// "https://media.wnyc.org/i/1400/1400/l/80/1/ScienceFriday_WNYCStudios_1400.jpg"),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
AudioSource.uri(
|
||||||
|
Uri.parse("https://s3.amazonaws.com/scifri-segments/scifri201711241.mp3"),
|
||||||
|
tag: MediaItem(
|
||||||
|
id: '${_nextMediaId++}',
|
||||||
|
album: "Science Friday",
|
||||||
|
title: "From Cat Rheology To Operatic Incompetence",
|
||||||
|
artUri: Uri.parse(
|
||||||
|
"https://media.wnyc.org/i/1400/1400/l/80/1/ScienceFriday_WNYCStudios_1400.jpg"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AudioSource.uri(
|
||||||
|
Uri.parse("asset:///audio/nature.mp3"),
|
||||||
|
tag: MediaItem(
|
||||||
|
id: '${_nextMediaId++}',
|
||||||
|
album: "Public Domain",
|
||||||
|
title: "Nature Sounds",
|
||||||
|
artUri: Uri.parse(
|
||||||
|
"https://media.wnyc.org/i/1400/1400/l/80/1/ScienceFriday_WNYCStudios_1400.jpg"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_player = AudioPlayer();
|
||||||
|
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_player.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _init() async {
|
||||||
|
final session = await AudioSession.instance;
|
||||||
|
await session.configure(const AudioSessionConfiguration.speech());
|
||||||
|
// Listen to errors during playback.
|
||||||
|
_player.playbackEventStream.listen((event) {},
|
||||||
|
onError: (Object e, StackTrace stackTrace) {
|
||||||
|
print('A stream error occurred: $e');
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await _player.setAudioSource(_playlist);
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
// Catch load errors: 404, invalid url ...
|
||||||
|
print("Error loading playlist: $e");
|
||||||
|
print(stackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream<PositionData> get _positionDataStream =>
|
||||||
|
// Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
|
||||||
|
// _player.positionStream,
|
||||||
|
// _player.bufferedPositionStream,
|
||||||
|
// _player.durationStream,
|
||||||
|
// (position, bufferedPosition, duration) => PositionData(
|
||||||
|
// position, bufferedPosition, duration ?? Duration.zero));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: SafeArea(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: StreamBuilder<SequenceState?>(
|
||||||
|
stream: _player.sequenceStateStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final state = snapshot.data;
|
||||||
|
if (state?.sequence.isEmpty ?? true) {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
final metadata = state!.currentSource!.tag as MediaItem;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Center(
|
||||||
|
child: Image.network(metadata.artUri.toString())),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(metadata.album!,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
Text(metadata.title),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ControlButtons(_player),
|
||||||
|
// StreamBuilder<PositionData>(
|
||||||
|
// stream: _positionDataStream,
|
||||||
|
// builder: (context, snapshot) {
|
||||||
|
// final positionData = snapshot.data;
|
||||||
|
// return SeekBar(
|
||||||
|
// duration: positionData?.duration ?? Duration.zero,
|
||||||
|
// position: positionData?.position ?? Duration.zero,
|
||||||
|
// bufferedPosition:
|
||||||
|
// positionData?.bufferedPosition ?? Duration.zero,
|
||||||
|
// onChangeEnd: (newPosition) {
|
||||||
|
// _player.seek(newPosition);
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
const SizedBox(height: 8.0),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
StreamBuilder<LoopMode>(
|
||||||
|
stream: _player.loopModeStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final loopMode = snapshot.data ?? LoopMode.off;
|
||||||
|
const icons = [
|
||||||
|
Icon(Icons.repeat, color: Colors.grey),
|
||||||
|
Icon(Icons.repeat, color: Colors.orange),
|
||||||
|
Icon(Icons.repeat_one, color: Colors.orange),
|
||||||
|
];
|
||||||
|
const cycleModes = [
|
||||||
|
LoopMode.off,
|
||||||
|
LoopMode.all,
|
||||||
|
LoopMode.one,
|
||||||
|
];
|
||||||
|
final index = cycleModes.indexOf(loopMode);
|
||||||
|
return IconButton(
|
||||||
|
icon: icons[index],
|
||||||
|
onPressed: () {
|
||||||
|
_player.setLoopMode(cycleModes[
|
||||||
|
(cycleModes.indexOf(loopMode) + 1) %
|
||||||
|
cycleModes.length]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"Playlist",
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StreamBuilder<bool>(
|
||||||
|
stream: _player.shuffleModeEnabledStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final shuffleModeEnabled = snapshot.data ?? false;
|
||||||
|
return IconButton(
|
||||||
|
icon: shuffleModeEnabled
|
||||||
|
? const Icon(Icons.shuffle, color: Colors.orange)
|
||||||
|
: const Icon(Icons.shuffle, color: Colors.grey),
|
||||||
|
onPressed: () async {
|
||||||
|
final enable = !shuffleModeEnabled;
|
||||||
|
if (enable) {
|
||||||
|
await _player.shuffle();
|
||||||
|
}
|
||||||
|
await _player.setShuffleModeEnabled(enable);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 240.0,
|
||||||
|
child: StreamBuilder<SequenceState?>(
|
||||||
|
stream: _player.sequenceStateStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final state = snapshot.data;
|
||||||
|
final sequence = state?.sequence ?? [];
|
||||||
|
return ReorderableListView(
|
||||||
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
|
if (oldIndex < newIndex) newIndex--;
|
||||||
|
_playlist.move(oldIndex, newIndex);
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
for (var i = 0; i < sequence.length; i++)
|
||||||
|
Dismissible(
|
||||||
|
key: ValueKey(sequence[i]),
|
||||||
|
background: Container(
|
||||||
|
color: Colors.redAccent,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.only(right: 8.0),
|
||||||
|
child: Icon(Icons.delete, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onDismissed: (dismissDirection) {
|
||||||
|
_playlist.removeAt(i);
|
||||||
|
},
|
||||||
|
child: Material(
|
||||||
|
color: i == state!.currentIndex
|
||||||
|
? Colors.grey.shade300
|
||||||
|
: null,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(sequence[i].tag.title as String),
|
||||||
|
onTap: () {
|
||||||
|
_player.seek(Duration.zero, index: i);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ControlButtons extends StatelessWidget {
|
||||||
|
final AudioPlayer player;
|
||||||
|
|
||||||
|
const ControlButtons(this.player, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.volume_up),
|
||||||
|
onPressed: () {
|
||||||
|
showSliderDialog(
|
||||||
|
context: context,
|
||||||
|
title: "Adjust volume",
|
||||||
|
divisions: 10,
|
||||||
|
min: 0.0,
|
||||||
|
max: 1.0,
|
||||||
|
stream: player.volumeStream,
|
||||||
|
onChanged: player.setVolume,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
StreamBuilder<SequenceState?>(
|
||||||
|
stream: player.sequenceStateStream,
|
||||||
|
builder: (context, snapshot) => IconButton(
|
||||||
|
icon: const Icon(Icons.skip_previous),
|
||||||
|
onPressed: player.hasPrevious ? player.seekToPrevious : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StreamBuilder<PlayerState>(
|
||||||
|
stream: player.playerStateStream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final playerState = snapshot.data;
|
||||||
|
final processingState = playerState?.processingState;
|
||||||
|
final playing = playerState?.playing;
|
||||||
|
if (processingState == ProcessingState.loading ||
|
||||||
|
processingState == ProcessingState.buffering) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.all(8.0),
|
||||||
|
width: 64.0,
|
||||||
|
height: 64.0,
|
||||||
|
child: const CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
} else if (playing != true) {
|
||||||
|
return IconButton(
|
||||||
|
icon: const Icon(Icons.play_arrow),
|
||||||
|
iconSize: 64.0,
|
||||||
|
onPressed: player.play,
|
||||||
|
);
|
||||||
|
} else if (processingState != ProcessingState.completed) {
|
||||||
|
return IconButton(
|
||||||
|
icon: const Icon(Icons.pause),
|
||||||
|
iconSize: 64.0,
|
||||||
|
onPressed: player.pause,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return IconButton(
|
||||||
|
icon: const Icon(Icons.replay),
|
||||||
|
iconSize: 64.0,
|
||||||
|
onPressed: () => player.seek(Duration.zero,
|
||||||
|
index: player.effectiveIndices!.first),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
StreamBuilder<SequenceState?>(
|
||||||
|
stream: player.sequenceStateStream,
|
||||||
|
builder: (context, snapshot) => IconButton(
|
||||||
|
icon: const Icon(Icons.skip_next),
|
||||||
|
onPressed: player.hasNext ? player.seekToNext : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StreamBuilder<double>(
|
||||||
|
stream: player.speedStream,
|
||||||
|
builder: (context, snapshot) => IconButton(
|
||||||
|
icon: Text("${snapshot.data?.toStringAsFixed(1)}x",
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
onPressed: () {
|
||||||
|
showSliderDialog(
|
||||||
|
context: context,
|
||||||
|
title: "Adjust speed",
|
||||||
|
divisions: 10,
|
||||||
|
min: 0.5,
|
||||||
|
max: 1.5,
|
||||||
|
stream: player.speedStream,
|
||||||
|
onChanged: player.setSpeed,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showSliderDialog({
|
||||||
|
required BuildContext context,
|
||||||
|
required String title,
|
||||||
|
required int divisions,
|
||||||
|
required double min,
|
||||||
|
required double max,
|
||||||
|
String valueSuffix = '',
|
||||||
|
required Stream<double> stream,
|
||||||
|
required ValueChanged<double> onChanged,
|
||||||
|
}) {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text(title, textAlign: TextAlign.center),
|
||||||
|
content: StreamBuilder<double>(
|
||||||
|
stream: stream,
|
||||||
|
builder: (context, snapshot) => SizedBox(
|
||||||
|
height: 100.0,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text('${snapshot.data?.toStringAsFixed(1)}$valueSuffix',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: 'Fixed',
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 24.0)),
|
||||||
|
Slider(
|
||||||
|
divisions: divisions,
|
||||||
|
min: min,
|
||||||
|
max: max,
|
||||||
|
value: snapshot.data ?? 1.0,
|
||||||
|
onChanged: onChanged,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PositionData {
|
||||||
|
final Duration position;
|
||||||
|
final Duration bufferedPosition;
|
||||||
|
final Duration duration;
|
||||||
|
|
||||||
|
PositionData(this.position, this.bufferedPosition, this.duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeekBar extends StatefulWidget {
|
||||||
|
final Duration duration;
|
||||||
|
final Duration position;
|
||||||
|
final Duration bufferedPosition;
|
||||||
|
final ValueChanged<Duration>? onChanged;
|
||||||
|
final ValueChanged<Duration>? onChangeEnd;
|
||||||
|
|
||||||
|
const SeekBar({
|
||||||
|
Key? key,
|
||||||
|
required this.duration,
|
||||||
|
required this.position,
|
||||||
|
required this.bufferedPosition,
|
||||||
|
this.onChanged,
|
||||||
|
this.onChangeEnd,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
SeekBarState createState() => SeekBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SeekBarState extends State<SeekBar> {
|
||||||
|
double? _dragValue;
|
||||||
|
late SliderThemeData _sliderThemeData;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
|
||||||
|
_sliderThemeData = SliderTheme.of(context).copyWith(
|
||||||
|
trackHeight: 2.0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
SliderTheme(
|
||||||
|
data: _sliderThemeData.copyWith(
|
||||||
|
thumbShape: HiddenThumbComponentShape(),
|
||||||
|
activeTrackColor: Colors.blue.shade100,
|
||||||
|
inactiveTrackColor: Colors.grey.shade300,
|
||||||
|
),
|
||||||
|
child: ExcludeSemantics(
|
||||||
|
child: Slider(
|
||||||
|
min: 0.0,
|
||||||
|
max: widget.duration.inMilliseconds.toDouble(),
|
||||||
|
value: min(widget.bufferedPosition.inMilliseconds.toDouble(),
|
||||||
|
widget.duration.inMilliseconds.toDouble()),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_dragValue = value;
|
||||||
|
});
|
||||||
|
if (widget.onChanged != null) {
|
||||||
|
widget.onChanged!(Duration(milliseconds: value.round()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChangeEnd: (value) {
|
||||||
|
if (widget.onChangeEnd != null) {
|
||||||
|
widget.onChangeEnd!(Duration(milliseconds: value.round()));
|
||||||
|
}
|
||||||
|
_dragValue = null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliderTheme(
|
||||||
|
data: _sliderThemeData.copyWith(
|
||||||
|
inactiveTrackColor: Colors.transparent,
|
||||||
|
),
|
||||||
|
child: Slider(
|
||||||
|
min: 0.0,
|
||||||
|
max: widget.duration.inMilliseconds.toDouble(),
|
||||||
|
value: min(_dragValue ?? widget.position.inMilliseconds.toDouble(),
|
||||||
|
widget.duration.inMilliseconds.toDouble()),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_dragValue = value;
|
||||||
|
});
|
||||||
|
if (widget.onChanged != null) {
|
||||||
|
widget.onChanged!(Duration(milliseconds: value.round()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChangeEnd: (value) {
|
||||||
|
if (widget.onChangeEnd != null) {
|
||||||
|
widget.onChangeEnd!(Duration(milliseconds: value.round()));
|
||||||
|
}
|
||||||
|
_dragValue = null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 16.0,
|
||||||
|
bottom: 0.0,
|
||||||
|
child: Text(
|
||||||
|
RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
|
||||||
|
.firstMatch("$_remaining")
|
||||||
|
?.group(1) ??
|
||||||
|
'$_remaining',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration get _remaining => widget.duration - widget.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
class HiddenThumbComponentShape extends SliderComponentShape {
|
||||||
|
@override
|
||||||
|
Size getPreferredSize(bool isEnabled, bool isDiscrete) => Size.zero;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(
|
||||||
|
PaintingContext context,
|
||||||
|
Offset center, {
|
||||||
|
required Animation<double> activationAnimation,
|
||||||
|
required Animation<double> enableAnimation,
|
||||||
|
required bool isDiscrete,
|
||||||
|
required TextPainter labelPainter,
|
||||||
|
required RenderBox parentBox,
|
||||||
|
required SliderThemeData sliderTheme,
|
||||||
|
required TextDirection textDirection,
|
||||||
|
required double value,
|
||||||
|
required double textScaleFactor,
|
||||||
|
required Size sizeWithOverflow,
|
||||||
|
}) {}
|
||||||
|
}
|
@ -354,6 +354,28 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 105,
|
||||||
|
bottom: 10,
|
||||||
|
child: TextButton.icon(
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateProperty
|
||||||
|
.resolveWith((states) {
|
||||||
|
return Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primaryContainer;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
Get.toNamed('/audioPlayer'),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.multitrack_audio_outlined,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
label: const Text('音频'),
|
||||||
|
),
|
||||||
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 12,
|
right: 12,
|
||||||
bottom: 10,
|
bottom: 10,
|
||||||
@ -372,7 +394,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
Icons.play_circle_outline,
|
Icons.play_circle_outline,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
label: const Text('Play'),
|
label: const Text('视频'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/pages/about/index.dart';
|
import 'package:pilipala/pages/about/index.dart';
|
||||||
|
import 'package:pilipala/pages/audio/index.dart';
|
||||||
import 'package:pilipala/pages/blacklist/index.dart';
|
import 'package:pilipala/pages/blacklist/index.dart';
|
||||||
import 'package:pilipala/pages/dynamics/deatil/index.dart';
|
import 'package:pilipala/pages/dynamics/deatil/index.dart';
|
||||||
import 'package:pilipala/pages/dynamics/index.dart';
|
import 'package:pilipala/pages/dynamics/index.dart';
|
||||||
@ -114,6 +115,10 @@ class Routes {
|
|||||||
name: '/displayModeSetting', page: () => const SetDiaplayMode()),
|
name: '/displayModeSetting', page: () => const SetDiaplayMode()),
|
||||||
// 关于
|
// 关于
|
||||||
CustomGetPage(name: '/about', page: () => const AboutPage()),
|
CustomGetPage(name: '/about', page: () => const AboutPage()),
|
||||||
|
<<<<<<< HEAD
|
||||||
|
// 音频播放
|
||||||
|
CustomGetPage(name: '/audioPlayer', page: () => const AudioPlayerPage()),
|
||||||
|
=======
|
||||||
//
|
//
|
||||||
CustomGetPage(name: '/htmlRender', page: () => const HtmlRenderPage()),
|
CustomGetPage(name: '/htmlRender', page: () => const HtmlRenderPage()),
|
||||||
// 历史记录搜索
|
// 历史记录搜索
|
||||||
@ -125,6 +130,7 @@ class Routes {
|
|||||||
CustomGetPage(name: '/favSearch', page: () => const FavSearchPage()),
|
CustomGetPage(name: '/favSearch', page: () => const FavSearchPage()),
|
||||||
// 登录页面
|
// 登录页面
|
||||||
CustomGetPage(name: '/loginPage', page: () => const LoginPage()),
|
CustomGetPage(name: '/loginPage', page: () => const LoginPage()),
|
||||||
|
>>>>>>> main
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import connectivity_plus
|
|||||||
import device_info_plus
|
import device_info_plus
|
||||||
import dynamic_color
|
import dynamic_color
|
||||||
import flutter_volume_controller
|
import flutter_volume_controller
|
||||||
|
import just_audio
|
||||||
import media_kit_libs_macos_video
|
import media_kit_libs_macos_video
|
||||||
import media_kit_video
|
import media_kit_video
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
@ -28,6 +29,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||||
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
||||||
FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin"))
|
FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin"))
|
||||||
|
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
||||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||||
|
31
pubspec.lock
31
pubspec.lock
@ -69,10 +69,17 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: audio_service
|
name: audio_service
|
||||||
|
<<<<<<< HEAD
|
||||||
|
sha256: dc3d10682b688f4779e0f4662586f1385f0c09169a6bbc42dcc193b9d4b6113f
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.18.11"
|
||||||
|
=======
|
||||||
sha256: a4d989f1225ea9621898d60f23236dcbfc04876fa316086c23c5c4af075dbac4
|
sha256: a4d989f1225ea9621898d60f23236dcbfc04876fa316086c23c5c4af075dbac4
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.18.12"
|
version: "0.18.12"
|
||||||
|
>>>>>>> main
|
||||||
audio_service_platform_interface:
|
audio_service_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -749,6 +756,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.1"
|
version: "4.8.1"
|
||||||
|
just_audio:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: just_audio
|
||||||
|
sha256: "890cd0fc41a1a4530c171e375a2a3fb6a09d84e9d508c5195f40bcff54330327"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.34"
|
||||||
|
just_audio_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: just_audio_platform_interface
|
||||||
|
sha256: d8409da198bbc59426cd45d4c92fca522a2ec269b576ce29459d6d6fcaeb44df
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
|
just_audio_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: just_audio_web
|
||||||
|
sha256: ff62f733f437b25a0ff590f0e295fa5441dcb465f1edbdb33b3dea264705bc13
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.8"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -121,6 +121,8 @@ dependencies:
|
|||||||
ref: master
|
ref: master
|
||||||
# 状态栏图标控制
|
# 状态栏图标控制
|
||||||
status_bar_control: ^3.2.1
|
status_bar_control: ^3.2.1
|
||||||
|
# 音频播放
|
||||||
|
just_audio: ^0.9.34
|
||||||
# 代理
|
# 代理
|
||||||
system_proxy: ^0.1.0
|
system_proxy: ^0.1.0
|
||||||
# pip
|
# pip
|
||||||
|
Reference in New Issue
Block a user