Add support for local files and package resources to MediaElement#2502
Add support for local files and package resources to MediaElement#2502ne0rrmatrix wants to merge 70 commits intoCommunityToolkit:mainfrom
Conversation
Updated `PlatformUpdateSource` to be asynchronous, re-implemented `SetPoster` method for robustness, and replaced `MetadataArtworkUrl` with `MetadataArtworkSource` across the project. - Replaced `MetadataArtworkUrl` with `MetadataArtworkSource` in `MediaElementPage.xaml` and related files. - Introduced `loadCustomMediaSource` constant and `saveDirectory` string in `MediaElementPage.xaml.cs`. - Updated `ChangeSourceClicked` method to handle new media source and artwork property. - Added file handling methods: `Savefile`, `GetFileName`, and `PickAndShow`. - Updated `IMediaElement` and `MediaElement` class to use `MetadataArtworkSource`. - Modified `SetMetadata` in `Metadata.macios.cs` for new artwork property. - Removed `Metadata` class from `Metadata.windows.cs`. - Enhanced `MediaManager.android.cs` to handle new artwork property and fetch image data. - Added `BlankByteArray` method and `PlaybackState` class in `MediaManager.android.cs`. - Made `PlatformUpdateSource` in `MediaManager.macios.cs` asynchronous, updated `Dispose` method. - Added `GetArtwork` struct for fetching artwork in `MediaManager.macios.cs`. - Updated `MediaManager.windows.cs` to handle new artwork property and added `ArtworkUrl` method. - Updated `MediaElementTests` for new artwork property.
Simplified `SetMetadata` in `Metadata.macios.cs` by removing a null check for `artwork` before checking if it is a `UIImage`. Cleaned up `Dispose` in `MediaManager.android.cs` by removing redundant empty lines. Streamlined `StopService` in `MediaManager.android.cs` by removing `HttpClient` usage and `GetBytesFromMetadataArtworkUrl` method. Updated `Dispose` in `MediaManager.macios.cs` to change `SetPoster` return type from `Task` to `ValueTask`. Refactored `UpdateMetadata` in `MediaManager.windows.cs` to handle different `MetadataArtworkSource` types explicitly and removed redundant `ArtworkUrl` method. Cleaned up `OnPlaybackSessionPlaybackStateChanged` in `MediaManager.windows.cs` by removing the now redundant `ArtworkUrl` method.
… into MetaDataSource
69936ec to
9347a3a
Compare
… into MetaDataSource
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.macios.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Primitives/Metadata.macios.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.windows.cs
Outdated
Show resolved
Hide resolved
samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
Outdated
Show resolved
Hide resolved
…os.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…oid.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…oid.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ios.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…oid.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
src/CommunityToolkit.Maui.MediaElement/Primitives/Metadata.macios.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.macios.cs
Outdated
Show resolved
Hide resolved
src/CommunityToolkit.Maui.MediaElement/Primitives/Metadata.macios.cs
Outdated
Show resolved
Hide resolved
StartService now verifies isAndroidForegroundServiceEnabled before starting the foreground service, preventing unnecessary service startup when the feature is disabled.
Updated the logging statement to include the exception object
using the "{Ex}" placeholder, providing more detailed error
information when file picking fails.
Correct ToggleCommand null check, clarify NSData log message, and remove file path/asset stream handling in MediaManager.android.cs for simplified stream logic.
SetMetadata is now called without a CancellationToken, reflecting a change in its method signature that no longer requires this parameter.
src/CommunityToolkit.Maui.MediaElement/Primitives/Metadata.macios.cs
Outdated
Show resolved
Hide resolved
samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs
Outdated
Show resolved
Hide resolved
…MediaElementPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ios.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Removed null-conditional logging for Logger, assuming it is always non-null. Moved thumbnail and poster clearing logic outside the switch statement to ensure artwork is reset when source, stream, or uri are null. This improves UI consistency when no artwork is available.
Prevent possible NullReferenceException by adding a null-conditional check when accessing url.AbsoluteString after calling NSBundle.MainBundle.GetUrlForResource. This ensures the code safely handles cases where the returned url may be null.
| AVAssetTrack? videoTrack = null; | ||
| if (PlayerItem.Asset is not null) | ||
| { | ||
| #if IOS || MACCATALYST | ||
| // Use the non-obsolete API for iOS 18+ and MacCatalyst 18+ | ||
| if (OperatingSystem.IsIOSVersionAtLeast(18) || OperatingSystem.IsMacCatalystVersionAtLeast(18)) | ||
| { | ||
| // On iOS 18+ and MacCatalyst 18+, AVAsset.TracksWithMediaType is obsolete. | ||
| // Instead, use the Tracks property and filter for video tracks. | ||
| videoTrack = PlayerItem.Asset.Tracks.FirstOrDefault(t => t.MediaType == AVMediaTypes.Video.GetConstant()); | ||
| } | ||
| else | ||
| #endif | ||
| { | ||
| // For earlier versions, use the existing API, but check for null | ||
| var videoMediaType = AVMediaTypes.Video.GetConstant(); | ||
| if (videoMediaType is not null) | ||
| { | ||
| videoTrack = PlayerItem.Asset.TracksWithMediaType(videoMediaType).FirstOrDefault(); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
There is code duplication between the SetPoster method (lines 539-560) and the GetTrack method (lines 505-516). Both implement version-specific logic for handling AVAsset.TracksWithMediaType obsolescence in iOS 18+/MacCatalyst 18+. However, the SetPoster implementation correctly uses the new Tracks API (line 548), while GetTrack simply returns null for newer OS versions. Either the GetTrack method should be fixed to match SetPoster's implementation, or SetPoster should call GetTrack instead of duplicating the logic.
| System.Diagnostics.Trace.WriteLine($"Failed to open app package file: '{resource}' - stream is null."); | ||
| return null; | ||
| } | ||
| await inputStream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false); | ||
| memoryStream.Position = 0; | ||
| NSData? nsdata = NSData.FromStream(memoryStream); | ||
| if (nsdata is null) | ||
| { | ||
| System.Diagnostics.Trace.TraceInformation($"NSData create from stream: {nsdata} is null."); |
There was a problem hiding this comment.
Using System.Diagnostics.Trace.WriteLine for debug logging violates the codebase's logging convention. According to the project's coding standards, Trace.WriteLine() should be used instead of Debug.WriteLine(), but more importantly, this file should use structured logging via the ILogger instance that exists in other platform managers. The Windows and Android implementations consistently use Logger.LogWarning() and Logger.LogInformation() for similar scenarios. This inconsistency makes debugging harder and prevents proper log filtering and categorization.
| Player.Play(); | ||
| } | ||
|
|
||
| await SetPoster(); |
There was a problem hiding this comment.
The SetPoster method can throw exceptions when loading images (UIImage.LoadFromData or UIImage.FromFile might fail), and it's called from PlatformUpdateSource without a try-catch block at line 276. If image loading fails, the entire source update operation could fail. Consider wrapping the SetPoster call in a try-catch block to ensure that media playback isn't prevented by artwork loading failures.
| await SetPoster(); | |
| try | |
| { | |
| await SetPoster(); | |
| } | |
| catch (Exception ex) | |
| { | |
| Logger.LogError(ex, "Failed to set poster artwork."); | |
| } |
| { | ||
| if (!File.Exists(resource)) | ||
| { | ||
| System.Diagnostics.Trace.WriteLine($"Metadata artwork file not found: '{resource}'."); |
There was a problem hiding this comment.
Using System.Diagnostics.Trace.WriteLine for debug logging violates the codebase's logging convention. According to the project's coding standards, Trace.WriteLine() should be used instead of Debug.WriteLine(), but more importantly, this file should use structured logging via the ILogger instance that exists in other platform managers. The Windows and Android implementations consistently use Logger.LogWarning() and Logger.LogInformation() for similar scenarios. This inconsistency makes debugging harder and prevents proper log filtering and categorization.
Converted HttpClient from static to instance member in MediaManager. Updated GetArtworkFromMediasource and GetBytesFromMetadataArtworkUrl to instance methods, ensuring each MediaManager has its own HttpClient.
Added validation to ensure the artwork file path is not null or empty before loading the bitmap. Logs a trace message and returns null if the path is invalid, preventing potential errors.
[Proposal] Add support for local files and package resources to MediaElement #2151
Description of Change
Add support for file and resource file types to
MediaElement.MetadataArtworkSource. This will allow developers to set artwork usingMediaSourceclass.Linked Issues
PR Checklist
approved(bug) orChampioned(feature/proposal)mainat time of PRAdditional information
Summary
Add support for local files and package resources as a source for
MediaElement.MetadataArtworkUrl. This will add the missing support for all types of files on all device for artwork images.Motivation
Allow developer more options to add images from more locations to use as artwork for player.
Detailed Design
API Design:
Usage Syntax
XAML:
Code Behind: