better_native_video_player 0.2.13
better_native_video_player: ^0.2.13 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.13 - 2025-10-30 #
Added #
- Overlay Lock Feature: Added ability to lock custom overlay to always be visible
- New
lockOverlay()method to keep overlay permanently visible - New
unlockOverlay()method to restore normal tap-to-hide behavior - New
isOverlayLockedgetter to check current lock state - New
isOverlayLockedStreamfor reactive lock state updates - When locked, overlay cannot be dismissed by tapping or auto-hide timer
- Useful for live streams, interactive content, or when constant access to controls is needed
- New
Fixed #
- AirPlay Connection State Updates: Fixed issue where AirPlay connection state was not properly updating the controller state
- Now properly updates
_state.isAirplayConnectedwhen receivingairPlayConnectionChangedevents - Ensures
isAirplayConnectedStreamemits correctly when connection state changes - Provides consistent state tracking between event handlers and controller state
- Now properly updates
0.2.12 - 2025-10-30 #
Added #
- Automatic Overlay Management for PiP: Custom overlays now automatically hide when entering PiP and show when exiting PiP on Android
- Prevents overlay from appearing in PiP window
- Seamless user experience when transitioning to/from PiP mode
- Only affects Android platform (iOS handles PiP differently)
Improved #
-
Enhanced Picture-in-Picture Transitions (Android): Major improvements to PiP mode behavior
- Added automatic fullscreen entry before PiP for better visual transitions
- Added
wasFullscreenBeforePiptracking to restore correct state after PiP - Implemented source rect hints for more accurate PiP window positioning
- Added seamless resize support for Android 12+ for smoother PiP transitions
- PiP window now correctly restores to inline or fullscreen mode based on state before PiP entry
- Improved visual consistency when entering and exiting PiP mode
-
Shared Player Surface Reconnection: Enhanced surface handling for shared players
- Added automatic surface reconnection after
releaseResources()is called - Ensures video playback resumes correctly when returning to a video with a shared player
- Prevents black screen issues when navigating back to previously viewed videos
- Added automatic surface reconnection after
-
PiP Availability Detection: Improved activity context handling for PiP feature detection
- Added
getActivity()helper method to properly unwrapContextWrapperinstances - More reliable PiP availability checks across different context types
- Better error handling when activity context is not immediately available
- Added
Fixed #
-
Custom Overlay in PiP Window: Fixed issue where custom overlays would appear in the PiP window on Android
- Overlay is now automatically hidden before entering PiP
- Overlay automatically reappears when exiting PiP
- Provides clean PiP experience with only native system controls
-
Fullscreen State After PiP: Fixed incorrect fullscreen state restoration after exiting PiP
- Now properly tracks fullscreen state before entering PiP
- Restores to inline mode if video was inline before PiP
- Maintains fullscreen mode if video was fullscreen before PiP
- Eliminates unexpected fullscreen state changes after PiP
0.2.11 - 2025-10-28 #
Fixed #
- Progress Bar Seek Jump: Fixed issue where progress bar would jump back briefly after seeking
- Added
_targetSeekPositionto track where we're seeking to - Modified seek handling to ignore old position events during seek operation
- Progress bar now stays at target position until native player confirms seek completion
- Position updates within 200ms of target are considered successful seeks
- Eliminates the 500ms "jump back" behavior when seeking
- Added
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)