Skip to content

Instantly share code, notes, and snippets.

@themobilecoder
Last active March 11, 2020 08:58
Show Gist options
  • Save themobilecoder/819523b3105be5d35e52e33264f57ea8 to your computer and use it in GitHub Desktop.
Save themobilecoder/819523b3105be5d35e52e33264f57ea8 to your computer and use it in GitHub Desktop.
How to make an online radio app in Flutter part 1
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());
},
);
}
},
),
)
],
),
),
);
}
}
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(),
),
);
}
}
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());
},
);
}
},
);
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();
}
}
}
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/
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();
}
}
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