flutter_playout 1.0.33

  • Readme
  • Changelog
  • Example
  • Installing
  • 92

AVPlayer for Flutter #

pub package

Audio & Video player in Flutter. This plugin provides audio/video playback with background audio support and lock screen controls for both iOS & Android. Also provides player events such as onPlay, onPause, onTime etc. See example for more details.

  • Video supports HLS and Progressive Steaming for both iOS & Android with multi-audio support.

  • Audio supports playback from URL only.

Apps Using flutter_playout #

See below for example of apps using flutter_playout.

  1. MTA International (iOS - Android)

iOS Example

screenshot1screenshot4screenshot3

Android Example

screenshot5screenshot6

Getting Started #

Android #

Uses ExoPlayer with PlatformView for Video playback and MediaPlayer for audio playback.

When using this plugin, please make sure you have included a notification icon for your project in drawable resource directory named ic_notification_icon. This plugin will use this icon to show lock screen controls for playback.

iOS #

Uses AVPlayer with PlatformView for video playback and AVPlayer with Flutter MethodChannels for audio playback.

Please make sure you've enabled background audio capability for your project. Please also note that the player might not function properly on a simulator.

Opt-in to the embedded views preview by adding a boolean property to the app's Info.plist file with the key io.flutter.embedded_views_preview and the value YES.

HLS MultiAudio Support #

Please see example app on how to implement multi audio for Android. On iOS multi audio is provided natively by the AVPlayer.

1.0.33 [March 23, 2020] #

1.0.32 [March 23, 2020] #

  • Merged PR (https://github.com/muslimtv/flutter_playout/pull/28)

  • Fixed wrong arguments casting in Android PlayerLayout. It was throwing exception and the change wouldn't happen.

  • Fixed crash on iOS when attempting to change media. It was crashing due to force unwrapping a non existing value (showControls).

1.0.31 [March 23, 2020] #

1.0.30 [February 15, 2020] #

  • Fixed an issue causing audio player to re-initialize on widget rebuild even though param values haven't changed

1.0.29 [February 14, 2020] #

  • Changed [position] from int to double

1.0.28 [February 14, 2020] #

  • Added [position] param for Video set set/update seek bar position

1.0.27 [February 14, 2020] #

  • Added preferredAudioLanguage param to Video to set audio language on player init

1.0.26 [February 11, 2020] #

  • Added support for HLS multi-audio for Android

1.0.25 [February 7, 2020] #

  • Fixed a bug where audio service wasn't being destroyed with player
  • Fixed an issue where onTime was not being called after audio player is disposed once and recreated

1.0.24 [February 7, 2020] #

  • Updated example to include media change callback

1.0.23 [February 7, 2020] #

  • Fixed an issue where media change (url change) was not being registered with Android audio player

1.0.22 [February 7, 2020] #

  • Fixed an issue where audio player on Android native side was not being disposed properly

1.0.21 [February 7, 2020] #

  • Changed video platform view dispose to use method channel

1.0.20 [February 7, 2020] #

  • Fixed an issue throwing exception at video platform view dispose

1.0.19 [January 29, 2020] #

  • Merged pull request #15 - Ability to show/hide player controls

1.0.18 [January 17, 2020] #

  • Moved player initialisation outside of build() method fixing issue where the underlying platform view keeps rebuilding whenever widget updates.

1.0.17 [January 4, 2020] #

  • Fixed an issue where audioServiceBinder was being used before initialisation

1.0.16 [December 10, 2019] #

  • Fixed an issue where onDuration wasn't being called after player re-init

1.0.15 [December 10, 2019] #

  • Fixed AVPlayer (iOS) reset issue on dispose

1.0.14 [December 10, 2019] #

  • Fixed an issue where Audio instance wasn't being cleared on dispose

1.0.13 [December 10, 2019] #

  • Implemented audio player as singleton

1.0.12 [December 10, 2019] #

  • Fixed an issue where dispose on iOS was failing because it was trying to remove observers twice

1.0.11 [October 27, 2019] #

  • fixed a bug in example app causing audio player to stop sending events after onComplete

  • fixed an issue with iOS audio player implementation causing URLs to not play

1.0.10 [October 27, 2019] #

  • fixed an issue causing audio player to crash on malformed URLs

  • added better exception handling for audio player

1.0.9 [October 26, 2019] #

  • Implemented desiredState flag in Video widget to play/pause video playback.

1.0.8 [October 24, 2019] #

  • fixed an issue where audio player was not playing new media on url change

1.0.7 [October 24, 2019] #

  • Added onDuration callback & updated example to reflect the change
  • Implemented onComplete for Android audio player

1.0.6 [October 17, 2019] #

  • Fixed an issue with audio player where onPlay & onPause were not being fired

1.0.5 [October 12, 2019] #

  • Fixed an issue causing iOS plugin to not respond to dispose

1.0.4 [October 12, 2019] #

  • Updated iOS plugin to use Swift 5 compiler

1.0.3 [October 12, 2019] #

  • Implemented video playback for Android
  • Fixed an issue with lock screen controls where subtitle wasn't being displayed correctly

1.0.2 [October 9, 2019] #

  • Implemented video playback for iOS

1.0.1 #

  • Updated documentation to include example implementation for the plugin

1.0.0 #

  • Play audio for both iOS & Android
  • Play audio in background with lock screen controls for both iOS & Android

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_playout/player_state.dart';
import 'package:flutter_playout_example/audio.dart';
import 'package:flutter_playout_example/video.dart';

void main() => runApp(MainApp());

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "AV Playout",
      home: PlayoutExample(),
    );
  }
}

