当前位置:网站首页>flutter 音乐播放器audioplayer
flutter 音乐播放器audioplayer
2022-04-22 02:13:00 【weixin_44911775】
audioplayer: ^0.8.1
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:path_provider/path_provider.dart';
typedef void OnError(Exception exception);
const kUrl =
"https://www.mediacollege.com/downloads/sound-effects/nature/forest/rainforest-ambient.mp3";
void main() {
runApp(MaterialApp(home: Scaffold(body: AudioApp())));
}
enum PlayerState {
stopped, playing, paused }
class AudioApp extends StatefulWidget {
@override
_AudioAppState createState() => _AudioAppState();
}
class _AudioAppState extends State<AudioApp> {
Duration duration;
Duration position;
AudioPlayer audioPlayer;
String localFilePath;
PlayerState playerState = PlayerState.stopped;
get isPlaying => playerState == PlayerState.playing;
get isPaused => playerState == PlayerState.paused;
get durationText =>
duration != null ? duration.toString().split('.').first : '';
get positionText =>
position != null ? position.toString().split('.').first : '';
bool isMuted = false;
StreamSubscription _positionSubscription;
StreamSubscription _audioPlayerStateSubscription;
@override
void initState() {
super.initState();
initAudioPlayer();
}
@override
void dispose() {
_positionSubscription.cancel();
_audioPlayerStateSubscription.cancel();
audioPlayer.stop();
super.dispose();
}
void initAudioPlayer() {
audioPlayer = AudioPlayer();
_positionSubscription = audioPlayer.onAudioPositionChanged
.listen((p) => setState(() => position = p));
_audioPlayerStateSubscription =
audioPlayer.onPlayerStateChanged.listen((s) {
if (s == AudioPlayerState.PLAYING) {
setState(() => duration = audioPlayer.duration);
} else if (s == AudioPlayerState.STOPPED) {
onComplete();
setState(() {
position = duration;
});
}
}, onError: (msg) {
setState(() {
playerState = PlayerState.stopped;
duration = Duration(seconds: 0);
position = Duration(seconds: 0);
});
});
}
Future play() async {
await audioPlayer.play(kUrl);
setState(() {
playerState = PlayerState.playing;
});
}
Future _playLocal() async {
await audioPlayer.play(localFilePath, isLocal: true);
setState(() => playerState = PlayerState.playing);
}
Future pause() async {
await audioPlayer.pause();
setState(() => playerState = PlayerState.paused);
}
Future stop() async {
await audioPlayer.stop();
setState(() {
playerState = PlayerState.stopped;
position = Duration();
});
}
Future mute(bool muted) async {
await audioPlayer.mute(muted);
setState(() {
isMuted = muted;
});
}
void onComplete() {
setState(() => playerState = PlayerState.stopped);
}
Future<Uint8List> _loadFileBytes(String url, {
OnError onError}) async {
Uint8List bytes;
try {
bytes = await readBytes(url);
} on ClientException {
rethrow;
}
return bytes;
}
Future _loadFile() async {
final bytes = await _loadFileBytes(kUrl,
onError: (Exception exception) =>
print('_loadFile => exception $exception'));
final dir = await getApplicationDocumentsDirectory();
final file = File('${dir.path}/audio.mp3');
await file.writeAsBytes(bytes);
if (await file.exists())
setState(() {
localFilePath = file.path;
});
}
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Center(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Flutter Audioplayer',
style: textTheme.headline,
),
Material(child: _buildPlayer()),
if (!kIsWeb)
localFilePath != null ? Text(localFilePath) : Container(),
if (!kIsWeb)
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () => _loadFile(),
child: Text('Download'),
),
if (localFilePath != null)
RaisedButton(
onPressed: () => _playLocal(),
child: Text('play local'),
),
],
),
),
],
),
),
);
}
Widget _buildPlayer() => Container(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(mainAxisSize: MainAxisSize.min, children: [
IconButton(
onPressed: isPlaying ? null : () => play(),
iconSize: 64.0,
icon: Icon(Icons.play_arrow),
color: Colors.cyan,
),
IconButton(
onPressed: isPlaying ? () => pause() : null,
iconSize: 64.0,
icon: Icon(Icons.pause),
color: Colors.cyan,
),
IconButton(
onPressed: isPlaying || isPaused ? () => stop() : null,
iconSize: 64.0,
icon: Icon(Icons.stop),
color: Colors.cyan,
),
]),
if (duration != null)
Slider(
value: position?.inMilliseconds?.toDouble() ?? 0.0,
onChanged: (double value) {
return audioPlayer.seek((value / 1000).roundToDouble());
},
min: 0.0,
max: duration.inMilliseconds.toDouble()),
if (position != null) _buildMuteButtons(),
if (position != null) _buildProgressView()
],
),
);
Row _buildProgressView() => Row(mainAxisSize: MainAxisSize.min, children: [
Padding(
padding: EdgeInsets.all(12.0),
child: CircularProgressIndicator(
value: position != null && position.inMilliseconds > 0
? (position?.inMilliseconds?.toDouble() ?? 0.0) /
(duration?.inMilliseconds?.toDouble() ?? 0.0)
: 0.0,
valueColor: AlwaysStoppedAnimation(Colors.cyan),
backgroundColor: Colors.grey.shade400,
),
),
Text(
position != null
? "${positionText ?? ''} / ${durationText ?? ''}"
: duration != null ? durationText : '',
style: TextStyle(fontSize: 24.0),
)
]);
Row _buildMuteButtons() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (!isMuted)
FlatButton.icon(
onPressed: () => mute(true),
icon: Icon(
Icons.headset_off,
color: Colors.cyan,
),
label: Text('Mute', style: TextStyle(color: Colors.cyan)),
),
if (isMuted)
FlatButton.icon(
onPressed: () => mute(false),
icon: Icon(Icons.headset, color: Colors.cyan),
label: Text('Unmute', style: TextStyle(color: Colors.cyan)),
),
],
);
}
}
版权声明
本文为[weixin_44911775]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_44911775/article/details/124299958
边栏推荐
- SSLHandshakeException
- Hexadecimal conversion
- Hj6 prime factor
- MySQL modifies a field to auto increment
- 3D立体相册模板(大小可更改)
- Leetcode 733, image rendering
- error:there‘s no Qt version assigned to project please assign a Qt installation in qt project settin
- 高级android面试答案,Gradle源码全解析
- Advanced file IO of system programming (12) -- blocking and non blocking reading
- Raspberry pie 4B 8g installation log (3) - Programming Environment
猜你喜欢

