[Bug] Snackbar opens a new app process on Windows
See original GitHub issueDescription
Snackbar opens a new window as shown here when you click the action button on Windows.
Stack Trace
Link to Reproduction Sample
Steps to Reproduce
- Place a snackbar inside the default template.
- Click on the toast action button
- See how a new window appears.
Expected Behavior
Action executes inside the current open app without opening a new app.
Actual Behavior
Action executes and a new app process is opened.
Basic Information
- Version with issue: prev 8 (MAUI prev 14)
- Last known good version: unknown
- IDE: VS
Workaround
None without modifying the snackbar files, since the snackbar registers itself to the Activated event instead of using the solution below:
I just wanted to share a little what I’ve discovered after quite a bit of experimentation. I thought it might be useful for your nuget.
On Windows there’s two kind of activations for UWP apps: foreground and background. The former will use the current app but you need to modify the package.appxmanifext file if you want to use ToastNotificationManagerCompat.OnActivated
. You must both modify the appxmanifest as indicated here in order to make this work without opening a new window. The background activation uses background tasks instead but they require the background tasks to be either registered as an In-Process background task or Out-of-Process background task as shown here.
For my use case the background task sounded ideal, but I was unable to make it work with MAUI (at least for the In-Process Background tasks). I kept getting argument out of range exception.
I might try the out-of-process background tasks later.
In any case, one way I found to solve this issue using the foreground activation (the one currently used here), you need to make this change to the package.appxmanifest
:
in the Package element this needs to be added:
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
IgnorableNamespaces="uap rescap com desktop"
Inside of the applications:
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements />
<Extensions>
<!-- Specify which CLSID to activate when toast clicked -->
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="guid-used-in-maui-csproj" />
</desktop:Extension>
<!--Register COM CLSID LocalServer32 registry key-->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="filename-used-for-the-exe-usually-the-assembly-name.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
<com:Class Id="guid-used-in-maui-csproj" DisplayName="Toast activator"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
</Applications>
Using $targetnametoken$.exe
for the executable in com:ExeServer didn’t work. I had to manually enter the assembly name.
Finally I register in the MauiProgram.cs the event:
using Microsoft.Toolkit.Uwp.Notifications;
builder.
... (every other build action)
.ConfigureLifecycleEvents(configure =>
{
configure.AddWindows(c =>
{
c.OnLaunched((window, args) =>
{
ToastNotificationManagerCompat.OnActivated += WindowsNotificationService.OnActivated;
});
});
});
I made this minimal repo that works: https://github.com/emorell96/MauiWithWindowsToasts
I guess to make the snackbar work you could do:
/// <summary>
/// Show Snackbar
/// </summary>
private partial async Task ShowNative(CancellationToken token)
{
await DismissNative(token);
token.ThrowIfCancellationRequested();
var toastContentBuilder = new ToastContentBuilder()
.AddText(Text)
.AddButton(
new ToastButton { ActivationType = ToastActivationType.Foreground }.SetContent(ActionButtonText));
var toastContent = toastContentBuilder.GetToastContent();
toastContent.ActivationType = ToastActivationType.Background;
dismissedTCS = new();
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(toastContent.GetContent());
NativeSnackbar = new ToastNotification(xmlDocument);
//NativeSnackbar.Activated += OnActivated; //this is not needed anymore
NativeSnackbar.Dismissed += OnDismissed;
NativeSnackbar.ExpirationTime = DateTimeOffset.Now.Add(Duration);
ToastNotificationManager.CreateToastNotifier().Show(nativeSnackbar);
OnShown();
}
public static void OnActivated(ToastNotification sender, object args)
{
if (NativeSnackbar is not null && Action is not null)
{
MainThread.BeginInvokeOnMainThread(Action);
}
}
And you would register OnActivated in an extension method that the user would have to register if he wants to use snackbar on windows?
I’d be happy to contribute to it.
Hope it helps.
Reproduction imagery
Issue Analytics
- State:
- Created a year ago
- Comments:21
Top GitHub Comments
Just a thought for a future feature - maybe we could add an extension to
CommunityToolit.Maui.Core
that adds the single-instance code for Windows easily into the Toolkit?@emorell96 the docs PR is merged. I am closing the issue.