bmdrm_mobile 0.0.21
bmdrm_mobile: ^0.0.21 copied to clipboard
A Flutter plugin for DRM-protected video playback with watermark support.
0.0.21 #
- Fixed the fullscreen drawer being unusable on iOS. The toggle pill never
appeared because it is drawn natively on Android, and the iOS side both
discarded the
BmdrmDrawerToggleconfiguration and drew nothing — the pill is now rendered from Dart on iOS and styled to match Android's. - Fixed AVKit's fullscreen presentation staying on screen in drawer mode. The
previous
dismiss(animated:)was a no-op (the player controller is never presented), so the native modal covered the Flutter drawer entirely. - Fixed Flutter-owned fullscreen being impossible to leave on iOS, and the
exit path never reporting
onFullscreenExit, which left both the plugin and the host app stuck in fullscreen. - Fixed the playback controls disappearing for good after the player was
resized.
AVPlayerViewControllerwas embedded view-only, leaving it detached from the view-controller hierarchy and starving it of the appearance callbacks AVKit builds its controls from; it is now a proper child controller. - The iOS drawer now insets the video (62/38) like Android instead of covering it, so Flutter content is never composited over the player where it would swallow the touches AVKit's controls need.
- Added the missing
setDrawerOpenhandler on iOS, which previously fell through tonotImplementedand surfaced a spurious player error.
0.0.20 #
- Fixed the fullscreen "About" drawer close (X) button doing nothing in apps
that host more than one player. The fullscreen/drawer state is now shared
across plugin instances, so
closeDrawer()always reaches the active fullscreen view instead of a stale one. - Fixed a duplicate, frozen video frame bleeding through the drawer gap while fullscreen — the inline player surface is now hidden for the duration.
- Fullscreen video now fills ultra-wide screens (zoom-crop) instead of sitting in a black pillarbox with stray controls floating in the empty area.
- Smoothed the exit-fullscreen transition so the drawer panel no longer flashes during the landscape-to-portrait flip.
0.0.19 #
- iOS playback analytics (parity with Android). iOS now reports the same
quality-of-service session stats to the backend that Android already sends —
previously iOS sent nothing. While a DRM video plays, the plugin accumulates
play / pause / buffering time, completion percentage, stalls, dropped frames,
and quality switches, then POSTs them to
https://<edge>.video-crypt.com/api/Sessionon the same cadence as Android (roughly every 10 seconds, plus a final report when the player is closed). Time is measured on a wall clock, so paused and buffering seconds are counted even while playback is not advancing.
0.0.18 #
- The fullscreen drawer toggle pill now shows and hides together with the video controls — it fades out when the controls auto-hide and reappears on tap, instead of staying on screen.
0.0.17 #
- The fullscreen drawer toggle is now a customizable pill button (Android). Pass
fullscreenDrawerToggle: BmdrmDrawerToggle(...)to set itslabel,color, andtextColor, orvisible: falseto hide it and open the drawer yourself viaBmdrmFullscreenController. Default: a translucent pill (icon + label + chevron) centered above the progress bar.
0.0.16 #
- Continue Watching + on-device SQLite resume store. Last-watched positions
now persist in an on-device SQLite database (via
sqflite), keyed perresumeId, saved automatically during playback (replacing the per-platform key-value stores). - New API on
VideoPlayerController:continueWatching({limit})returns the in-progress videos most recently watched first (each aResumeEntrywith position, duration, andprogress); plusgetSavedPosition,clearSavedPosition, andclearAllSavedPositions. - Adds a
sqflitedependency.
0.0.15 #
- Fixed the janky fullscreen enter/exit when
fullscreenDrawerBuilderis set. Drawer-mode fullscreen now runs the native fullscreen path (fresh surface, atomic rotation) instead of re-parenting the video surface from Flutter, so the transition is smooth with no glitch or delay. - The drawer opens and closes beside a native-inset video via a toggle button;
open/close and enter/exit are also drivable through
BmdrmFullscreenController.
0.0.14 #
- Customizable fullscreen drawer: pass
fullscreenDrawerBuildertoBmdrmVideoPlayerto show an app-owned panel (any Flutter widget) beside the video while in fullscreen, with a built-in toggle button and exit-fullscreen button.- Dart: new params on every constructor —
fullscreenDrawerBuilder,fullscreenDrawerIcon,fullscreenDrawerWidth,fullscreenDrawerBackgroundColor,fullscreenDrawerAlignment, andfullscreenController(aBmdrmFullscreenControllerto open/close the drawer and enter/leave fullscreen programmatically, and to observe state). When a builder is supplied, fullscreen is rendered by Flutter (the same platform view is re-parented into a root overlay), and the video shrinks beside the open drawer.VideoPlayerControllergainssetFullscreen(). - Backward compatible: with no
fullscreenDrawerBuilder, fullscreen keeps its native behaviour unchanged. Native learns whether Flutter owns fullscreen via aflutterOwnsFullscreenflag insetDrmConfig; when set, the native fullscreen control notifies Flutter (onFullscreenEnter/onFullscreenExit) instead of building a native fullscreen surface. - Android:
enterFullscreen/exitFullscreenshort-circuit to a notify-only path (applyFlutterFullscreen) that keeps the control icon, watermark scaling and hardware-back handling in sync. - iOS: the
AVPlayerViewControllerfullscreen presentation is intercepted and redirected to Flutter; asetFullscreenchannel method keeps orientation and watermark in sync.
- Dart: new params on every constructor —
0.0.13 #
- Resume from last position: playback now automatically resumes from where the
viewer last stopped. The position is saved on the device as the video plays
(throttled), on pause, and when the player is closed, then restored the next time
the same video is opened. A fully watched video (within the last few seconds)
starts over from the beginning.
- Dart:
BmdrmVideoPlayergainsresumeIdandresumeFromLastPosition(defaulttrue) on every constructor. The resume key is resolved asresumeId→videoId→ thevideoIdinside a backend session; resume is disabled when no stable key is available.VideoPlayerControllergainsclearSavedPosition()andgetSavedPosition(). - Android: positions are persisted in
SharedPreferencesand applied viaExoPlayer.seekTo()beforeprepare(). - iOS: positions are persisted in
UserDefaultsand applied onreadyToPlay. Also adds the previously-missing periodic position reporting, soonPositionChanged,onDurationChangedandonPausenow fire on iOS too (parity with Android). HardenedgetCurrentPosition/getDurationagainstNaN/indefinite durations.
- Dart:
0.0.12 #
- Android: Fixed playback callbacks (
onPlay,onPause,onPositionChanged,onDurationChanged) never reaching the app when a secondFlutterEngineis present (e.g. Firebase Cloud Messaging's background isolate). The plugin sent events over static method channels that the background engine overwrote, so callbacks were delivered to the wrong isolate. Events are now sent over aMethodChannelbound to the platform view's own engine messenger (the UI engine), so they always reach the isolate that owns the player. - Android: Removed the spurious one-shot
onError("Player not available or disposed") emitted at autoplay start — callingplay/pausebefore the platform view exists is now a no-op, sinceconfigureDrmAndPlayalready starts playback once the view is created.
0.0.11 #
- Android: Fixed
onPlay,onPause,onPositionChangedandonDurationChangednever firing. These callbacks are now driven by the real ExoPlayer playback state instead of a fixed-delay one-shot, so they also fire for the on-screen controls and survive the DRM player rebuild:onPlay/onPauseare emitted fromonIsPlayingChanged.onDurationChangedis emitted once the media is ready (real duration).onPositionChangedis emitted on a ~500 ms ticker while playing, plus a final tick on pause.
- Dart:
VideoPlayerControllernow storesonPositionChanged/onDurationChanged(previously dropped in_setCallbacks) and handles theonPause/onPositionChanged/onDurationChangedmethod-channel calls. The optimistic localonPlay/onPauseinvocations were removed so events are no longer fired twice.
0.0.10 #
- Android: Fixed the playback speed menu pausing the video — the menu is no longer a focusable window, so it no longer steals window focus (which caused the player to pause). Speed can now be changed while the video keeps playing.
0.0.9 #
- Android: Added an in-player playback speed selector (0.5×–2×) to the control bar, next to the fullscreen button, with a custom dark speed menu. Available on the inline and fullscreen players, and the selected speed persists across them.
- iOS: Enabled the native AVPlayer playback speed menu (iOS 16+) and routed
programmatic
setPlaybackSpeedthrough it so the menu and the API stay in sync.
0.0.8 #
- Android: Fixed reversed fullscreen toggle icons — the control now shows the expand icon while windowed and the collapse icon while in fullscreen.
- Android/Widevine: Build the license and challenge-nonce URLs from the DRM server response, and send the device-attestation nonce signature in IEEE P1363 raw format.
0.0.7 #
- Android: Internal hardening for license requests.
- Minor stability improvements.
0.0.6 #
- iOS/FairPlay: Fixed license URL formatting - correct path segment.
- iOS: Fixed certificate URL resolution - automatically convert relative paths (/cert) to absolute URLs.
- iOS: Fixed communication channel - changed to strong reference to prevent platform events from dropping.
- iOS: Added onDRMStep debugging logs to track FairPlay handshake in real-time.
- iOS: Resolved build errors and enabled native playback on physical devices.
0.0.5 #
- Implemented RTL (Right-to-Left) support for Arabic language in video player.
- Fixed horizontal layout padding issues for better UI consistency.
0.0.4 #
- Android: Fixed hardware back button to exit fullscreen mode instead of quitting the app.
0.0.3 #
- Implemented JWT authentication for DRM sessions.
- Fixed 401 Unauthorized error during DRM license requests.
- Improved URL signing and re-signing mechanism for expired signatures.
- Enhanced error logging for license authentication issues.
0.0.2 #
- Refine player layout and synchronize control animations.
- Added custom player control icons (play, pause, forward, rewind, fullscreen).
- Improved player UI with custom colors and styles.
0.0.1 #
- Initial release of BMDRM Mobile.
- Support for Widevine (Android) and FairPlay (iOS) DRM systems.
- Integrated watermark overlay support (static and dynamic).
- Native ExoPlayer (Media3) implementation on Android.
- Native AVPlayer implementation on iOS.
- Secure DRM session management and cryptographic signing.
- Multiple player constructors: drmMinimal, drmWithSession, drmFromBackendSession, and drmDirectUrl.