Play YouTube video | YouTube API integration in Flutter
Last updated Jan 03, 2021Nowadays Users are more interested in using Media Applications. Media applications will use video players to play the Videos/music/audio files. If we want to play the Youtube videos in the Flutter application, how will youtube videos to play in the side application.
There are many player plugins to play the videos in the Flutter application. In that youtube_api plugin, we are going to use it to play the youtube videos inside our application.
youtube_api : A Flutter plugin for fetching interacting with YouTube Server to fetch data using API. Supports iOS and Android
In this article, we will cover
- Handle Statmanagement with Provider
- Integrate youtube_api plugin
- Fetch Youtube Channel Playlist data
- Search Youtube Videos
- Play Youtube Videos
Let's get started
Step 1: Create a Flutter application
Step 2: Add required plugins inside pubspec.yaml file
dependencies:
flutter:
sdk: flutter
youtube_api: ^0.8.0
youtube_player_flutter: ^7.0.0+7
url_launcher: ^5.7.5
provider:
flutter_offline:
|
youtube_api: Get youtube Data
youtube_player_flutter: Play youtube videos
provider: Using ChangeNotifier Provider to handle the State management.
flutter_offline: Check the Device has an internet connection or not
url_launcher: Open URL in the browser
Handle Statmanagement with Provider
State management is a big thing in the flutter application. In this example, we are using the ChangeNotfierProvider to handle the State data.
Read How to handle state management with ChangeNotifier Provider
Integrate youtube_api plugin
To use youtube_api plugin to fetch youtube data we need to create an application in Google Developers Console and create a Project.
Follow the link to get API key for the project
Copy the API key from credentials inside the google console project.
Now create YoutubeAPI object by passing the API key
YoutubeAPI ytApi = YoutubeAPI(key);
|
Fetch Youtube Channel Playlist data
Get Youtube Channel videos
Future callAPI() {
String query = "Flutter TPoint";
return ytApi.channel("UChcz-3skEk2Akpn3X2q1nQg",order: "date");
}
|
This will return all the Youtube videos for the given Channel.
Search Youtube Videos
To Search Youtube video we need to write quiery with Youtube Data object like
ytApi.search(searchController.text).then((ss) => {
}) ;
|
This will return a list of Youtube videos based on passed search query text.
Play Youtube Videos
We fetched Youtube videos from Channel or Search by text, Now it's time to play the youtube videos.
To play the youtube videos we need to Create a Youtube Player controller and pass video Id
YoutubePlayerController(
initialVideoId: widget.video.id,
flags: YoutubePlayerFlags(
mute: false,
autoPlay: true,
),
)..addListener(_listener);
|
Complete code for the example
This example contains below dart files
- home.dart
- mychannel.dart (logic to get channel videos)
-
VideoPlayerScreen (Play the video)
- search_screen( Search the videos)
- screen_notifier( Handle the Provide Notify changes)
home.dart
import 'package:flutter/material.dart';
import 'package:flutter_offline/flutter_offline.dart';
import 'package:provider/provider.dart';
import 'package:yutube_video/src/screen_notifier.dart';
import 'package:yutube_video/src/search_screen.dart';
import 'mychannel.dart';
/*class HomeTab extends StatefulWidget{
@override
_HomeTabState createState() => _HomeTabState();
}*/
class HomeTab extends StatelessWidget{
int current_index=0;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.redAccent
),
home: Consumer<ScreenNotifier>(builder: (context,screenprovider,child)=>Scaffold(
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.redAccent,
onTap: (index){
screenprovider.setIndex(index);
},
currentIndex: screenprovider.current_index,
unselectedItemColor: Colors.white70,
selectedItemColor: Colors.white,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home),label: "My Channel"),
BottomNavigationBarItem(icon: Icon(Icons.search),label: "Search")
]),
body: Builder(
builder: (BuildContext context) {
return OfflineBuilder(connectivityBuilder:
(BuildContext context, ConnectivityResult connectivity,
Widget child) {
final bool connected =
connectivity != ConnectivityResult.none;
if(connected) screenprovider.setIndex(1);
return Stack(
fit: StackFit.expand,
children: [
child,
Positioned(
left: 0.0,
right: 0.0,
top: 20,
height: 32.0,
child: (connected)?Container():AnimatedContainer(
duration: const Duration(milliseconds: 300),
color:
connected ? Colors.green : Colors.brown,
child: connected
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Online",
style: TextStyle(color: Colors.white),
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Offline",
style: TextStyle(color: Colors.white),
),
SizedBox(
width: 8.0,
),
SizedBox(
width: 12.0,
height: 12.0,
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor:
AlwaysStoppedAnimation(
Colors.white),
),
),
],
),
),
),
],
);;
},child: (screenprovider.current_index==0)?DemoApp():VideoSearch(),);
},
)
)));
}
}
|
mychannel.dart
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:youtube_api/youtube_api.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:yutube_video/src/screen_notifier.dart';
class DemoApp extends StatefulWidget {
@override
_DemoAppState createState() => _DemoAppState();
}
class _DemoAppState extends State<DemoApp> {
static String key = "";
YoutubeAPI ytApi = YoutubeAPI(key);
Future callAPI() {
String query = "Flutter TPoint";
return ytApi.channel("UChcz-3skEk2Akpn3X2q1nQg",order: "date");
}
@override
void initState() {
super.initState();
callAPI();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Youtube API'),
),
body: Consumer<ScreenNotifier>(builder: (context,screenprovider,child){
return (screenprovider.ytResult==null||screenprovider.ytResult.isEmpty)?FutureBuilder(
future: callAPI(),
builder: (context, snapshot) {
screenprovider.videoList(snapshot.data);
if(screenprovider.ytResult!=null)
{
return Container(
child: ListView.builder(
itemCount: screenprovider.ytResult.length,
itemBuilder: (_, int index) => listItem(screenprovider.ytResult[index]),
),
);
}else{
return Container(height:double.infinity,child: Center(child: CircularProgressIndicator(backgroundColor: Colors.green,)));
}
} ,
):Container(
child: ListView.builder(
itemCount: screenprovider.ytResult.length,
itemBuilder: (_, int index) => listItem(screenprovider.ytResult[index]),
),
);
})
);
}
Widget listItem(video) {
return GestureDetector(
onTap: (){
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return VideoPlayerScreen(
video: video,
);
}));
},
child: Card(
child: Container(
margin: EdgeInsets.symmetric(vertical: 7.0),
padding: EdgeInsets.all(12.0),
child: Row(
children: <Widget>[
Image.network(
video.thumbnail['default']['url'],
),
Padding(padding: EdgeInsets.only(right: 20.0)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
video.title,
softWrap: true,
style: TextStyle(fontSize: 18.0),
),
Padding(padding: EdgeInsets.only(bottom: 1.5)),
Text(
video.channelTitle,
softWrap: true,
),
Padding(padding: EdgeInsets.only(bottom: 3.0)),
Text(
video.url,
softWrap: true,
),
]))
],
),
),
),
);
}
}
class VideoPlayerScreen extends StatefulWidget {
//
VideoPlayerScreen({this.video});
final YT_API video ;
@override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
//
YoutubePlayerController _controller;
bool _isPlayerReady;
@override
void initState() {
super.initState();
_isPlayerReady = false;
_controller = YoutubePlayerController(
initialVideoId: widget.video.id,
flags: YoutubePlayerFlags(
mute: false,
autoPlay: true,
),
)..addListener(_listener);
}
void _listener() {
if (_isPlayerReady && mounted && !_controller.value.isFullScreen) {
//
}
}
@override
void deactivate() {
_controller.pause();
super.deactivate();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
String desc=widget.video.description;
String link="";
if(desc.contains("http")) {
link = desc.substring(desc.indexOf("http"));
link=link.split(" ")[0];
if(link.endsWith(".")) {
desc= desc.replaceAll(link, "");
link = link.substring(0,link.lastIndexOf("."));
}
}
return Scaffold(
appBar: AppBar(
title: Text(widget.video.id),
),
body: Container(
child: ListView(
children: [
YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
onReady: () {
_isPlayerReady = true;
},
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(
children: [
TextSpan(
style: TextStyle(color: Colors.black,fontSize: 20),
text: desc
),
TextSpan(
style: TextStyle(color: Colors.red,fontSize: 20),
text: link,
recognizer: TapGestureRecognizer()..onTap = () async{
var url = link;
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
),
]
)),
)
],
),
),
);
}
}
|
search_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:youtube_api/youtube_api.dart';
import '../mychannel.dart';
class VideoSearch extends StatefulWidget{
@override
_VideoSearchState createState() => _VideoSearchState();
}
class _VideoSearchState extends State<VideoSearch> {
List<YT_API> ytResult = [];
TextEditingController searchController=TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: TextField(decoration: InputDecoration(hintText: "Search Videos"),controller: searchController,),
actions: [
IconButton( icon: Icon(Icons.search), onPressed: (){
ytApi.search(searchController.text).then((ss) => {
setState(() {
print("Result ${ss.length} $ss");
ytResult=ss;
})
}) ;
})
]
),
body: FutureBuilder(
future: callAPI(),
builder: (context, snapshot) {
ytResult=(snapshot.data);
if(ytResult!=null)
{
return Container(
child: ListView.builder(
itemCount: ytResult.length,
itemBuilder: (_, int index) => listItem(ytResult[index],context),
),
);
}else{
return Container(height:double.infinity,child: Center(child: CircularProgressIndicator(backgroundColor: Colors.green,)));
}
} ,
),
);
}
Widget listItem(video,context) {
return GestureDetector(
onTap: (){
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return VideoPlayerScreen(
video: video,
);
}));
},
child: Card(
child: Container(
margin: EdgeInsets.symmetric(vertical: 7.0),
padding: EdgeInsets.all(12.0),
child: Row(
children: <Widget>[
Image.network(
video.thumbnail['default']['url'],
),
Padding(padding: EdgeInsets.only(right: 20.0)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
video.title,
softWrap: true,
style: TextStyle(fontSize: 18.0),
),
Padding(padding: EdgeInsets.only(bottom: 1.5)),
Text(
video.channelTitle,
softWrap: true,
),
Padding(padding: EdgeInsets.only(bottom: 3.0)),
Text(
video.url,
softWrap: true,
),
]))
],
),
),
),
);
}
Future callAPI() {
String query = searchController.text;
return ytApi.search(query);
}
}
String key = "";
YoutubeAPI ytApi = YoutubeAPI(key);
|
screen_notifier.dart
import 'package:flutter/cupertino.dart';
import 'package:youtube_api/yt_video.dart';
class ScreenNotifier with ChangeNotifier{
int current_index;
List<YT_API> ytResult = [];
ScreenNotifier({this.current_index});
Set setIndex(index)
{
current_index=index;
notifyListeners();
}
Set videoList(data)
{
ytResult=data;
notifyListeners();
}
}
|
main.dart
void main() {
runApp(
ChangeNotifierProvider<ScreenNotifier>(create: (contex)=>ScreenNotifier(current_index:0),child: HomeTab() ,)
);
}
|
Article Contributed By :
|
|
|
|
3389 Views |