home_page.dart 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // ignore_for_file: unnecessary_null_comparison
  2. import 'dart:async';
  3. import 'package:flutter/material.dart';
  4. import 'package:audioplayers/audioplayers.dart';
  5. /// Description: home page
  6. /// Time : 11/06/2023 Monday
  7. /// Author : liuyuqi.gov@msn.cn
  8. class HomePage extends StatefulWidget {
  9. HomePage({super.key});
  10. @override
  11. State<HomePage> createState() => _HomePageState();
  12. }
  13. class _HomePageState extends State<HomePage> {
  14. String url = "";
  15. late PlayerMode mode;
  16. late AudioPlayer _audioPlayer;
  17. late Duration _duration;
  18. late Duration _position;
  19. late StreamSubscription _durationSubscription;
  20. late StreamSubscription _positionSubscription;
  21. late StreamSubscription _playerCompleteSubscription;
  22. late StreamSubscription _playerErrorSubscription;
  23. late StreamSubscription _playerStateSubscription;
  24. get _durationText => _duration.toString().split('.').first;
  25. get _positionText => _position.toString().split('.').first;
  26. @override
  27. Widget build(BuildContext context) {
  28. return Scaffold(
  29. appBar: AppBar(
  30. title: const Text('Netease Music'),
  31. ),
  32. body: Column(
  33. children: [
  34. Text(
  35. _position != null
  36. ? '${_positionText ?? ''} / ${_durationText ?? ''}'
  37. : _duration != null
  38. ? _durationText
  39. : '',
  40. ),
  41. Padding(
  42. padding: const EdgeInsets.all(12.0),
  43. child: Stack(
  44. children: [
  45. Slider(
  46. onChanged: (v) {
  47. final Position = v * _duration.inMilliseconds;
  48. _audioPlayer.seek(Duration(milliseconds: Position.round()));
  49. },
  50. value: (_position.inMilliseconds > 0 &&
  51. _position.inMilliseconds < _duration.inMilliseconds)
  52. ? _position.inMilliseconds / _duration.inMilliseconds
  53. : 0.0,
  54. ),
  55. ],
  56. ),
  57. ),
  58. Row(
  59. children: [
  60. IconButton(
  61. icon: const Icon(Icons.play_arrow),
  62. onPressed: () {
  63. _play();
  64. }),
  65. IconButton(
  66. icon: const Icon(Icons.pause),
  67. onPressed: () {
  68. _pause();
  69. }),
  70. IconButton(
  71. icon: const Icon(Icons.stop),
  72. onPressed: () {
  73. _stop();
  74. }),
  75. ],
  76. )
  77. ],
  78. ),
  79. );
  80. }
  81. @override
  82. void initState() {
  83. super.initState();
  84. url = 'http://music.163.com/song/media/outer/url?id=476592630.mp3';
  85. _initAudioPlayer();
  86. }
  87. @override
  88. void dispose() {
  89. super.dispose();
  90. _audioPlayer.dispose();
  91. _durationSubscription.cancel();
  92. _positionSubscription.cancel();
  93. _playerCompleteSubscription.cancel();
  94. _playerErrorSubscription.cancel();
  95. _playerStateSubscription.cancel();
  96. }
  97. _initAudioPlayer() {
  98. mode = PlayerMode.mediaPlayer;
  99. //初始化
  100. _audioPlayer = AudioPlayer(mode: mode);
  101. _durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
  102. setState(() => _duration = duration);
  103. if (Theme.of(context).platform == TargetPlatform.iOS) {
  104. _audioPlayer.startHeadlessService();
  105. _audioPlayer.setNotification(
  106. title: 'App Name',
  107. artist: 'Artist or blank',
  108. albumTitle: 'Name or blank',
  109. imageUrl: 'url or blank',
  110. forwardSkipInterval: const Duration(seconds: 30), // default is 30s
  111. backwardSkipInterval: const Duration(seconds: 30), // default is 30s
  112. duration: duration,
  113. elapsedTime: const Duration(seconds: 0));
  114. }
  115. });
  116. //监听进度
  117. _positionSubscription =
  118. _audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
  119. _position = p;
  120. }));
  121. //播放完成
  122. _playerCompleteSubscription =
  123. _audioPlayer.onPlayerCompletion.listen((event) {
  124. // _onComplete();
  125. setState(() {
  126. _position = const Duration();
  127. });
  128. });
  129. //监听报错
  130. _playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
  131. print('audioPlayer error : $msg');
  132. setState(() {
  133. // _playerState = PlayerState.stopped;
  134. _duration = const Duration(seconds: 0);
  135. _position = const Duration(seconds: 0);
  136. });
  137. });
  138. //播放状态改变
  139. _audioPlayer.onPlayerStateChanged.listen((state) {
  140. if (!mounted) return;
  141. setState(() {});
  142. });
  143. ///// iOS中来自通知区域的玩家状态变化流。
  144. _audioPlayer.onDurationChanged.listen((state) {
  145. if (!mounted) return;
  146. });
  147. // _playingRouteState = PlayingRouteState.speakers;
  148. }
  149. //开始播放
  150. void _play() async {
  151. final playPosition = (_position.inMilliseconds > 0 &&
  152. _position.inMilliseconds < _duration.inMilliseconds)
  153. ? _position
  154. : null;
  155. await _audioPlayer.play(UrlSource(url), position: playPosition);
  156. _audioPlayer.setPlaybackRate(1.0);
  157. }
  158. //暂停
  159. void _pause() async {
  160. await _audioPlayer.pause();
  161. }
  162. //停止播放
  163. _stop() async {
  164. await _audioPlayer.stop();
  165. }
  166. }