Last active
March 11, 2020 08:58
-
-
Save themobilecoder/819523b3105be5d35e52e33264f57ea8 to your computer and use it in GitHub Desktop.
How to make an online radio app in Flutter part 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HomeScreen extends StatelessWidget { | |
final _planetRockUrl = 'https://stream-mz.planetradio.co.uk/planetrock.mp3'; | |
final _planetRockImage = 'assets/images/planet_rock.png'; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('Online Radio'), | |
), | |
body: Padding( | |
padding: const EdgeInsets.only(bottom: 100), | |
child: Container( | |
child: Center( | |
child: BlocBuilder<PlayerBloc, PlayerState>(builder: (context, state) { | |
if (state is PausedState) { | |
return IdleDots(color: Theme.of(context).accentColor); | |
} else if (state is PlayingState) { | |
return Loading( | |
indicator: LineScalePulseOutIndicator(), | |
size: 100, | |
color: Theme.of(context).accentColor, | |
); | |
} else { | |
throw Exception('Unknown state of bloc'); | |
} | |
}), | |
), | |
), | |
), | |
bottomSheet: Container( | |
color: Theme.of(context).primaryColor, | |
height: 100, | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: <Widget>[ | |
Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: Container( | |
height: 50, | |
width: 50, | |
child: Image.asset(_planetRockImage), | |
), | |
), | |
Text( | |
'Planet Rock', | |
style: TextStyle(fontWeight: FontWeight.bold), | |
), | |
Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: BlocBuilder<PlayerBloc, PlayerState>( | |
bloc: BlocProvider.of<PlayerBloc>(context), | |
builder: (context, state) { | |
if (state is PausedState) { | |
return IconButton( | |
icon: Icon( | |
Icons.play_arrow, | |
size: 32, | |
), | |
onPressed: () { | |
context.bloc<PlayerBloc>().add(PlayEvent(url: _planetRockUrl)); | |
}, | |
); | |
} else { | |
return IconButton( | |
icon: Icon( | |
Icons.pause, | |
size: 32, | |
), | |
onPressed: () { | |
context.bloc<PlayerBloc>().add(PauseEvent()); | |
}, | |
); | |
} | |
}, | |
), | |
) | |
], | |
), | |
), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RadioApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
final RadioPlayer radioPlayer = JustAudioPlayer(); | |
return MaterialApp( | |
title: 'Online Radio', | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData.dark(), | |
home: BlocProvider<PlayerBloc>( | |
create: (context) => PlayerBloc(radioPlayer: radioPlayer), | |
child: HomeScreen(), | |
), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PlayerBloc extends Bloc<PlayerEvent, PlayerState> { | |
final RadioPlayer radioPlayer; | |
PlayerBloc({@required this.radioPlayer}) : assert(radioPlayer != null); | |
@override | |
PlayerState get initialState => PausedState(); | |
@override | |
Stream<PlayerState> mapEventToState( | |
PlayerEvent event, | |
) async* { | |
if (event is PlayEvent && state is! PlayingState) { | |
radioPlayer.play(url: event.url); | |
yield PlayingState(); | |
} else if (event is PauseEvent) { | |
radioPlayer.pause(); | |
yield PausedState(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependencies: | |
flutter: | |
sdk: flutter | |
bloc: ^3.0.0 | |
flutter_bloc: ^3.2.0 | |
just_audio: ^0.1.3 | |
loading: ^1.0.2 | |
flutter: | |
uses-material-design: true | |
assets: | |
- assets/images/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class RadioPlayer { | |
Future<void> play({@required String url}); | |
Future<void> pause(); | |
} | |
class JustAudioPlayer extends RadioPlayer { | |
final audioPlayer = AudioPlayer(); | |
var _isUrlSet = false; | |
@override | |
Future<void> pause() { | |
return audioPlayer.pause(); | |
} | |
@override | |
Future<void> play({@required String url}) async { | |
if (!_isUrlSet) { | |
await audioPlayer.setUrl(url); | |
_isUrlSet = true; | |
} | |
return audioPlayer.play(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BlocBuilder<PlayerBloc, PlayerState>( | |
builder: (context, state) { | |
if (state is PausedState) { | |
return IdleDots(color: Theme.of(context).accentColor); | |
} else if (state is PlayingState) { | |
return Loading( | |
indicator: LineScalePulseOutIndicator(), | |
size: 100, | |
color: Theme.of(context).accentColor, | |
); | |
} else { | |
throw Exception('Unknown state of bloc'); | |
} | |
}, | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment