Building a Flutter Media App

Building an app which plays video and audio files from local as well as from internet in flutter

What is Flutter?

Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.

Flutter enables a smooth and easy cross-platform mobile app development. You don’t need to develop an iOS and Android app separately. All you need is one codebase for both platforms.

Widgets in Flutter

Widgets are high level objects used to describe any part of an application. In flutter, almost everything is a widget.In a sense, widgets are extremely similar to React components.

For example, if we need to create a button, we have a RaisedButton widget which provides functionality of the button.

Every widget is like a function. Flutter uses dart language. Dart is a Functional programming language. That means, we can pass functions as parameters to other functions. So, every widget is a function which has parameters which accept other widgets(functions).

Some widgets have a child parameter. This parameter accepts only one widget.Some other widgets like Column widget has children parameter which accepts more than one widget.

Basic widgets

MaterialApp and Scaffold

These two widgets are necessary for every application. We build our app on top of MaterialApp. This widget uses google’s material design.

Scaffold is a widget in flutter which provides many other widgets or we can say APIs like Drawer, SnackBar, BottomNavigationBar, FloatingActionButton, AppBar etc. Its like a basic template for an app to start.

Text Widget

This widget is used for displaying Text on screen. This is the most common widget used in flutter.

Text("Hello World")

This widget also has style property which takes TextStyle widget. Using TextStyle widget, we can change the color,font,size etc for the text.

Container

Container is simply a box. It mainly has 4 properties. They are height,width,color and child.

Container(
color: Colors.amber,
width: 48.0,
height: 48.0,
child: Text("Hello"),
),

As you can see, we provided color using Colors.amber. Like that we can pass many other colors like Colors.black,Colors.blue etc

Column and Row

This widget has a children property that takes more than one widget. It displays all widgets in a vertical array.

Similarly, Row widget also takes more than one widget and it displays all its widgets in a row.

NOTE: Column widget doesn’t support scrolling. Do, if the widgets occupy more space than screen height, we get an error. To avoid it, we wrap it under ListView Widget.

ListView Widget

We use this widget to provide scrolling capability. IF we have more widgets in our application which uses more space than screen height, we need a scrolling option. It is provided by ListView Widget

Our Main App

I built an app which plays audio and video files from local storage and as well as from internet. I explained each and every step in this article. Also I provided github link of this project at end of article.

Structure

Here, we create four dart files. One is main.dart which gets executed when we run the application. Next is Offline.dart which plays videos from local storage. Next one is Online.dart which plays youtube videos. Final is Songs.dart which plays songs.

main.dart file

This is the file we run while running flutter application.In this file we use both MaterialApp and Scaffold Widget. In Scaffold widget, I used both AppBar and BottomNavigationBar Widgets.

AppBar

An AppBar widgets simply displays an AppBar on top of screen. It mainly has three properties. They are leading,title and actions. We use leading to provide any icon, title is for displaying title

Here I used only title and actions parameters.

In actions parameter, I created an icon using GestureDetector and on clicking that icon, it leads to my github page.

To launch websites from app, we need url_launcher package and import it in the file. Then we can pass required url in launch() function.

Scaffold(
appBar: AppBar(
title: Text("Entertaintment App"),
actions: [
Padding(
padding: EdgeInsets.all(5),
child: GestureDetector(
child: Icon(AntDesign.linkedin_square),
onTap: () {
launch(
"https://www.linkedin.com/in/vishnu-kvs-69aa25151/");
}),
),
),

GestureDetector vs IconButton

The above two widgets are used in creating clickable icons. But IconButton comes with inbuilt padding which is big for AppBar. GestureDetector has no padding. So, using GestureDetector in AppBar is better than IconButton

BottonNavigationBar

This widget is used for Navigating between pages. This widget can be passed to bottomNavigationBar parameter of Scaffold.

First I created a list called tabs which takes all pages.

final tabs = [
Center(
child: Online(),
),
Center(
child: Offline(),
),
Center(
child: Songs(),
),
];

Then we have to pass this to body parameter of scaffold

body: tabs[_currentIndex],

Then in BottomNavigationBar widget, we have parameters like currentIndex, iconSize, items, onTap etc.

items: It takes BottonNavigationBarItem widget in which we can pass icon and title. As we have three pages, we create three items.

iconSize: To specify size of icon

currentIndex: We create a variable called _currentIndex and set it to 0. Then we pass this variable to this currentIndex parameter of BottomNavigationBar.

onTap: To change the currentIndex on tapping the icon, we use setState function.

bottomNavigationBar:
BottomNavigationBar(
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
iconSize: 25,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.video_library),
title: Text("Offline Videos")),
BottomNavigationBarItem(
icon: Icon(Icons.video_label), title: Text("Online Videos")),
BottomNavigationBarItem(
icon: Icon(Icons.audiotrack), title: Text("Songs")),
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),

Online.dart file

In this file, I created a widget called Cardd. In this widget, I used a Card widget. Inside card widget, I used an Image widget, a like widget and a Text widget.

To get a like button , I used like_button package.First I took a column widget and passed an image widget at top. The I passed a Row widget in which , I used like_button and Text widgets.

Also I used InkWell widget. InkWell is usually wrapped for widgets like containers etc. With InkWell widget, we get a onTap property. With this, I used url_launcher and passed youtube links.

