Add video player buffering status (#583)

diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md
index d174052..028d728 100644
--- a/packages/video_player/CHANGELOG.md
+++ b/packages/video_player/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.3
+
+* Added video buffering status.
+
 ## 0.5.2
 
 * Fixed a bug on iOS that could lead to missing initialization.
diff --git a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java
index 5aa904a..1f1f3d2 100644
--- a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java
+++ b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java
@@ -132,6 +132,29 @@
             }
           });
 
+      mediaPlayer.setOnInfoListener(
+          new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mediaPlayer, int what, int extra) {
+              Map<String, Object> event = new HashMap<>();
+              switch (what) {
+                case MediaPlayer.MEDIA_INFO_BUFFERING_START:
+                  {
+                    event.put("event", "bufferingStart");
+                    eventSink.success(event);
+                    return true;
+                  }
+                case MediaPlayer.MEDIA_INFO_BUFFERING_END:
+                  {
+                    event.put("event", "bufferingEnd");
+                    eventSink.success(event);
+                    return true;
+                  }
+              }
+              return false;
+            }
+          });
+
       mediaPlayer.prepareAsync();
 
       Map<String, Object> reply = new HashMap<>();
diff --git a/packages/video_player/example/lib/main.dart b/packages/video_player/example/lib/main.dart
index 3f857ae..25fe0ae 100644
--- a/packages/video_player/example/lib/main.dart
+++ b/packages/video_player/example/lib/main.dart
@@ -81,6 +81,10 @@
         ),
       ),
       new Center(child: imageFadeAnim),
+      new Center(
+          child: controller.value.isBuffering
+              ? const CircularProgressIndicator()
+              : null),
     ];
 
     return new Stack(
diff --git a/packages/video_player/ios/Classes/VideoPlayerPlugin.m b/packages/video_player/ios/Classes/VideoPlayerPlugin.m
index 5274690..b59a8b4 100644
--- a/packages/video_player/ios/Classes/VideoPlayerPlugin.m
+++ b/packages/video_player/ios/Classes/VideoPlayerPlugin.m
@@ -46,6 +46,8 @@
 static void* timeRangeContext = &timeRangeContext;
 static void* statusContext = &statusContext;
 static void* playbackLikelyToKeepUpContext = &playbackLikelyToKeepUpContext;
+static void* playbackBufferEmptyContext = &playbackBufferEmptyContext;
+static void* playbackBufferFullContext = &playbackBufferFullContext;
 
 @implementation FLTVideoPlayer
 - (instancetype)initWithAsset:(NSString*)asset frameUpdater:(FLTFrameUpdater*)frameUpdater {
@@ -73,6 +75,14 @@
          forKeyPath:@"playbackLikelyToKeepUp"
             options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
             context:playbackLikelyToKeepUpContext];
+  [item addObserver:self
+         forKeyPath:@"playbackBufferEmpty"
+            options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
+            context:playbackBufferEmptyContext];
+  [item addObserver:self
+         forKeyPath:@"playbackBufferFull"
+            options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
+            context:playbackBufferFullContext];
 
   _player = [AVPlayer playerWithPlayerItem:item];
   _player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
@@ -161,6 +171,17 @@
   } else if (context == playbackLikelyToKeepUpContext) {
     if ([[_player currentItem] isPlaybackLikelyToKeepUp]) {
       [self updatePlayingState];
+      if (_eventSink != nil) {
+        _eventSink(@{@"event" : @"bufferingEnd"});
+      }
+    }
+  } else if (context == playbackBufferEmptyContext) {
+    if (_eventSink != nil) {
+      _eventSink(@{@"event" : @"bufferingStart"});
+    }
+  } else if (context == playbackBufferFullContext) {
+    if (_eventSink != nil) {
+      _eventSink(@{@"event" : @"bufferingEnd"});
     }
   }
 }
diff --git a/packages/video_player/lib/video_player.dart b/packages/video_player/lib/video_player.dart
index 2b34922..4b04817 100644
--- a/packages/video_player/lib/video_player.dart
+++ b/packages/video_player/lib/video_player.dart
@@ -52,6 +52,9 @@
   /// True if the video is looping.
   final bool isLooping;
 
+  /// True if the video is currently buffering.
+  final bool isBuffering;
+
   /// The current volume of the playback.
   final double volume;
 
@@ -72,6 +75,7 @@
     this.buffered: const <DurationRange>[],
     this.isPlaying: false,
     this.isLooping: false,
+    this.isBuffering: false,
     this.volume: 1.0,
     this.errorDescription,
   });
@@ -92,6 +96,7 @@
     List<DurationRange> buffered,
     bool isPlaying,
     bool isLooping,
+    bool isBuffering,
     double volume,
     String errorDescription,
   }) {
@@ -102,6 +107,7 @@
       buffered: buffered ?? this.buffered,
       isPlaying: isPlaying ?? this.isPlaying,
       isLooping: isLooping ?? this.isLooping,
+      isBuffering: isBuffering ?? this.isBuffering,
       volume: volume ?? this.volume,
       errorDescription: errorDescription ?? this.errorDescription,
     );
@@ -116,6 +122,7 @@
         'buffered: [${buffered.join(', ')}], '
         'isPlaying: $isPlaying, '
         'isLooping: $isLooping, '
+        'isBuffering: $isBuffering'
         'volume: $volume, '
         'errorDescription: $errorDescription)';
   }
@@ -230,6 +237,12 @@
             buffered: values.map<DurationRange>(toDurationRange).toList(),
           );
           break;
+        case 'bufferingStart':
+          value = value.copyWith(isBuffering: true);
+          break;
+        case 'bufferingEnd':
+          value = value.copyWith(isBuffering: false);
+          break;
       }
     }
 
diff --git a/packages/video_player/pubspec.yaml b/packages/video_player/pubspec.yaml
index 5591b45..5e86bee 100644
--- a/packages/video_player/pubspec.yaml
+++ b/packages/video_player/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Flutter plugin for displaying inline video with other Flutter
   widgets on Android and iOS.
 author: Flutter Team <flutter-dev@googlegroups.com>
-version: 0.5.2
+version: 0.5.3
 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player
 
 flutter: