Play YouTube video | YouTube API integration in Flutter

Last updated Jan 03, 2021

Nowadays 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

 

Youtube api integration flutter

 

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) => {

}) ;

 

Youtube Video Search in flutter application

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 :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

2837 Views