NLP model summary

In PostgreSQL, convert a string to an integer or floating-point type in the query result

postgresql中在查询结果中将字符串转换为整形或浮点型

The youqilin 22.04 lts version system will be released on April 22, equipped with the new ukui 3.1

Leetcode 141, circular linked list
![[DFS] [pruning] Sudoku (simple version)](/img/72/52b8b7079b48141e8073100133fae0.png)
[DFS] [pruning] Sudoku (simple version)

Basic operation of MySQL database ------ (basic addition, deletion, query and modification)

How to select the appropriate neo4j Version (2022)

Leetcode-232 - queue implementation with stack

IP报文分析笔记
随机推荐
高级UI都没弄明白凭什么拿高薪,劲爆
8种MySQL常见SQL错误用法详解
Advanced C language formula 42: analysis of classical problems of memory operation II
Introduction to Alibaba's super large-scale Flink cluster operation and maintenance system
php. ini Module ‘redis‘ already loaded in Unknown on line 0
IP报文分析笔记
Use Wx The showactionsheet selection box modifies the information in the database. Why does it report an error that data is not defined
Page 107 planning and design of enterprise digital transformation
PMSM or im12 sector model predictive torque control
高级android面试答案,Gradle源码全解析
Why won't MySQL lose data when the power is suddenly off? (Collection)
Stack and queue
Login procedure 2
Leetcode 1572, sum of diagonal elements of matrix
Ezreal--将一个动画切割为四动作动画成功---New Unity Project (3).
MySQL modifies a field to auto increment
718. Longest repeating subarray
Leetcode-232 - queue implementation with stack
Swoole high performance in memory database use and configuration tutorial
C reads data from the database and exports it to CSV