github CommunityToolkit/Maui 11.0.0-mediaelement
MediaElement v11.0.0 Bug Fix-A-Palooza

latest release: 5.0.0-maps
one hour ago

MediaElement v11.0.0 Bug Fix-A-Palooza 🎉

We have FINALLY implemented Device Tests! These are platform-specific unit tests that run on iOS, Android, MacCatalyst and Windows. This allows us to unit test all platform-specific code and has MASSIVELY increased our Unit Test Code Coverage to 91.8% Code Coverage on CommunityToolkti.Maui.MediaElement.

Breaking Changes

To fix certain bugs, and re-align features to ensure they behave the same across all platforms, we did have to modify some APIs and the associated underlying behavior. Please find the features you use, below, and update your apps accordingly.

All packages
  • API: Null arguments throw ArgumentNullException at the call. Public and protected members of the five libraries now guard the non-nullable reference parameters they cannot handle (about 275 guards).
    • A null that used to cause a NullReferenceException later (or was stored silently) fails at the call, with a ParamName. What to do: fix the caller.
    • An async member throws from the call itself, before it returns a Task.
    • Null arguments that a member handled before are still accepted, for example an IProgress<double> or a Paint background of null.
    • Feature-specific effects are listed in each feature's section.
    • BasePlatformBehavior guards only bindable. A null platform view passes through, because the Android IconTintColorBehavior accepts it.
  • Setup: CommunityToolkit.Maui.Core on Android adds a <queries> entry for the launcher (MAIN/HOME) to the app's merged manifest through the package's library manifest (src/CommunityToolkit.Maui.Core/AndroidManifest.xml). Badge needs it on Android 11 and later. If your app or Play listing reviews <queries>, check the merged manifest.
  • Setup: Dependencies: on Windows, CommunityToolkit.Maui.Core references System.Speech 10.0.11 (it was 10.0.1). No action is needed unless you pin the package. This comes from #3288 on main, not from this PR.

New APIs In This Release

  • Popup now declares IPaddingElement, which it already inherited from ContentView
  • GravatarImageSource declares IStreamImageSource, which it already inherited from StreamImageSource, and overrides Cancel() (see GravatarImageSource, after that ApiCompat run);
  • [SupportedOSPlatform("android23.0")] on the Android StatusBarBehavior (see StatusBar and StatusBarBehavior).
  • DefaultPopupSettings.BackgroundColorDark and OnInitializing (#3345)
  • NumericValidationBehavior.Interval (#3329)
MediaElement
API
  • Null arguments: FileMediaSourceConverter.ConvertFrom(null) throws ArgumentNullException.
  • Null arguments: MediaFailedEventArgs rejects null for its non-nullable members.
Behavior
  • An exception thrown by an event handler while Source changes is reported through MediaFailed.
    • Before, an exception from a StateChanged, PropertyChanged or PropertyChanging handler reached the code that set Source, or ended the app when MAUI set it from XAML or a binding.
    • Now it is logged and the change goes on. The first exception is reported once through MediaFailed: ErrorMessage names its type and message, and CurrentState is not set to Failed.
    • What to do: handle MediaFailed, and check ErrorMessage before treating every MediaFailed as a failed source.
  • MediaElement playback.
    • SeekTo clamps a position outside the media to its start or end and raises SeekCompleted. On iOS such a seek never completed.
    • SeekTo fails with the platform's exception, for example InvalidOperationException before the player is ready, where that exception ended the app.
    • Play() at the end of the media starts it again on iOS and Mac Catalyst, as on Android.
    • On Android, CurrentState reports Buffering while buffering (it was Paused) and Stopped at the end of the media.
    • A source without data empties the player and reports None.
    • What to do: check code that relied on the old states.
  • A disconnected handler stops the position timer. The MediaElement no longer keeps its page alive after the page is left. No action is needed.
    • Why: the dispatcher timer stops when the handler disconnects, and starts again when a handler connects later.
    • Found on iOS: a probe left the Sample's MediaElementPage alive 3 of 3 times after it was left (0 of 3 with the fix). The same leak is fixed and tested on Android, Mac Catalyst and Windows.
    • On Windows, MediaOpened arrives on the player's worker thread. An open that was still running when the handler disconnected no longer starts the timer again: the timer starts on the UI thread, and only while a handler is attached.
    • A second leak was in the Sample: MediaElementFromStreamPage was IAsyncDisposable, so the window's service scope kept every page that was opened.
      • iOS: a probe left the page alive 3 of 3 times before the change, 0 of 3 after.
      • Windows (the Sample at 4a8d407, 5 visits, a GC dump after the 5th Back): 0 MediaElementFromStreamPage, MediaElement or StreamMediaSource stay alive, GC heap 6.5 MB. With the Sample change reverted: 5 of each, 167.7 MB.
  • Also fixed: FileMediaSourceConverter.ConvertFrom had an inverted condition. A real path threw InvalidOperationException, and an empty or white-space string returned a source. Now a real path returns the FileMediaSource, and an empty or white-space string throws InvalidOperationException, as documented.

What's Changed

Don't miss a new Maui release

NewReleases is sending notifications on new releases.