better_native_video_player 0.2.10
better_native_video_player: ^0.2.10 copied to clipboard
Native video player using AVPlayerViewController (iOS) and ExoPlayer (Android) with HLS, Picture-in-Picture, AirPlay, and fullscreen support.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.2.10 - 2025-10-28 #
Added #
-
Quality List Stream: Added
qualitiesStreamto track changes in available video qualities- Stream emits
List<NativeVideoPlayerQuality>whenever quality list changes - Useful for updating UI when qualities are loaded or changed
- Follows the same pattern as other property streams
- Example usage in
custom_video_overlay.dartdemonstrates reactive quality selector updates
- Stream emits
-
Automatic Orientation Restoration: Enhanced
FullscreenManagerwith intelligent orientation tracking- Automatically saves current orientation preferences when entering fullscreen
- Restores original orientations when exiting fullscreen (no manual setup required)
- Added
setPreferredOrientations()helper method as optional drop-in replacement forSystemChrome.setPreferredOrientations() - Added
preferredOrientationsparameter toNativeVideoPlayerControllerfor easy orientation configuration - Supports per-controller orientation preferences (e.g., portrait-only apps can specify this when creating the controller)
-
Tap-to-Hide Overlay: Enhanced custom overlay interaction
- Tapping on visible overlay now hides it (in addition to the auto-hide timer)
- Tapping on hidden overlay shows it (existing behavior)
- Interactive elements (buttons, sliders) are unaffected and work normally
- Uses
HitTestBehavior.deferToChildfor proper gesture handling
Fixed #
- Stream Disposal Race Condition: Fixed "Bad state: Cannot add new events after calling close" error
- Added
_isDisposedflag to prevent state updates after disposal - Added
isClosedchecks before adding events to all stream controllers - Improved disposal order: now cancels event subscriptions before closing stream controllers
- Added double-disposal guard to prevent errors from multiple dispose calls
- Affects:
bufferedPositionController,durationController,playerStateController,positionController,speedController,isPipEnabledController,isPipAvailableController,isAirplayAvailableController,isAirplayConnectedController,isFullscreenController,qualityChangedController, andqualitiesController
- Added
Changed #
- Custom Video Overlay: Refactored to use streams instead of control events
- Now uses
bufferedPositionStreamfor reactive buffer position updates - Now uses
qualitiesStreamfor reactive quality list updates - Reduced dependency on control event polling
- Improved code organization and separation of concerns
- Added
dart:asyncimport forStreamSubscriptionsupport
- Now uses
Documentation #
- Updated
NativeVideoPlayerControllerdocumentation withpreferredOrientationsusage examples - Updated
FullscreenManagerdocumentation explaining automatic orientation tracking - Added comprehensive explanation of auto quality feature and buffer health thresholds
0.2.9 - 2025-10-27 #
Added #
-
HDR Control: Added
enableHDRparameter toNativeVideoPlayerController- Defaults to
falseto prevent washed-out/too-white video appearance on HDR content - Set to
trueto enable HDR playback when desired - Applies to both iOS and Android platforms
- ExoPlayer automatically handles tone-mapping to SDR when HDR is disabled
- Defaults to
-
AirPlay Connection State Tracking: Enhanced AirPlay monitoring with connection state
- Added
isAirplayConnectedproperty toNativeVideoPlayerState - Added
isAirplayConnectedgetter toNativeVideoPlayerController - Added
isAirplayConnectedStreamfor real-time connection state updates - New
PlayerControlStateevents:airPlayConnectedandairPlayDisconnected - Allows UI to respond to active AirPlay streaming state
- Added
-
Convenience State Getters: Added direct property access to controller state
speed- Current playback speedisPipEnabled- Current Picture-in-Picture stateisPipAvailable- PiP device availabilityisAirplayAvailable- AirPlay device availabilityisAirplayConnected- Active AirPlay connection state
Fixed #
- Android Picture-in-Picture Media Session: Fixed media info not displaying correctly in PiP mode
- Media session now properly updates when entering PiP mode (manual, automatic, and exit)
- Ensures notification and lock screen controls show correct title, subtitle, and artwork
- Applies to all PiP entry/exit scenarios: manual start/stop and automatic transitions
Changed #
- Enhanced
NativeVideoPlayerStatemodel withisAirplayConnectedproperty - Updated event handling to process AirPlay connection state changes
- Improved Android PiP lifecycle to ensure media session consistency
0.2.8 - 2025-10-27 #
Added #
-
Individual Property Streams: Added dedicated broadcast streams for convenient property monitoring
bufferedPositionStream- Stream of buffered position changesdurationStream- Stream of duration changesplayerStateStream- Stream of player state changes (playing, paused, buffering, etc.)positionStream- Stream of playback position changesspeedStream- Stream of playback speed changesisPipEnabledStream- Stream of Picture-in-Picture state changesisPipAvailableStream- Stream of Picture-in-Picture availability changesisAirplayAvailableStream- Stream of AirPlay availability changesisFullscreenStream- Stream of fullscreen state changesqualityChangedStream- Stream of quality changes- Streams only emit when values actually change (no duplicate emissions)
- All streams are broadcast streams allowing multiple listeners
-
Toggle Picture-in-Picture: Added
togglePictureInPicture()method for easy PiP toggling- Automatically checks current PiP state and enters/exits accordingly
- Returns
boolindicating success/failure of the operation - Follows the same pattern as
toggleFullScreen()for consistency
Changed #
-
Enhanced State Model: Extended
NativeVideoPlayerStatewith new properties- Added
speedproperty to track playback speed - Added
isPipEnabledproperty to track current PiP state - Added
isPipAvailableproperty to track PiP device availability - Added
isAirplayAvailableproperty to track AirPlay device availability - Updated
copyWith(),operator==, andhashCodeto include new properties
- Added
-
Improved Event Handling: Enhanced event processing to update state properties
- Quality changes now update state and emit to quality stream
- Speed changes now update state and emit to speed stream
- PiP state changes (both platform view and MainActivity events) now update state and emit to PiP streams
- PiP availability changes now update state and emit to availability stream
- AirPlay availability changes now update state and emit to AirPlay stream
Documentation #
- Added comprehensive documentation for individual property streams in README
- Added usage examples showing how to use streams vs event listeners
- Updated API Reference section with new streams and toggle method
- Added dedicated Streams subsection in API Reference documenting all 10 available streams
- Updated Picture-in-Picture section with
togglePictureInPicture()usage examples
Note #
- The original event listeners (
addActivityListener,addControlListener) continue to work as before - Users can choose between using dedicated streams or event listeners based on their use case
- Stream controllers are properly disposed in the
dispose()method to prevent memory leaks
0.2.7 - 2025-10-23 #
Improved #
- Enhanced Player Disposal and Cleanup: Improved SharedPlayerManager on both iOS and Android platforms
- Added
stopAllViewsForController()method to properly stop playback and clear player from all views when disposing - Enhanced iOS disposal to pause player and clear current item before removing
- Enhanced Android disposal to stop playback and clear active views
- Improved logging for better debugging of player lifecycle
- Better cleanup of view references when controller is disposed
- Added
Changed #
- Code formatting improvements across the codebase to comply with Dart style guidelines
- Improved readability with better line formatting in
NativeVideoPlayerController
0.2.6 - 2025-10-23 #
Fixed #
-
Critical Controller Disposal Bug: Fixed incomplete resource cleanup in
NativeVideoPlayerController.dispose()method- Added proper cleanup of PiP event subscription (Android global listener)
- Added cleanup of AirPlay listeners (availability and connection handlers)
- Added cleanup of platform view contexts map
- Added cleanup of overlay builder and fullscreen callback references
- Fixed memory leaks by ensuring all event handlers and subscriptions are properly cancelled
-
Android Player Reinitialization Issue: Fixed critical bug where Android players could not be reinitialized after disposal
- Fixed
VideoPlayerMethodHandler.handleDispose()to properly remove player fromSharedPlayerManager - Added
controllerIdparameter toVideoPlayerMethodHandlerconstructor - Now properly releases ExoPlayer, notification handler, and clears PiP settings on disposal
- Android players can now be disposed and recreated just like iOS players
- Fixed
Changed #
- Enhanced
VideoPlayerMethodChannelwith newdispose()method that calls native platform disposal - Updated Flutter controller
dispose()to call native cleanup via method channel - Improved disposal flow to ensure both Flutter and native resources are properly cleaned up
Documentation #
- Updated
dispose()method documentation to reflect proper disposal of both Flutter and native platform resources
0.2.5 - 2025-10-23 #
Improved #
- Android Media Info Management: Refactored VideoPlayerNotificationHandler and VideoPlayerObserver for improved media information management
- Enhanced media session and notification updates to occur consistently when playback starts
- Improved user experience in both normal playback and Picture-in-Picture modes
- Cleaned up code for better readability and maintainability
- Enhanced logging for better debugging capabilities
0.2.4 - 2025-10-23 #
Fixed #
- iOS Automatic Picture-in-Picture for Shared Controllers: Fixed critical issue where automatic PiP would not work correctly when multiple views share the same controller (e.g., list view + detail view scenario)
- Fixed race condition where multiple views observing the same shared player would compete for PiP control
- Added primary view tracking to ensure only the most recently active view can trigger automatic PiP
- Fixed automatic PiP not working for videos started with native controls (non-programmatic playback)
- Improved SharedPlayerManager to properly handle PiP state transfers between views with the same controller ID
- Added
isPrimaryView()andgetPrimaryViewId()methods to prevent observer conflicts
Changed #
- Enhanced observer logic to detect when playback starts via native controls and automatically set the view as primary
- Improved logging for debugging PiP state transitions across multiple views
0.2.3 - 2025-10-21 #
Fixed #
- Fixed Dart formatting issues in
native_video_player_controller.dartandfullscreen_manager.dartto comply with pub.dev static analysis requirements
0.2.2 - 2025-10-21 #
Added #
- WASM compatibility: Package now supports Web Assembly (WASM) runtime
- Implemented conditional imports using
dart:ioonly on native platforms - Added
PlatformUtilsclass for platform detection without directdart:iodependency - Exported
PlatformUtilsfor users who need platform-agnostic code
- Implemented conditional imports using
Changed #
- Replaced direct
Platformchecks withPlatformUtilsin fullscreen manager and controller - Code formatting improvements across all files
0.2.0 - 2025-10-21 #
Added #
-
AirPlay Support (iOS): Complete AirPlay integration for streaming to Apple TV and AirPlay-enabled devices
isAirPlayAvailable()method to check for available AirPlay devicesshowAirPlayPicker()method to display native AirPlay device pickeraddAirPlayAvailabilityListener()to monitor when AirPlay devices become available/unavailableaddAirPlayConnectionListener()to track AirPlay connection state changes- Automatic detection of AirPlay-enabled devices on the network
- Support for streaming video to multiple AirPlay receivers
-
Custom Overlay Controls: Build your own video player UI on top of the native player
- New
overlayBuilderparameter inNativeVideoPlayerwidget - Full access to controller state for custom UI implementations
- Allows building custom controls while maintaining native video decoding performance
- Example implementation in
example/lib/widgets/custom_video_overlay.dartwith:- Play/pause control
- Progress slider with buffered position indicator
- Speed controls (0.25x - 2.0x)
- Quality selector for HLS streams
- Fullscreen toggle
- Volume control
- AirPlay button (iOS)
- Auto-hide functionality
- New
-
Dart-side Fullscreen Management: New
FullscreenManagerclass for Flutter-based fullscreenFullscreenVideoPlayerwidget for fullscreen video playback in a Flutter overlayenterFullscreen()andexitFullscreen()methods- System UI management (hide/show status bar and navigation bar)
- Device orientation locking options
- Fullscreen dialog helper for easy integration
- Works alongside native fullscreen for maximum flexibility
-
Buffered Position Tracking: Real-time buffered position updates
- New
bufferedPositionproperty in controller - Included in
timeUpdatedcontrol events - Enables showing how much video has been preloaded
- Perfect for showing secondary progress indicator in custom overlays
- New
Improved #
- Enhanced controller state management with better activity and control state tracking
- Improved fullscreen state synchronization between native and Dart layers
- Better event listener management with separate activity and control listeners
- Enhanced example app with new
video_with_overlay_screen.dartdemonstrating custom controls - Improved documentation with comprehensive AirPlay and custom overlay usage examples
- Better error handling and state validation throughout the player lifecycle
Documentation #
- Updated README with comprehensive sections on AirPlay and custom overlays
- Added example code for all new features
0.1.4 - 2025-10-20 #
Fixed #
- Fixed Dart SDK constraint to use proper version range (>=3.9.0 <4.0.0) instead of exact version, allowing compatibility with all Dart 3.9.x and 3.x versions
0.1.3 - 2025-10-20 #
Fixed #
- Fixed fullscreen exit handling on iOS when user dismisses by swiping down or tapping Done button
- Fixed iOS playback state preservation when exiting fullscreen (video now resumes playing if it was playing before)
- Fixed Android fullscreen button icon synchronization when fullscreen is toggled from Flutter code
- Fixed fullscreen event parsing to properly distinguish between entering and exiting fullscreen states
- Fixed shared player state synchronization by sending current playback state when new views attach
Improved #
- Standardized event naming by renaming
videoLoadedtoloadedacross all platforms for consistency - Enhanced Android fullscreen button to detect and correct icon desynchronization
- Improved shared player initial state callback mechanism to properly communicate loaded state with duration
- Better fullscreen state event notifications on Android with proper
isFullscreendata - Enhanced iOS fullscreen delegate handling with playback state restoration
0.1.2 - 2025-01-16 #
Fixed #
- Fixed iOS player state tracking by observing
timeControlStatusinstead of relying only on item observers - Fixed shared player initialization to properly handle existing players vs new players
- Fixed Android PiP event channel setup to only initialize on Android platform (prevents iOS errors)
- Fixed playback state synchronization when connecting to shared players
- Fixed unnecessary buffering/loading events for shared players during reattachment
Improved #
- Enhanced iOS player observer to distinguish between play/pause and buffering states
- Improved shared player management with better state tracking and event handling
- Enhanced Android player controls by hiding unnecessary buttons (next, previous, settings)
- Better error handling and logging throughout the player lifecycle
0.1.1 - 2025-10-20 #
Fixed #
- Fixed Android package name to match plugin name (com.huddlecommunity.better_native_video_player)
- Fixed plugin registration in Android
0.1.0 - 2025-10-20 #
Changed #
- Updated Flutter SDK constraint to 3.9.2
- Updated flutter_lints to 6.0.0
0.0.1 - 2025-01-16 #
Added #
- Initial release of native_video_player plugin
- Native video playback using AVPlayerViewController (iOS) and ExoPlayer/Media3 (Android)
- HLS streaming support with adaptive quality selection
- Picture-in-Picture (PiP) mode on both platforms
- Native fullscreen playback
- Now Playing integration (Control Center on iOS, lock screen on Android)
- Background playback with media notifications
- Comprehensive playback controls:
- Play/pause
- Seek to position
- Volume control
- Playback speed adjustment (0.5x to 2.0x)
- Quality selection for HLS streams
- Event streaming for player state changes
- Support for custom media info (title, subtitle, album, artwork)
- Configurable PiP behavior
- Native player controls toggle
- Example app demonstrating all features
- Comprehensive documentation and API reference
Platform Support #
- iOS 12.0+
- Android API 24+ (Android 7.0+)
Dependencies #
- Flutter SDK ^3.9.2
- iOS: AVFoundation framework
- Android: androidx.media3 1.5.0 (ExoPlayer, HLS, Session)