import 'dart:async'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: _SimpleExampleApp())); } class _SimpleExampleApp extends StatefulWidget { const _SimpleExampleApp(); @override _SimpleExampleAppState createState() => _SimpleExampleAppState(); } class _SimpleExampleAppState extends State<_SimpleExampleApp> { late AudioPlayer player = AudioPlayer(); @override void initState() { super.initState(); // Create the audio player. player = AudioPlayer(); // Set the release mode to keep the source after playback has completed. player.setReleaseMode(ReleaseMode.stop); // Start the player as soon as the app is displayed. WidgetsBinding.instance.addPostFrameCallback((_) async { await player.setSource(AssetSource('iphone.mp3')); await player.resume(); }); } @override void dispose() { // Release all sources and dispose the player. player.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Simple Player'), ), body: PlayerWidget(player: player), ); } } // The PlayerWidget is a copy of "/lib/components/player_widget.dart". //#region PlayerWidget class PlayerWidget extends StatefulWidget { final AudioPlayer player; const PlayerWidget({ required this.player, super.key, }); @override StatecreateState() { return _PlayerWidgetState(); } } class _PlayerWidgetState extends State { PlayerState? _playerState; Duration? _duration; Duration? _position; StreamSubscription? _durationSubscription; StreamSubscription? _positionSubscription; StreamSubscription? _playerCompleteSubscription; StreamSubscription? _playerStateChangeSubscription; bool get _isPlaying => _playerState == PlayerState.playing; bool get _isPaused => _playerState == PlayerState.paused; String get _durationText => _duration?.toString().split('.').first ?? ''; String get _positionText => _position?.toString().split('.').first ?? ''; AudioPlayer get player => widget.player; @override void initState() { super.initState(); // Use initial values from player _playerState = player.state; player.getDuration().then( (value) => setState(() { _duration = value; }), ); player.getCurrentPosition().then( (value) => setState(() { _position = value; }), ); _initStreams(); } @override void setState(VoidCallback fn) { // Subscriptions only can be closed asynchronously, // therefore events can occur after widget has been disposed. if (mounted) { super.setState(fn); } } @override void dispose() { _durationSubscription?.cancel(); _positionSubscription?.cancel(); _playerCompleteSubscription?.cancel(); _playerStateChangeSubscription?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final color = Theme.of(context).primaryColor; return Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( key: const Key('play_button'), onPressed: _isPlaying ? null : _play, iconSize: 48.0, icon: const Icon(Icons.play_arrow), color: color, ), IconButton( key: const Key('pause_button'), onPressed: _isPlaying ? _pause : null, iconSize: 48.0, icon: const Icon(Icons.pause), color: color, ), IconButton( key: const Key('stop_button'), onPressed: _isPlaying || _isPaused ? _stop : null, iconSize: 48.0, icon: const Icon(Icons.stop), color: color, ), ], ), Slider( onChanged: (value) { final duration = _duration; if (duration == null) { return; } final position = value * duration.inMilliseconds; player.seek(Duration(milliseconds: position.round())); }, value: (_position != null && _duration != null && _position!.inMilliseconds > 0 && _position!.inMilliseconds < _duration!.inMilliseconds) ? _position!.inMilliseconds / _duration!.inMilliseconds : 0.0, ), Text( _position != null ? '$_positionText / $_durationText' : _duration != null ? _durationText : '', style: const TextStyle(fontSize: 16.0), ), ], ); } void _initStreams() { _durationSubscription = player.onDurationChanged.listen((duration) { setState(() => _duration = duration); }); _positionSubscription = player.onPositionChanged.listen( (p) => setState(() => _position = p), ); _playerCompleteSubscription = player.onPlayerComplete.listen((event) { setState(() { _playerState = PlayerState.stopped; _position = Duration.zero; }); }); _playerStateChangeSubscription = player.onPlayerStateChanged.listen((state) { setState(() { _playerState = state; }); }); } Future _play() async { await player.resume(); setState(() => _playerState = PlayerState.playing); } Future _pause() async { await player.pause(); setState(() => _playerState = PlayerState.paused); } Future _stop() async { await player.stop(); setState(() { _playerState = PlayerState.stopped; _position = Duration.zero; }); } }
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:video_player/video_player.dart'; void main() => runApp(const VideoPlayerApp()); class VideoPlayerApp extends StatelessWidget { const VideoPlayerApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Video Player Demo', home: VideoPlayerScreen(), ); } } class VideoPlayerScreen extends StatefulWidget { const VideoPlayerScreen({super.key}); @override StatecreateState() => _VideoPlayerScreenState(); } class _VideoPlayerScreenState extends State { late VideoPlayerController _controller; late Future _initializeVideoPlayerFuture; @override void initState() { super.initState(); // Create and store the VideoPlayerController. The VideoPlayerController // offers several different constructors to play videos from assets, files, // or the internet. _controller = VideoPlayerController.networkUrl( Uri.parse( 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4', ), ); // Initialize the controller and store the Future for later use. _initializeVideoPlayerFuture = _controller.initialize(); // Use the controller to loop the video. _controller.setLooping(true); } @override void dispose() { // Ensure disposing of the VideoPlayerController to free up resources. _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Butterfly Video'), ), // Use a FutureBuilder to display a loading spinner while waiting for the // VideoPlayerController to finish initializing. body: FutureBuilder( future: _initializeVideoPlayerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { // If the VideoPlayerController has finished initialization, use // the data it provides to limit the aspect ratio of the video. return AspectRatio( aspectRatio: _controller.value.aspectRatio, // Use the VideoPlayer widget to display the video. child: VideoPlayer(_controller), ); } else { // If the VideoPlayerController is still initializing, show a // loading spinner. return const Center( child: CircularProgressIndicator(), ); } }, ), floatingActionButton: FloatingActionButton( onPressed: () { // Wrap the play or pause in a call to `setState`. This ensures the // correct icon is shown. setState(() { // If the video is playing, pause it. if (_controller.value.isPlaying) { _controller.pause(); } else { // If the video is paused, play it. _controller.play(); } }); }, // Display the correct icon depending on the state of the player. child: Icon( _controller.value.isPlaying ? Icons.pause : Icons.play_arrow, ), ), ); } }