Inorder to make this widget reusable or ( Inorder to create any widget), we use variables and a constructor.

class Cardd extends StatelessWidget {
String img;
String link;
String name;
Cardd(this.img, this.link, this.name);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => launch(link),
child: Container(
margin: EdgeInsets.all(10),
//width: double.infinity,
//height: double.infinity,
child: Column(
children: [
Card(
elevation: 10,
margin: EdgeInsets.all(10),
child: Column(
children: [
Image.asset(
img,
fit: BoxFit.cover,
),
SizedBox(height: 10),
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
LikeButton(
likeBuilder: (bool isLiked) {
return Icon(
Icons.favorite,
color:
isLiked ? Colors.deepPurpleAccent : Colors.grey,
//size: buttonSize,
);
},
),
SizedBox(width: 15),
Text(
name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.pink,
),
)
])
],
),
),
],
),
),
);
}
}

After creating a widget, I used it in a column widget and wrapped it in ListView widget for scrolling function.

import 'variables.dart' as vary;class Online extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: [
Column(
children: [
Cardd(vary.image1, vary.link1, vary.name1),
Cardd(vary.image2, vary.link2, vary.name2),
Cardd(vary.image3, vary.link3, vary.name3),
],
),
],
);
}
}

As you can see, I created a separate file for variables called variable.dart

String image1 = "assets/images/dilbechara.jpg";
String link1 = "https://www.youtube.com/watch?v=GODAlxW5Pes&t=3s";
String name1 = "Dil Bechara";
String image2 = "assets/images/rrr.jpg";
String link2 = "https://www.youtube.com/watch?v=lDVQojLPI4Y";
String name2 = "RRR";
String image3 = "assets/images/bahubali2.jpg";
String link3 = "https://www.youtube.com/watch?v=G62HrubdD6o";
String name3 = "Bahubali 2";

Offline.dart file

Normally to play videos from local, we need a video player. To get a video player, we use video_player package. But using this package is very complicated. So, we use another package called chewie which is built upon video_player package.

The main part of below code is where we pass the path of files. Rest other is like a template. To get a detailed explanation Click Here

import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';
class ChewieListItem extends StatefulWidget {
final VideoPlayerController videoPlayerController;
final bool looping;
ChewieListItem({
@required this.videoPlayerController,
this.looping,
Key key,
}) : super(key: key);
@override
_ChewieListItemState createState() => _ChewieListItemState();
}
class _ChewieListItemState extends State<ChewieListItem> {
ChewieController _chewieController;
@override
void initState() {
super.initState();
_chewieController = ChewieController(
videoPlayerController: widget.videoPlayerController,
aspectRatio: 16 / 9,
autoInitialize: true, //First frame of video display
looping: widget.looping, //for looping
//For errors
errorBuilder: (context, errorMessage) {
return Center(
child: Text(
errorMessage,
style: TextStyle(color: Colors.white),
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Chewie(
controller: _chewieController,
),
);
}
@override
void dispose() {
super.dispose();
widget.videoPlayerController.dispose();
_chewieController.dispose();
}
}
class Offline extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: [
ChewieListItem(
videoPlayerController:
VideoPlayerController.asset('assets/videos/samsung.mp4'),
looping: true,
),
SizedBox(width: 10),
ChewieListItem(
videoPlayerController:
VideoPlayerController.asset('assets/videos/ipad.mp4'),
looping: true,
),
SizedBox(width: 10),
ChewieListItem(
videoPlayerController:
VideoPlayerController.asset('assets/videos/xiomi.mp4'),
looping: true,
),
],
);
}
}

Songs.dart file

To use audio files in the application, we need to install audioplayers package.

First we create a AudioPlayer and AudioCache instances. Then we can play local files using audioCache instance. As in below code, I created a SongPlay() function which gets path from variable and plays the song. I created buttons to update the variable.

Songs() {
AudioPlayer _audioPlayer = AudioPlayer();
var audioCache = AudioCache(fixedPlayer: _audioPlayer);
String path = "";
SongPlay() {
audioCache.play(path);
}
return Center(
child: Container(
color: Colors.amber.shade200,
child: Column(
children: [
Container(
child: Image.asset(
"assets/images/musicphoto.png",
fit: BoxFit.cover,
)),
SizedBox(height: 20),
Container(
color: Colors.amber,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RaisedButton(
child: Icon(Icons.play_arrow),
onPressed: SongPlay,
),
SizedBox(width: 10),
RaisedButton(
child: Icon(Icons.pause),
onPressed: () {
_audioPlayer.pause();
}),
SizedBox(width: 10),
RaisedButton(
child: Icon(Icons.stop),
onPressed: () {
_audioPlayer.stop();
}),
],
),
),
SizedBox(height: 40),
Container(
//color: Colors.amberAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RaisedButton(
onPressed: () {
path = "songs/Bekhayali.mp3";
SongPlay();
},
child: Text("Bekhayali")),
RaisedButton(
onPressed: () {
path = "songs/Makhna.mp3";
SongPlay();
},
child: Text("Makhna")),
]),
],
),
),
],
),
),
);
}

This is the complete project.

Github repo : https://github.com/Vishnukvsvk/Entertaintment-App

Thank you very much Vimal Daga Sir. I couldn’t believe I made an app from just 10 days of your training.

Tech Explorer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store