class PlayoutExample extends StatefulWidget {
  @override
  _PlayoutExampleState createState() => _PlayoutExampleState();
}

class _PlayoutExampleState extends State<PlayoutExample> {
  PlayerState _desiredState = PlayerState.PLAYING;
  bool _showPlayerControls = true;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        brightness: Brightness.dark,
        backgroundColor: Colors.grey[900],
        centerTitle: true,
        leading: IconButton(
          icon: Icon(Icons.menu),
          onPressed: () {},
        ),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.favorite),
            onPressed: () async {
              // pause playback
              setState(() {
                _desiredState = PlayerState.PAUSED;
              });
              // wait for user to come back from navigated screen
              await Navigator.push(context, MaterialPageRoute<void>(
                builder: (context) {
                  return Scaffold(
                    appBar: AppBar(),
                    body: Container(
                      child: Center(
                        child: AudioPlayout(
                          desiredState: _desiredState,
                        ),
                      ),
                    ),
                  );
                },
              ));
              // user is back. resume playback
//              setState(() {
//                _desiredState = PlayerState.PLAYING;
//              });
            },
          ),
          /* toggle show player controls */
          IconButton(
            icon: Icon(Icons.adjust),
            onPressed: () async {
              setState(() {
                _showPlayerControls = !_showPlayerControls;
              });
            },
          ),
        ],
        title: Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Icon(
              Icons.local_play,
              color: Colors.white,
            ),
            Container(
              width: 7.0,
            ),
            Text(
              "AV Player",
              style: Theme.of(context)
                  .textTheme
                  .title
                  .copyWith(color: Colors.white),
            )
          ],
        ),
      ),
      body: Container(
        color: Colors.black,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(
              child: Container(
                padding: EdgeInsets.fromLTRB(17.0, 33.0, 17.0, 0.0),
                child: Text(
                  "Video Player",
                  style: Theme.of(context).textTheme.display1.copyWith(
                      color: Colors.pink[500], fontWeight: FontWeight.w600),
                ),
              ),
            ),
            SliverToBoxAdapter(
              child: Container(
                padding: EdgeInsets.fromLTRB(17.0, 0.0, 17.0, 30.0),
                child: Text(
                  "Plays video from a URL with background audio support and lock screen controls.",
                  style: Theme.of(context).textTheme.subhead.copyWith(
                      color: Colors.white70, fontWeight: FontWeight.w400),
                ),
              ),
            ),
            SliverToBoxAdapter(
                child: VideoPlayout(
              desiredState: _desiredState,
              showPlayerControls: _showPlayerControls,
            )),
            SliverToBoxAdapter(
              child: Container(
                padding: EdgeInsets.fromLTRB(17.0, 23.0, 17.0, 0.0),
                child: Text(
                  "Audio Player",
                  style: Theme.of(context).textTheme.display1.copyWith(
                      color: Colors.pink[500], fontWeight: FontWeight.w600),
                ),
              ),
            ),
            SliverToBoxAdapter(
              child: Container(
                padding: EdgeInsets.fromLTRB(17.0, 0.0, 17.0, 30.0),
                child: Text(
                  "Plays audio from a URL with background audio support and lock screen controls.",
                  style: Theme.of(context).textTheme.subhead.copyWith(
                      color: Colors.white70, fontWeight: FontWeight.w400),
                ),
              ),
            ),
            SliverToBoxAdapter(
              child: AudioPlayout(
                desiredState: _desiredState,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_playout: ^1.0.33

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_playout/audio.dart';
import 'package:flutter_playout/multiaudio/HLSManifestLanguage.dart';
import 'package:flutter_playout/multiaudio/ISO_639_2_LanguageCode.dart';
import 'package:flutter_playout/multiaudio/MultiAudioSupport.dart';
import 'package:flutter_playout/player_observer.dart';
import 'package:flutter_playout/player_state.dart';
import 'package:flutter_playout/video.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
84
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
92
Learn more about scoring.

We analyzed this package on Apr 6, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Fix lib/multiaudio/ISO_639_2_LanguageCode.dart. (-0.50 points)

Analysis of lib/multiaudio/ISO_639_2_LanguageCode.dart reported 1 hint:

line 3 col 7: Name types using UpperCamelCase.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test