mohe_native_player 1.11.20
mohe_native_player: ^1.11.20 copied to clipboard
A Flutter native video player plugin for iOS and Android with full-featured controls, HLS/DASH support, danmaku, DLNA casting, PiP, and more.
1.11.20 #
- feat(ios): new
setStartTime(seconds)— hand the resume position to the player beforeplay()and it seeks there while still paused, only starting playback once the seek lands. Previously hosts could only seek after playback began, so resuming a half-watched video flashed the opening frame for ~230ms before jumping away. Measured on-device: that flash is now ~1ms. Call it before everyplay()(pass0when there is no resume position); iOS only — it is a no-op elsewhere, so callers need no platform checks. - fix(ios): a pre-roll ad no longer swallows the resume position. Ads and the feature share one
playVideoWithURL/readyToPlaypath, so the ad's ready consumed the pending start time (and seeked into the ad); by the time the feature started, the position was gone. - fix(ios): keep the resume position when an unsupported codec falls back to VLC. The failure branch cleared it before deciding whether to fall back, and
startVLCPlayerWithURLhad no other source for it, so those videos restarted from zero. - fix(ios): pausing while a video is still loading no longer loses the resume position — the seek now happens even in the paused state, it just doesn't start playback.
1.11.19 #
- fix(ios): dragging the progress bar on encrypted video no longer stalls with the thumb snapping back. Encrypted playback decrypts and remuxes into a local HLS playlist in playback order, so seeking past the decrypted frontier is parked as a pending seek — previously with no feedback at all. Two things were wrong: a target beyond the clip's real end (hosts rounding up, e.g. 82.0s on an 81.99s clip) hung forever because
seekableTimeRangescan never cover it, and the wait itself was silent. Out-of-range targets are now clamped, and the wait shows the native loading indicator while holding the thumb in place until the pending seek lands. - feat(ios):
timeupdatenow carriesseekableEnd— the furthest position already decrypted and immediately seekable, in seconds (0= unrestricted). Hosts that draw their own progress bar can use it to shade the decrypted range or to gate dragging.
1.11.18 #
- fix(ios): stop the player container from growing past the size Flutter gives it. A zero-size layout fallback inherited from the uni-app port wrote a fixed height onto the native view; Flutter feeds platform-view sizes to the embedded view as autoresizing deltas, so that value stuck around and an 857pt slot ended up 1067pt tall — pushing
contain-fitted (landscape) videos about 105pt down the screen.
1.11.17 #
- fix(ios): live streams no longer pause the moment they enter fullscreen, and resume correctly on the way back. The transition's "was it playing" check only looked at AVPlayer, but live playback runs on VLC, so it always recorded "not playing" and skipped the resume.
- fix(android): keep the back button visible in fullscreen even when the control bar is switched off. Live pages hide the native control bar and draw their own chrome, which fullscreen covers — leaving no way out. Hosts that don't want it can still call
setLandscapeBackButtonVisible(false).
1.11.16 #
- fix(android): restore the orientation and remove the fullscreen container when the player is destroyed while still in fullscreen. That black full-bleed container is added to the DecorView and Flutter does not take it away, so popping the player page from fullscreen left a black screen stuck in landscape.
- fix(android): never leave the player view without a parent when exiting fullscreen. A parentless view is never drawn, so its
SurfaceTextureis never rebuilt and playback strands as "sound but no picture". - fix(android): respect the system "auto-rotate" setting before rotating into fullscreen on gravity.
OrientationEventListenerreads the raw sensor and keeps firing after the user locks rotation, so the player rotated anyway. Only gravity-triggered rotation is affected; the fullscreen button still works. - chore(android): log the video-surface lifecycle, so "black screen with sound" reports can be diagnosed from a log instead of guesswork.
1.11.15 #
- fix(android): hide the loading indicator when playback fails, so it cannot swallow taps. A regression from 1.11.14: a failed Huolong transcode never produces a first frame, leaving the spinner on top of the player and blocking the play button.
- fix(android): pick the video decoder from the stream instead of assuming VVC, which fixes Huolong episodes that would not open at all. These sources are not uniformly VVC — within one series, episode 1 is VVC and episode 2 onwards is HEVC. iOS was unaffected because it has always let FFmpeg choose.
- fix(android): decode Huolong video through FFmpeg instead of the bundled vvdec. The FFmpeg bug that motivated vvdec is fixed in the version this repository already ships, and one decode path is what makes decoder selection by codec id possible.
1.11.14 #
- fix(android): keep the loading indicator up for the whole startup, removing the black gap between "parsing finished" and the first frame. It used to require the host to supply a GIF, and it was hidden on
PLAYING— which ExoPlayer reaches before the first frame reaches the surface. Hiding is now driven byonRenderedFirstFrame. - fix(android): close several paths that could leave the indicator spinning forever, reachable once the gate above was removed — playback stopped or paused mid-load, ad mode, and
playHuolong, which previously showed no indicator at all. - style(android/ios): match the native loading spinner to the host's parsing spinner. The two waits are a relay, so a difference in stroke width or diameter showed up as a visible jump at the handover. Both platforms now draw their own 20pt / 1pt white ring.
1.11.13 #
- fix(ios): apply the asset-stage fallback on the resource-loader flow as well. 1.11.12 only widened the standard flow, leaving the branch that live URLs without an
.m3u8extension actually take. - fix(ios): do not re-arm the load-failure detector during ad playback, which could surface a spurious load timeout to the host mid-ad.
1.11.12 #
Some TV live sources emit #EXTINF:3E+00, — a duration in scientific notation, which RFC 8216 §4.3.2.1 does not allow. Each platform failed differently, so the fixes differ.
- fix(android): accept playlists whose
EXTINFduration is written in scientific notation. media3's parser regex cannot match such a value, so it rejected the whole playlist and those channels would not play. The playlist is normalised before parsing, with magnitude limits so a hostile value cannot exhaust memory. - fix(ios): stop the 8-second black screen when AVPlayer cannot play such a stream. AVPlayer reports it as
-1002 unsupported URLunder a domain the format-error check did not recognise, so it was treated as a transport problem and never fell back to VLC. - fix(ios): keep the spinner up across a VLC fallback, instead of leaving the screen black until VLC renders its first frame.
- fix(ios): fall back to VLC when the same failure surfaces while loading the asset's keys rather than on the player item — a path where no watchdog was armed, so the black screen lasted even longer.
- fix(ios): preserve the custom
User-Agentwhen the resource-loader path falls back to VLC; hotlink-protected sources returned 403 without it. - fix(ios): report a failed load once instead of twice, and do not judge VLC against a timeout budget AVPlayer had already spent.
Note: Android is fixed at the source and keeps decoding in hardware, whereas iOS relies on the VLC fallback and therefore decodes these channels in software. Normalising the playlist on iOS too would require routing every HLS stream through the local proxy — a much larger change, not done here.
1.11.11 #
- fix(ios): implement
setNativeUIVisible:. The bridge header declared it but the implementation was missing, so everyPlayerViewWithControlsmount raisedunrecognized selector— that widget had never been usable on iOS. - fix(android): add the missing
setNativeUIVisiblecase, which raisedMissingPluginException. - fix(dart): attach
catchErrorto the fire-and-forgetsetNativeUIVisiblecalls, which otherwise surfaced as uncaught async exceptions in the host's zone. - fix(android): accept the
setCoverImageRPC instead of raisingMissingPluginException. Android has no media notification, so the URL is only recorded and nothing renders it — the dartdoc now says so per platform. - fix(ios): drop two unreachable duplicate branches from
handleMethodCall:; behaviour is unchanged.
1.11.10 #
- fix(ios): stop the progress bar from snapping back to its old position after a drag, caused by the periodic refresh overwriting the slider while a seek was still in flight.
- fix(ios): register
UIControlEventTouchCancelon both progress sliders. An incoming call or a stolen touch delivers only that event, and without a handler the progress bar stopped updating for the rest of the session. - fix(ios): rework realtime scrubbing (seek-feedback mode 2) around Apple's QA1820 chase-time pattern. The previous throttle made high-frequency seeks cancel each other, so almost no frame was presented on slow HLS.
- fix(ios): widen the first-frame timeout from 1s to 8s and distinguish "cannot render" from "merely slow". 1s only covered local files and fast CDNs, so streams AVPlayer could have decoded in hardware were pushed onto VLC software decoding.
- fix(ios): only fall back to VLC on a documented media-format error. Falling back unconditionally swept transport failures — dropped connections, expired signatures, 404s — into the "codec unsupported" path, where VLC fails on the same URL and merely defers the error behind a silent black screen.
- fix(ios): seek VLC by time instead of position. libvlc derives position from a byte offset, which is badly distorted on VBR or multi-segment sources — one title landed 785s away from the target.
1.11.9 #
- fix(ios): recover encrypted playback from mid-playback time-base freezes the watchdog previously ignored. Buffering stalls now get a grace period instead of a free pass, after which the pipeline is rebuilt. Verified on device: previously 5 black screens in 3.6h, now none across multi-hour runs.
- fix(ios): eliminate a
setRatefeedback loop during 2x playback, measured at 2–28setRatecalls per second and hundreds of redundant buffering events per stall. Only non-1.0 rates were affected. - fix(ios): keep the freeze watchdog responsive by moving its diagnostic snapshot off the watchdog queue; a blocked tick previously disabled freeze detection entirely.
- fix(ios): reuse the decryption key when the same encrypted source is re-loaded, instead of falling through to the plain playback path and reporting a black screen.
- feat(ios/android): add a
liveplayer mode and an independentsetLandscapeBackButtonVisibleAPI. Live mode hides the native chrome but keeps the fullscreen back button, re-applying it after fullscreen transitions.
1.11.8 #
- fix(ios): recover encrypted AVPlayer playback from persistent non-buffering freezes by rebuilding the player item and resuming at the previous position, with bounded retries and per-instance diagnostics to prevent recovery loops.
1.11.7 #
- fix(ios): rebuild the AVPlayer render pipeline after Flutter platform views transition from 0x0 to a valid size, preventing startup/initial-seek playback from freezing on the first frame when the layer was created without a renderable canvas.
- fix(ios): reduce false load-failure prompts near natural video end by suppressing end-of-video buffer-empty handling and resetting the load-failure detector when playback finishes.
- fix(ios): add encrypted/Huolong playback freeze diagnostics with a wall-clock watchdog, periodic alive logs, and switch-path diagnostics while keeping the watchdog observation-only to avoid unintended playback recovery side effects.
- perf(ios): throttle Now Playing heartbeat reloads when playback is paused or ended, so the lock-screen card commits the stop state once instead of reloading unchanged metadata every second.
1.11.6 #
- fix(ios): align the long-press speed default in the speed-settings page with the long-press overlay, so a fresh install no longer shows "2.0X" in the overlay but "3.0X" in settings — both now resolve from the same persisted default.
- fix(android): harden crash/ANR paths — R8 keep rule so transcode cancellation stays effective, JNI OOM and null-context guards, short-circuit async callbacks after dispose, API-level guard on PiP calls, fix a Surface leak on texture re-attach, and make fullscreen reparent crash-safe.
- fix(ios): harden crash paths — remove KVO before tearing down the player item, make sample-buffer enqueues recoverable on failed layers, and fix partial-write truncation of large segments in the local HLS server.
1.11.5 #
- feat(android/ios): add customizable long-press speed boost settings with persisted preferences, a redesigned speed feedback overlay, high-speed playback handling, and animated directional chevrons for swipe feedback.
- fix(android/ios): harden crash-prone playback entry points, ad playback parameters, HLS proxy URL/response handling, SIGPIPE handling, and resource-loader retry state under invalid input or concurrent requests.
- fix(android/ios): improve Huolong, encrypted playback, DLNA, local HTTP, and native decode shutdown stability by guarding memory allocation, mid-stream resolution changes, socket lifecycle races, native-context use-after-free windows, and AudioTrack release races.
- perf(ios): reduce peak memory during continuous short-drama swiping by capping AVPlayer forward buffering, lowering concurrent FFmpeg decrypt instances, and limiting Huolong decoder thread usage.
1.11.4 #
- feat(android/ios/dart): detect load timeout (no first frame in time) and mid-playback stall, stop the infinite spinner, and report through the existing
errorevent with areasonfield (load_timeout/stall_timeout) so hosts can show a retry prompt. NewsetLoadFailureDetection(firstFrameTimeoutSec, stallTimeoutSec); defaults 15s / 15s, 0 disables. Covers every engine on both platforms; skipped in ad mode and while backgrounded. Network-reachability detection is intentionally left to the host.
1.11.3 #
- fix(ios): start Huolong playback intent before transcoding and add a
readyForDisplayfallback so episode switches no longer stall on the first frame when EVENT HLS playlists do not reachreadyToPlay. - fix(ios): trim old Huolong local HLS cache directories with a session LRU policy, preventing repeated episode switches from growing tmp storage until segment writes fail.
1.11.2 #
- fix(ios): guard the Huolong VVC pipeline (
MoheVVCPlayer/HuolongHLSTranscoder) behind#if !TARGET_OS_SIMULATORso iOS Simulator builds no longer fail linking the device-onlyff8_*FFmpeg 8 symbols; the simulator falls back to a stub that reports VVC as unsupported, while real-device playback is unchanged.
1.11.1 #
- feat(huolong): add Huolong VVC/H.266 playback support, including the Dart
playHuolongentry and routing forplatform == 'huolong'. - feat(android): add VVC-to-HEVC transcoding with bundled FFmpeg 8/vvdec, fMP4 HLS edge playback, audio handling, cancellation, and end-list integrity gating.
- feat(ios): add the Huolong VVC pipeline with segmented Apple HLS output and playback through the existing native player UI.
- fix(huolong): harden transcoding/download failure handling, timestamp rescaling, decoder threading, temporary output finalization, and CDN/error diagnostics.
- chore(android): ship Huolong VVC JNI as a prebuilt arm64 library and exclude build-only FFmpeg8/vvdec static inputs from the pub package.
1.10.45 #
- fix(ios): forward
customHttpHeaders['User-Agent']to the VLC fallback engine so CDN-sensitive HLS segments keep the caller-provided user agent after AVPlayer fallback.
1.10.44 #
- fix(ios): exit active PiP when the app is reopened from the home screen or app switcher, while preserving PiP for transient inactive states and protected-data lock-screen recovery.
1.10.43 #
- chore: version bump.
1.10.42 #
- feat(android): wrap quality selector content in a
ScrollViewso panels with many custom quality options scroll rather than overflow.
1.10.41 #
- refactor(android): extract
getIntOrNullhelper inQualitySelectorViewfor robust null/type-safe value parsing; fixgetFlutterOptionNameto handle non-Stringnamefields viaString.valueOf.
1.10.40 #
- fix(android): disable swipe-up-to-next-episode gesture when ad mode is active, preventing vertical brightness/volume gestures from being incorrectly blocked during ads.
- fix(ios): disable swipe-up-to-next-episode gesture when ad mode is active; gate all writes to
shortDramaLandscapeNextEpisodeEnabledwith!isAdModeEnabled. - fix(android): remove unused
getOptBooldead code fromQualitySelectorView. - fix(ios): correct stale comment "满 3 个" → "满 2 个" in
QualitySelectorViewlayout loop. - fix(dart): add
@Deprecatedannotation tosetVideoCurrentQuality()so call sites get compile-time warnings. - fix(android): call
ensureUIManager()at the start ofsetPlaybackQuality()so the landscape quality button is updated immediately even when called before the UI is initialized. - fix(ios): replay quality button display after
qualityButtonis wired inviewDidLoad, covering both custom-JSON and built-in quality paths. - fix(android): pass explicit
isCustomQualityValue=falsewhen resetting quality onsetOptions([]), and callrefreshCustomPlaybackQualityDisplay()on all active players after a non-emptysetOptionscall. - fix(ios): forward
isCustomQualityValueargument through the native dispatch layer; postPlayerQualityOptionsDidUpdatenotification after a non-emptysetOptionscall to trigger landscape button refresh on all active players.
1.10.39 #
- feat(android/ios): add
setPlaybackQuality(int quality)as the canonical API for switching playback resolution;setVideoCurrentQualityis now deprecated and delegates to it.
1.10.38 #
- feat(android): add swipe-up-to-next-episode gesture in short-drama landscape fullscreen mode via
shortDramaLandscapeNextEpisodeEnabled. - feat(ios): add swipe-up-to-next-episode gesture in short-drama landscape fullscreen mode, disabled automatically in ad mode.
- feat(android/ios): support
vipflag andvaluefield in quality selector options for custom quality item rendering.
1.10.37 #
- fix(ios): preserve the playback rate while paused so a speed change made during a pause is no longer discarded, keeping the selected speed in effect after switching episodes or resuming.
1.10.36 #
- fix(ios): recover the local HLS server when an established connection is dropped after screen-off (NSURLErrorNetworkConnectionLost / -1005) — the transport-phase counterpart of the -1004 listen-socket reclaim case, per Apple TN2277.
- fix(ios): walk the NSUnderlyingErrorKey chain when classifying server failures, so an NSURLError wrapped inside an AVFoundation/CoreMedia error is no longer missed.
- fix(ios): reset the server self-heal retry quota on a time window instead of on every ReadyToPlay, so a readable playlist whose later segments keep failing can no longer defeat the 2-retry cap and loop forever without reporting the failure.
1.10.35 #
- fix(ios): recover the local HLS server when its listening socket is reclaimed after screen-off (NSURLErrorCannotConnectToHost / -1004), preventing a permanent black screen on reconnect.
- fix(ios): reset the server self-heal retry quota whenever a player item becomes ready, so the "give up after 2 consecutive failures" limit is not mistaken for a per-instance lifetime cap.
- fix(ios): restore fullscreen pan gestures for short drama.
1.10.34 #
- feat: support custom HTTP headers for long video playback.
- feat(ios): forward custom HTTP headers to AVURLAsset resource requests.
1.10.33 #
- feat(android): support custom progress slider thumb images via
setProgressSliderThumbImage, including raw base64 and data URL payloads. - fix(android): restore the default progress slider thumb when the custom image payload is empty or invalid.
1.10.32 #
- fix(ios): report encrypted HLS remux failures to Flutter instead of leaving playback stuck on a black buffering screen.
- fix(ios): isolate concurrent encrypted HLS remux cache directories to avoid cache cleanup races under the same cache key.
- fix(ios): improve encrypted HLS loading feedback on slow networks, including a system loading indicator fallback when no GIF is provided.
1.10.31 #
- fix(ios): start PiP explicitly after the app enters background and keep transient inactive states from triggering PiP prematurely.
1.10.30 #
- fix(ios): prevent HLS preload cleanup from deleting the active main playback cache directory, fixing short-drama black screens after lock-screen recovery.
- chore: expand
.pubignoreexclusions to keep local release scripts and test credentials out of the pub.dev package.
1.10.29 #
- fix(ios): prevent HLS preload cleanup from deleting the active main playback cache directory, fixing short-drama black screens after lock-screen recovery.
- chore: expand
.pubignoreexclusions to keep local release scripts and test credentials out of the pub.dev package.
1.10.28 #
- chore: log the mohe_native_player plugin version on startup (iOS and Android).
1.10.27 #
- fix(ios): cover short-drama lock-screen black-card and blank NowPlaying edge cases.
- fix(ios): harden LocalHLSServer path validation and DecryptFileAVPlayer failure recovery.
- fix(ios): verify m3u8 existence before server-failure recovery to close a shutdown race.
- chore(ios): mute noisy internal
AVPlayer.ratereset logs.
1.10.26 #
- feat(ios): add
setCoverImageRPC for NowPlaying artwork. - fix(ios): force a non-mixable playback audio session so the NowPlaying card appears during PiP.
1.10.25 #
- fix(ios): activate the playback audio session before local playback and FFmpeg audio queue setup.
1.10.24 #
- fix(android): allow episode, playback speed, and quality panels to scroll in short-drama fullscreen mode.
1.10.23 #
- fix(ios): sync the landscape speed label when Flutter updates playback rate.
- fix(ios): refresh the landscape play/pause button after FFmpeg short-drama playback starts, including auto next episode.
1.10.22 #
- fix(ios): remove SpringBoard
lockcompleteprivate API usage to pass App Store review. - fix(ios): restore the portrait control bar when
setControlBarHidden(false)is called from fullscreen.
1.10.21 #
- fix(ios): prevent short-drama playback from auto-entering PiP after PiP is disabled and the app goes to background.
1.10.20 #
- fix(ios): preserve Flutter-hidden native control bar state when entering landscape fullscreen, preventing duplicate progress bars when Flutter renders its own controls.
1.10.19 #
- fix(ios): hide the portrait back button during fullscreen so it no longer duplicates the landscape control-bar back button.
- fix(ios): refresh
mediaInfowhenpresentationSizearrives afterreadyToPlay, and reset stale media metadata during engine/video switches. - fix(android): show cellular generation text next to the landscape status-bar cellular icon.
1.10.18 #
- fix(ios): restore the
mediaInfoevent after sync overwrite. - fix(ios): reset
mediaInfoon VLC fallback and guardvlcAdapterReadyToPlayhandling. - sync(ios): update bundled iLookPlayerCore to ilook-ios-player v1.0.497.
1.10.17 #
- fix(android): remove the duplicated
ShortDramaImmersiveCoordinator.forceRestore(Activity)method somohe_native_playercompiles on Android.
1.10.16 #
- fix(android):
restoreSystemUInow callsShortDramaImmersiveCoordinator.forceRestore()to unconditionally reset immersive state and restore system bars, preventing permanent status-bar hide when refCount is imbalanced. - fix(ios): default
isPiPEnabledtoYES, aligning with native player defaults. - fix(ios): detect
AVPlayerItemStatusFailedinrecoverFromBackgroundIfNeededand escalate torecoverAfterLongBackground(replaceCurrentItem) so a background-failed item no longer blocks recovery. - feat(ios): add
isLayerReadyForDisplayproperty toFFmpegDecryptPlayer/DecryptFileAVPlayerfor callers to detect AVPlayer render channel health after background.
1.10.13 #
- fix(ios): add instance guards to all VLC/FFmpeg delegate callbacks — prevents stale engine instances from firing error events, corrupting seek/loading UI state, or leaking CMSampleBuffers on engine switch.
1.10.12 #
- feat(ios): add
mediaInfoevent (fires once when both duration and video size are available), aligning with Android behavior. All three engines (FFmpeg / AVPlayer / VLC) supported. - feat(ios): PiP handoff session — preserves background playback state across episode switches during PiP, fixing black-screen freeze on
didStopPictureInPicture. - feat(ios):
recoverAfterLongBackgroundusesreplaceCurrentItemWithPlayerItemto rebuild the RemoteXPC render channel after long background/PiP. - fix(ios): memory-warning handler now only evicts paused instances, preserving playing and stalling instances.
- fix(ios): stall recovery re-applies user playback rate via
playbackLikelyToKeepUpKVO. - fix(ios):
lockcompleteduplicate-fire guard; volume KVO dedup for multi-instance short-drama. - feat(ios/android):
PlayerController.restoreSystemUI()— restore system bars after exiting short-drama immersive mode (Android functional; iOS no-op). - fix(dart): commands issued before the platform channel is ready are now queued and flushed automatically, eliminating initialization race conditions.
1.10.11 #
- fix(android): fix PiP aspect ratio flash and incorrect view restore on Samsung One UI.
setPictureInPictureParams()now only fires for the active PiP player; layout restore always usesMATCH_PARENTso the view fills the container regardless of when reparenting occurred.
1.10.10 #
- fix(android): drama videos rendered shrunk inside landscape PiP on certain OEM ROMs (Flutter HC
PlatformViewWrapperrebounding inline-mode layout params beforeTextureViewcould push the correct frame). Proactively re-assertMATCH_PARENTlayout params across multiple frames after reparenting, and force PiP-modeonMeasureto honor the parent container size regardless of explicit-pixel layout params. - feat(android): add
PlayerController.restoreSystemUI()API. Exiting short-drama immersive no longer auto-restores system bars — the host app should now callrestoreSystemUI()explicitly after popping the short-drama route. View destroy still emergency-restores when this view is the last immersive holder. - feat(ios): lock-screen / control-center "Now Playing" card via
MPNowPlayingInfoCenter+MPRemoteCommandCenter. New RPCssetNowPlayingEnabled/setCoverImage; default enabled. iOS-only feature.
1.10.9 #
- fix: unify list-style episode selection with
episodeselectand remove the legacy list-item event path. - fix(android): add PiP play/pause action state handling and resume an existing PiP player after screen-off recovery.
1.10.8 #
- fix(android): start the localhost HLS server when an existing encrypted HLS cache is hit, so cached short-drama playback uses the local
index.m3u8directly instead of falling back to the legacy MP4 path.
1.10.7 #
- feat(android): implement runtime
PlayerController.setFitMode(...), allowing contain/cover switches without rebuilding the platform view. - feat(android): emit a one-shot
mediaInfoevent after duration and video size are both available.
1.10.6 #
- fix(android): report encrypted HLS source duration as soon as FFmpeg discovers it, so Flutter can receive the short-drama total duration before HLS remuxing finishes.
- fix(android): only auto-enter PiP after an explicit user-leave signal, while screen-off/background stops pause playback instead.
1.10.5 #
- fix(android): ignore provisional HLS live-window duration until the real VOD duration is known, preventing short-drama progress jumps and premature next-episode switching on slow networks.
- fix(android): hand off the PiP video owner when short-drama auto-play moves to the next episode, so PiP continues showing the video instead of the whole Activity.
1.10.4 #
- feat(android): fire
videosizechangeevent to Flutter when first valid video size arrives, matching iOS. Detail payload{width, height}. Subscribers receive it viaPlayerController.eventStream.
1.10.3 #
- fix(android): ship consumer ProGuard rules so JNI-resolved methods on
OkHttpStreamingIOandFFmpegHlsRemuxer$CancelChecker / $ProgressListenersurvive host R8/minify. Without this, host apps withminifyEnabled truecrash on entering encrypted HLS playback withjava.lang.NoSuchMethodError: no non-static method "...readBytes([BI)I".
1.10.2 #
- feat: expose
PlayerController.getCurrentVideoDisplayInfo()for native video display metadata. - fix(ios): sync native player core updates for encrypted playback, fullscreen cleanup, PiP state, and initial seek handling.
- fix(android): align FFmpeg HLS remux bridge with the updated decrypt core callback signature.
1.10.1 #
- fix(android): notify the encrypted player of the first rendered frame when playback enters
PLAYING.
1.10.0 #
- feat(android): add encrypted HLS streaming playback with FFmpeg remuxing and local segment serving.
- feat(android): enable MP4/MPEG-TS/HLS muxer support in bundled FFmpeg libraries.
- fix(android): harden FFmpeg/JNI, streaming I/O, local HTTP server, and memory-pressure handling for playback stability.
1.9.0 #
- feat(ios): add HLS streaming preload support for encrypted playback.
- fix(flutter): clean up fullscreen gesture overlay analyzer issues before release.
1.8.1 #
- fix(android):
PlayerPlatformView.disposenow callsrestoreFromPiPto prevent PiP window leak on view destroy. - fix(android): immersive short drama mode — fix top status bar black strip on OnePlus / ColorOS devices.
- fix(android): landscape pause ad → portrait transition —
hideAllSelectorsno longer callsremoveAllViews, preventing layout disappear. - fix(android): prevent
MPEG4WriterFORTIFY abort — add Annex-B structure validation before writing. - fix(android): fix
DFEncryptedPlayerresource leak —shutdownnow enforces main-thread dispatch.
1.8.0 #
- feat: add
PlayerController.setFitMode(PlayerFitMode)— switch fill mode at runtime without rebuilding the widget. - feat(ios): fire
videosizechangeevent with{width, height}on video ready and VLC video size change. - feat(ios): ad mode now allows
videosizechangeevent through (previously blocked). - fix(android): danmaku settings panel — SeekBar thumb clipped on landscape; add padding equal to thumb radius and disable
clipChildrenon parent containers; addWindowInsetslistener for display cutout / waterfall right safe-inset. - chore(ios): bump
ILOOK_PLAYER_VERSIONto1.0.359.
1.7.0 #
- feat: add
PlayerFitModeenum (contain/cover) andPlayerView.fitModeparameter — passed viacreationParamsto native layer; cover = fill screen (short drama), contain = letterbox (default). - feat(ios): sync native core to v1.0.348 —
isHostFlutterflag blocks shortDrama auto-fullscreen black screen;setupViewWithFrame:attributes:dispatchescreationParamsfit-mode tosetFitMode:. - feat(ios):
FullscreenManagerenhancements for Flutter hosting — suppresses auto-rotate onisHostFlutter, correct safe-area handling inFullscreenPlayerViewController. - feat(android):
setPlayerMode(shortDrama)enters immersive fullscreen (hides status/nav bar, addsKEEP_SCREEN_ON);ShortDramaImmersiveCoordinatoruses activity-level ref counting so multiplePlayerViewinstances cooperate. - feat(android):
creationParamsfit-modemapped toCENTER_CROP(cover) orFIT_CENTER(contain) onTextureView.
1.6.0 #
- feat: add
PlayerPreload/PreloadRequestDart API — priority-based video preload withpreload,cancel,cancelExcept,configure,shutdownAllPlayers. - feat(android): add
ILookPreloadManager/ILookPreloadTask/ILookCacheKey— Android preload system aligned with iOS, with disk cache, priority queue, and inflight preemption. - feat(android):
PlayerPluginadds plugin-levelglobalChannelforshutdownAllPlayers,preloadVideos,cancelPreload,cancelPreloadExcept,configurePreload. - feat(android):
DFEncryptedPlayeradd full lifecycle —setDataSource,prepare,start,pause,stop,seekTo,getState,getDuration,getCurrentPosition. - fix(android):
FFDecryptMuxerstability improvements.
1.5.1 #
- feat(ios): sync ILookPlayerCore to v1.0.322 — enable FFmpeg Class Cluster (auto-routes to
DecryptFileAVPlayer), add offline-encryption engine (DFEnc*/DFURLSessionSourceDownloader/FFVideoPacketQueue). - feat:
playWithAdsadds optionallandingUrlparameter for "了解详情" ad tap-through. - feat: expose
shutdownAllPlayersvia global Flutter channel for batch player cleanup. - fix(android): add
setControlBarVisiblesupport on Android to align with iOS v1.4.0 — fixesMissingPluginExceptionthat broke short-drama playback.
1.5.1 #
- feat: add
setBarrageSettings({displayAreaRatio, opacity, fontSize, speedLevel})— batch configure danmaku display parameters in one call. - feat: add
setPiPEnabled(bool)— enable or disable PiP at runtime. - feat(ios): new
ILookPreloadManager/ILookPreloadTask— priority-based video preload system with configurable concurrency and disk cache limit. - feat(ios): expose preload API via Flutter plugin channel (
preloadVideos,cancelPreload,cancelPreloadExcept,configurePreload). - chore(ios): bump
ILOOK_PLAYER_VERSIONto1.0.330.
1.4.0 #
- feat: add
setControlBarVisible(bool)— show/hide the control bar (play/pause, progress, etc.). When hidden, tap gestures will not reveal controls. - feat(ios):
PlayerUIManagerrespectscontrolBarHiddenin bothshowControlsWithAutoHideandtoggleLandscapeControls. - feat(ios): add
methodSignatureForSelector/forwardInvocationguard inTestComponentto prevent crashes when a native method is missing after sync.sh.
1.3.3 #
- fix(ios/pip): align PiP lifecycle with original uni-app implementation to fix double-video on background.
- Remove manual
startPictureInPictureinsceneWillDeactivate(app still visible). applicationWillResignActiveonly setsisPiPStartPendingflag.applicationDidEnterBackgroundstarts AVPlayer PiP manually.- SampleBuffer PiP (VLC/FFmpeg) relies on system
canStartPictureInPictureAutomaticallyFromInline. - Add
isPiPStartPendingguard, pause protection, andfailedToStartfallback.
- Remove manual
1.3.2 #
- fix(ios/pip): disable
canStartPictureInPictureAutomaticallyFromInlinefor AVPlayer PiP to prevent double-video during app switch animation; SampleBuffer PiP still uses auto-start as required. - fix(ios/pip): add FFmpeg player path to
isBufferingandseekableTimeRangesPiP delegate callbacks. - fix(ios/pip): fix PiP
setPlayingdelegate to handle VLC, FFmpeg, and no-player cases independently. - chore(ios): comment out verbose
[BarrageSpeed]debug NSLogs in BarrageManager, BarrageRenderer, and BarrageScheduler.
1.3.1 #
- chore(ios): clarify
gravityRotationAllowednaming comment to explain why it differs from the exportedsetGravityRotationEnabled:method name.
1.3.0 #
- feat:
PlayerViewnow accepts amodeparameter (PlayerMode.normal/PlayerMode.shortDrama). In short drama mode, Flutter gesture recognizers are not registered so outerPageViewcan handle vertical swipes natively. - feat(ios): short drama mode disables double-tap and long-press gestures to prevent
UITapGestureRecognizer.delaysTouchesEndedfrom blocking Flutter'sVerticalDragGestureRecognizer. - fix(ios): gravity rotation no longer starts automatically on player init — must be explicitly enabled via
setGravityRotationEnabled(true). - fix(ios): reset motion manager orientation state on stop to prevent stale landscape/portrait state on next start.
1.2.1 #
- fix(ios): back button hidden state was being reset by internal UI refresh — add
portraitBackButtonHiddenproperty and respect user override acrossshowControlsand fullscreen transitions. - fix(android): align Android short drama mode with iOS —
setPlayerMode(SHORT_DRAMA)now hides back button by default; explicitsetPortraitBackButtonVisiblecalls take priority over mode defaults.
1.2.0 #
- feat: add
playerMode(normal / shortDrama) — short drama mode disables mid-video pan gestures. - feat: add
backButtonInsets— customize portrait back button position to avoid Dynamic Island. - feat: add
seekToSeconds— precise seek for both normal and short drama modes. - fix: sync adMode priority fix — ad mode now takes precedence over shortDrama, keeping pan gesture enabled during ads.
- feat(android): add
playerMode,backButtonInsets, andseekToSecondssupport on Android.
1.1.1 #
- Fix: restore gravity rotation detection —
startDeviceMotionUpdatesToQueuewas accidentally commented out, causing auto-rotation to stop working. - Fix: add
setGravityRotationEnabledandsetPortraitBackButtonVisiblebridge methods to iOS Flutter bridge.
1.0.1 #
- Add missing Android entry point:
PlayerPlugin.java,AndroidManifest.xml. - Add full Android Java sources: managers, views, models, utils, DanmakuFlameMaster library.
1.0.0 #
- Rename package from
nova_native_playertomohe_native_player. - Fix unused field, unused method, and unnecessary import warnings.
0.0.1 #
- Initial release.
- Native video player for iOS and Android.
- HLS/DASH streaming support.
- Full playback controls, danmaku, DLNA, PiP, fullscreen.