Issue 1:
There is a race condition in the video_player plugin code that prevents videos from displaying on a Widget.

Steps to Reproduce

Download a video on your phone: http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4

Edit the image_picker sample app (https://github.com/flutter/plugins/blob/master/packages/image_picker/example/lib/main.dart#L50) and add the following in line 50 just after if (file != null && mounted) {:

print(file);

Run the image_picker sample app, enable read permissions from external storage and choose the video from the gallery. Keep note of the video path. It will look something like /storage/emulated/0/Download/big_buck_bunny_720p_20mb.mp4 (remove the file:// prefix if needed)

Replace the main.dart content in image_picker by the code below (Based on the video_player sample app found here.

Open and close the app until the video no longer shows. You should see a blank screen.

import 'dart:io';

import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';

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

class VideoApp extends StatefulWidget {
@override
_VideoAppState createState() => _VideoAppState();
}

class _VideoAppState extends State<VideoApp> {
VideoPlayerController _controller;

@override
void initState() {
try {
super.initState();
// _controller = VideoPlayerController.network('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4',)
_controller = VideoPlayerController.file(
new File('/storage/emulated/0/Download/big_buck_bunny_720p_20mb.mp4'))
..addListener(() {
print('controller listener: $_controller');
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
})
..initialize().then((_) {
print('initialized listener: $_controller');
setState(() {});
}).catchError((error) {
print('Unexpected error1: $error');
});
print('controller is set');
} catch (e) {
print('Unexpected error: $e');
}
}

@override
Widget build(BuildContext context) {
try {
print('entering build. Needs _controller $_controller');
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: _controller.value.isPlaying
? _controller.pause
: _controller.play,
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
} catch (e) {
print('Unexpected error: $e');
}
}
}

Buggy app:

Expected:

Logs

When the video works. You'll see in the logs:

I/flutter ( 8147): controller listener: VideoPlayerController#fff7e(VideoPlayerValue(duration: 0:01:57.312000, size: Size(1280.0, 720.0), position: 0:00:00.000000, buffered: [], isPlaying: false, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null,rotationDegrees: 0))
I/flutter ( 8147): initialized listener: VideoPlayerController#fff7e(VideoPlayerValue(duration: 0:01:57.312000, size: Size(1280.0, 720.0), position: 0:00:00.000000, buff

Otherwise you will see something like (the _controller.value is an empty/default video instance). Notice the initialized listener is never called:

I/flutter (10928): controller listener: VideoPlayerController#0235e(VideoPlayerValue(duration: null, size: null, position: 0:00:00.000000, buffered: [], isPlaying: false, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null,rotationDegrees: null))

Root Cause

The initialized event is not always received in the dart code. This event is sent from the ExoPlayer to the Java code, from there to the Dart world through an Event Channel. However it is possible that the init event from the ExoPlayer is fired before the dart code had a chance to listen to any broadcasts from the Java code (eventSink is null in https://github.com/flutter/plugins/blob/master/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java#L213). In such a case, the init event is not fired and the video cannot be played nor displayed.

flutter doctor -v
[✓] Flutter (Channel master, v0.5.8-pre.152, on Mac OS X 10.12.6 16G1510, locale fr-FR)
• Flutter version 0.5.8-pre.152 at /Users/rodrigo/Libs/flutter
• Framework revision 8b05629658 (3 days ago), 2018-07-26 19:12:04 -0700
• Engine revision 6f7bdc9fab
• Dart version 2.0.0-dev.69.3.flutter-937ee2e8ca

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
• Android SDK at /Users/rodrigo/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling support)
• Platform android-27, build-tools 27.0.3
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
• All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 9.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.2, Build version 9C40b
• ios-deploy 1.9.2
• CocoaPods version 1.5.3

[✓] Android Studio (version 3.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 26.0.1
• Dart plugin version 173.4700
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[!] IntelliJ IDEA Community Edition (version 2018.1.1)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
• For information about installing plugins, see
https://flutter.io/intellij-setup/#installing-the-plugins

[!] VS Code (version 1.25.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected devices (1 available)
• SM G920F • 02157df2bc245b2a • android-arm64 • Android 7.0 (API 24)

! Doctor found issues in 2 categories.

Issue 2:
Video player widget is not sometimes displayed in an application that essentially follows the example code for VideoPlayer plugin.

Sequence of events:

VideoPlayerController is created asynchronously.

The widgets builds. But since the controller has not yet finished asynchronous initialization at this point, VideoPlayer widget renders to nothing.

VideoPlayerController finishes initialization, but VideoPlayer wants to hear nothing of it. It keeps showing a blank Container.

Unfortunately, making VideoPlayer stateful and making it rebuild itself once the controller becomes initialized doesn't immediately help.

Sequence of events:

Dart VideoPlayerController is created: https://github.com/flutter/plugins/tree/master/packages/video_player#example

It calls plugin "create" method asynchronously.

VideoPlayerPlugin creates ExoPlayer.

Exoplayer initializes quickly and calls onPlayerStateChanged

VideoPlayerPlugin tries to send initialized event to Dart, but there is nothing listening.

Dart VideoPlayerController starts listening to the events on the channel.

But it's too late. It missed the initialized event. So...

The listener is not invoked and VideoPlayer is never rebuilt with the correct texture.