Skip to content

Fix Windows Media Source bug with Packaged Apps #2609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.Reflection;
using Windows.ApplicationModel;

namespace CommunityToolkit.Maui.Extensions;

// Since MediaElement can't access .NET MAUI internals we have to copy this code here
// https://github.com/dotnet/maui/blob/main/src/Essentials/src/AppInfo/AppInfo.uwp.cs
static class AppInfoUtils
{
static readonly Lazy<bool> isPackagedAppLazy = new Lazy<bool>(() =>
{
try
{
if (Package.Current != null)
{
return true;
}
}
catch
{
// no-op
}

return false;
});

/// <summary>
/// Gets if this app is a packaged app.
/// </summary>
public static bool IsPackagedApp => isPackagedAppLazy.Value;

static readonly Lazy<string> platformGetFullAppPackageFilePath = new Lazy<string>(() =>
{
return IsPackagedApp
? Package.Current.InstalledLocation.Path
: AppContext.BaseDirectory;
});

/// <summary>
/// Gets full application path.
/// </summary>
public static string PlatformGetFullAppPackageFilePath => platformGetFullAppPackageFilePath.Value;

/// <summary>
/// Converts a <see cref="PackageVersion"/> object to a <see cref="Version"/> object.
/// </summary>
/// <param name="version">The <see cref="PackageVersion"/> to convert.</param>
/// <returns>A new <see cref="Version"/> object with the version information of this app.</returns>
public static Version ToVersion(this PackageVersion version) =>
new Version(version.Major, version.Minor, version.Build, version.Revision);

/// <summary>
/// Gets the version information for this app.
/// </summary>
/// <param name="assembly">The assembly to retrieve the version information for.</param>
/// <param name="name">The key that is used to retrieve the version information from the metadata.</param>
/// <returns><see langword="null"/> if <paramref name="name"/> is <see langword="null"/> or empty, or no version information could be found with the value of <paramref name="name"/>.</returns>
public static Version GetAppInfoVersionValue(this Assembly assembly, string name)
{
if (assembly.GetAppInfoValue(name) is string value && !string.IsNullOrEmpty(value))
{
return Version.Parse(value);
}

return null!;
}

/// <summary>
/// Gets the app info from this apps' metadata.
/// </summary>
/// <param name="assembly">The assembly to retrieve the app info for.</param>
/// <param name="name">The key of the metadata to be retrieved (e.g. PackageName, PublisherName or Name).</param>
/// <returns>The value that corresponds to the given key in <paramref name="name"/>.</returns>
public static string GetAppInfoValue(this Assembly assembly, string name) =>
assembly.GetMetadataAttributeValue("Microsoft.Maui.ApplicationModel.AppInfo." + name);

/// <summary>
/// Gets the value for a given key from the assembly metadata.
/// </summary>
/// <param name="assembly">The assembly to retrieve the information for.</param>
/// <param name="key">The key of the metadata to be retrieved (e.g. PackageName, PublisherName or Name).</param>
/// <returns>The value that corresponds to the given key in <paramref name="key"/>.</returns>
public static string GetMetadataAttributeValue(this Assembly assembly, string key)
{
foreach (var attr in assembly.GetCustomAttributes<AssemblyMetadataAttribute>())
{
if (attr.Key == key)
{
return attr.Value!;
}
}

return null!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Diagnostics.CodeAnalysis;

namespace CommunityToolkit.Maui.Extensions;

// Since MediaElement can't access .NET MAUI internals we have to copy this code here
// https://github.com/dotnet/maui/blob/main/src/Essentials/src/AppInfo/AppInfo.uwp.cs
static class FileSystemUtils
{
//
// Summary:
// Normalizes the given file path for the current platform.
//
// Parameters:
// filename:
// The file path to normalize.
//
// Returns:
// The normalized version of the file path provided in filename. Forward and backward
// slashes will be replaced by System.IO.Path.DirectorySeparatorChar so that it
// is correct for the current platform.
public static string NormalizePath(string filename)
{
return filename.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar);
}

public static bool AppPackageFileExists(string filename)
{
string path = PlatformGetFullAppPackageFilePath(filename);
return File.Exists(path);
}

public static string PlatformGetFullAppPackageFilePath(string filename)
{
if (filename == null)
{
throw new ArgumentNullException("filename");
}

filename = NormalizePath(filename);
return Path.Combine(AppInfoUtils.PlatformGetFullAppPackageFilePath, filename);
}

public static bool TryGetAppPackageFileUri(string filename, [NotNullWhen(true)] out string? uri)
{
string text = PlatformGetFullAppPackageFilePath(filename);
if (File.Exists(text))
{
if (AppInfoUtils.IsPackagedApp)
{
uri = "ms-appx:///" + filename.Replace('\\', '/');
}
else
{
uri = "file:///" + text.Replace('\\', '/');
}

return true;
}

uri = null;
return false;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Numerics;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Extensions;
using CommunityToolkit.Maui.Views;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Xaml.Controls;
Expand Down Expand Up @@ -301,14 +302,21 @@ protected virtual async partial ValueTask PlatformUpdateSource()
}
else if (MediaElement.Source is ResourceMediaSource resourceMediaSource)
{
string path = "ms-appx:///" + resourceMediaSource.Path;
if(string.IsNullOrWhiteSpace(resourceMediaSource.Path))
{
Logger.LogInformation("ResourceMediaSource Path is null or empty");
return;
}

// To test this run app as unpackaged and packaged.
string path = FileSystemUtils.PlatformGetFullAppPackageFilePath(resourceMediaSource.Path);
if (!string.IsNullOrWhiteSpace(path))
{
Player.Source = WinMediaSource.CreateFromUri(new Uri(path));
}
}
}

protected virtual partial void PlatformUpdateShouldLoopPlayback()
{
if (Player is null)
Expand Down
Loading