Skip to content
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

[flutter_local_notifications] [WIP] Windows implementation of notifications #1473

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

kennethnym
Copy link
Contributor

@kennethnym kennethnym commented Feb 9, 2022

This draft PR contains Windows implementation of this plugin. Still a WIP.

  • initialize WIP
  • show WIP
  • periodicallyShow (not sure if possible due to limitation of win32)
  • cancel
  • cancelAll
  • pendingNotificationRequests
  • onSelectNotification WIP

cc @azchohfi
Related issue: #746

@azchohfi
Copy link
Contributor

Hey @kennethnym, I've cloned your branch and built the source, and a simple plain notification worked totally fine for me.
The problem with your particular code is the template=ToastGeneric. If you switch that to, for example, ToastText01, then it works fine.
This value needs to be one of the valid TileTemplateType

@kennethnym
Copy link
Contributor Author

kennethnym commented Feb 10, 2022

I tried using the default templates but it would just show "New notification" instead of the actual body.

@kennethnym
Copy link
Contributor Author

@azchohfi To illustrate, this is the code that I have at the moment:

const auto doc = winrt::Windows::UI::Notifications::ToastNotificationManager::GetTemplateContent(winrt::Windows::UI::Notifications::ToastTemplateType::ToastText01);
const auto nodes = doc.GetElementsByTagName(L"text");
nodes.Item(0).AppendChild(doc.CreateTextNode(winrt::to_hstring(title)));

winrt::Windows::UI::Notifications::ToastNotification notif{ doc };
const auto notifier = winrt::Windows::UI::Notifications::ToastNotificationManager::CreateToastNotifier(L"com.dexterous.example");

notifier.Show(notif);

and this is the toast shown:
image

title is 'plain title', but it is not shown in the notification.

@azchohfi
Copy link
Contributor

Oh, I see. The parameters are being sent from dart to C++, but your GetString method is not querying them properly.
You should wrap the key inside an EncodableValue:

	const auto pair = m->find(flutter::EncodableValue(key));

Also, when you call the GetString method, you should store it not using a reference(&):

		const auto body = Utils::GetString("body", args).value();

You can use Visual Studio 2022 or 2019 to attach to the running exe and debug the C++ code. There is also a solution at "flutter_local_notifications\flutter_local_notifications\example\build\windows\example.sln" that will have the reference to all the files so you can add breakpoints, etc.

I've also found another issue. You need to add the id's to the texts, like this:

		XmlDocument doc;
		doc.LoadXml(L"\
			<toast>\
				<visual>\
					<binding template=\"ToastText01\">\
						<text id=\"1\">abc</text>\
						<text id=\"2\">def</text>\
					</binding>\
				</visual>\
			</toast>");

You can also debug this using cout:

std::cout << winrt::to_string(doc.GetXml()) << std::endl;

I've tested this changes here and now the notifications shows properly:
image

Let me know if this helps!

@kennethnym
Copy link
Contributor Author

Ahh thanks, that makes sense now. I am not a C++ programmer, so I really appreciate your help!

@lzzy12
Copy link

lzzy12 commented Feb 14, 2022

Hi, is it working as expected now after your latest commits?

@kennethnym
Copy link
Contributor Author

Basic title body notification is working, but nothing beyond that.

@kennethnym
Copy link
Contributor Author

@lzzy12 Just an update: I have implemented cancel and cancelAll in the latest commit.

@MaikuB
Copy link
Owner

MaikuB commented Feb 21, 2022

FYI this reminds me that zonedSchedule currently part of the platform interface but should be so that will happen soon. Note that there's a 10.0.0 branch right now for the 10.0.0 prerelease

Edit: had trouble adding zonedSchedule to platform interface as overriding the method and having a required parameter isn't possible

@azchohfi
Copy link
Contributor

azchohfi commented Mar 1, 2022

@kennethnym any updates on this PR?

@kennethnym
Copy link
Contributor Author

Hi sorry, busy with coursework at the moment, I will continue the work this weekend.

@kennethnym
Copy link
Contributor Author

kennethnym commented Mar 5, 2022

Just a bit of progress update: I am currently in the process of implementing onSelectNotification callback.

Update: onSelectNotification now works, but only when the program is active.

@kennethnym
Copy link
Contributor Author

kennethnym commented Mar 6, 2022

At the moment, onSelectNotification is only called once. After a toast is clicked and the callback is invoked, for some reason Windows would not invoke the callback anymore whenever subsequent toasts are clicked on. I am investigating what is going wrong.

@kennethnym
Copy link
Contributor Author

Sorry for the silence, I am currently busy with courseworks. At the moment I am still stuck with the issue above. I would really appreciate it If anyone can help me with it.

@azchohfi
Copy link
Contributor

Hello @kennethnym. I've tried your branch and I managed to make it work more than once. Cherry-pick this commit from my fork:
azchohfi@d363e5c

@sidevesh
Copy link

sidevesh commented Apr 3, 2022

@kennethnym I tried your WIP branch and had some issues with notifications and msix packaging,
@azchohfi found the culprit,
YehudaKremer/msix#118 (comment) something to keep in mind.
Looks like we might have to use the correct CreateToastNotifier method based on if the app is packaged or not.

@kennethnym
Copy link
Contributor Author

Thanks for bring that to attention, I'll investigate how to handle msix apps as well.

@kennethnym
Copy link
Contributor Author

@sidevesh Can you test if the latest commit fixes your issue?

@sidevesh
Copy link

I get the following error when building an app with the latest commit:

C:\Users\test\Projects\Side-projects\tomatoro\tomatoro-app\windows\flutter\ephemeral\.plugin_symlinks\flutter_local_notifications\windows\flutter_local_notifications_plugin.cpp(224): error C2220: the 
following warning is treated as an error [C:\Users\test\Projects\Side-projects\tomatoro\tomatoro-app\build\windows\plugins\flutter_local_notifications\flutter_local_notifications_plugin.vcxproj]      
C:\Users\test\Projects\Side-projects\tomatoro\tomatoro-app\windows\flutter\ephemeral\.plugin_symlinks\flutter_local_notifications\windows\flutter_local_notifications_plugin.cpp(224): warning C4715: '`anonymous namespace'::FlutterLocalNotificationsPlugin::Initialize': not all control paths return a value [C:\Users\test\Projects\Side-projects\tomatoro\tomatoro-app\build\windows\plugins\flutter_localBuild process failed.
 
#0      WindowsBuild.build (package:msix/src/windowsBuild.dart:33:7)
<asynchronous suspension>
#1      Msix._createMsix (package:msix/msix.dart:73:7)
<asynchronous suspension>
#2      Msix.create (package:msix/msix.dart:33:5)
<asynchronous suspension>
#3      main (file:///C:/Users/test/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/msix-3.3.1/bin/create.dart:4:3)
<asynchronous suspension>
pub finished with exit code 255

@kennethnym
Copy link
Contributor Author

Thanks for reporting, it's an easy fix.

@kennethnym
Copy link
Contributor Author

@sidevesh the issue should be fixed.

@sidevesh
Copy link

Hey @kennethnym , after the latest commit, I am able to build the app but notification has stopped showing up now.
I had actually made a simple patch earlier replacing the CreateToastNotifier with the correct version and had gotten it to work with the app name showing up correctly, so we should be close to a solution.
I encountered another issue which is that on clicking the notification it opens another copy of the app rather than bring the app to focus or dismiss.
In macOS and Linux, clicking the notification without any on SelectNotification just dismisses the notification and brings the app to focus and I am trying to replicate that on Windows.
Is it possible to implement that behavior ?

@kennethnym
Copy link
Contributor Author

after the latest commit, I am able to build the app but notification has stopped showing up now.

I had actually made a simple patch earlier replacing the CreateToastNotifier with the correct version and had gotten it to work with the app name showing up correctly, so we should be close to a solution.

I encountered another issue which is that on clicking the notification it opens another copy of the app rather than bring the app to focus or dismiss.

Thanks for reporting, I'll look into this.

In macOS and Linux, clicking the notification without any on SelectNotification just dismisses the notification and brings the app to focus and I am trying to replicate that on Windows.

It should be possible to implement this behavior on Windows as well.

@kennethnym
Copy link
Contributor Author

@sidevesh From the issue you linked earlier, @azchohfi mentioned:

For deciding whether to use the overloaded method...
HasIdentity true = CreateToastNotifier()
HasIdentity false = CreateToastNotifier(myAumid)"

I have in fact integrated this into the code in previous commits already:

if (hasIdentity.value())
    toastNotifier = winrt::Windows::UI::Notifications::ToastNotificationManager::CreateToastNotifier();
else
    toastNotifier = winrt::Windows::UI::Notifications::ToastNotificationManager::CreateToastNotifier(winrt::to_hstring(aumid));

Is the app name still not showing up correctly?

As for the other issues, I still need some time to figure out what's going on that is causing them to occur.

@sidevesh
Copy link

hey @kennethnym , tried it again and same behavior, notifications have stopped showing up,
so can't really see if the app name in notification is fixed or not.

@sidevesh
Copy link

Like I mentioned previously I had simply replaced the CreateToastNotifier with the correct version and managed to fix the app name,
although that would mess up non msix apps so your fix with the check built in is the proper solution here.

@kennethnym
Copy link
Contributor Author

I am struggling to understand why it would stop working altogether. Exams are coming up for me; I'll start working on it again after exams.

@sidevesh
Copy link

Also, any pointers about the issue: on clicking the notification it opens another copy of the app rather than bring the app to focus or dismiss ?

@kennethnym
Copy link
Contributor Author

I have no idea what is causing that issue either. It wasn't happening before, and I never changed the code related to that.

@sidevesh
Copy link

I have no idea what is causing that issue either. It wasn't happening before, and I never changed the code related to that.

Okay, I will try testing this in a non msix build to see if msix packaging is causing the difference in behavior, might help us debug this issue.

@DomingoMG
Copy link

DomingoMG commented Jun 12, 2022

I'm looking forward to using this on Windows, Is it a long way from launch?

@kennethnym
Copy link
Contributor Author

Sorry for the silence. I've been very busy lately, so I was not able to squeeze time to work on this. I will give this another look over the weekend.

@keanallen
Copy link

Hello, guys

Copy link
Contributor

@lightrabbit lightrabbit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found some parts in the code that could be improved, could you please take a look?


const auto bindingNode = doc.SelectSingleNode(L"//binding[1]");

if (title.has_value()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to this link: https://docs.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml
Maybe we can pass the XML text directly to the plugin and then combine the title and content etc into XML text on the Dart code side?
In this way, more Toast styles can be easily supported in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is something that I have thought about actually - a Windows specific method that allows users to pass in XML of the notification toast directly.

/// <summary>
/// String representation of the callback GUID.
/// </summary>
const std::string CALLBACK_GUID_STR = "{68d0c89d-760f-4f79-a067-ae8d4220ccc1}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According the resources doc in UpdateRegistry. It looks like every application should have a unique GUID, so the GUID here should be configurable. Maybe change the GUID to be passed from the initialization parameter instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, will fix.


UINT32 length;
auto err = GetCurrentPackageFullName(&length, nullptr);
if (err != ERROR_INSUFFICIENT_BUFFER) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run the example here, it returns the error code 87(ERROR_INVALID_PARAMETER) which causes the initialization to fail. But when I still return false(not std:nullopt) here, the plugin still works fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the cause of the problem. The variable length needs to be initialized.
Replace UINT32 length; to UINT32 length = 0; could resolve this issue.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow! Can't wait! Thank you guys for working on this.

@kennethnym
Copy link
Contributor Author

Quick update - I recently switched to working on a MacBook fully as I will be away from my main computer for an extended period. Parallel seems to be a good option for running Windows on a MacBook. As soon as I get that up and running I should be able to start working on this (longrunning) PR, addressing @lightrabbit 's helpful comments as well.

@tenraneko
Copy link

Hello everybody!
Sorry, I still do not understand how to fix the error with the wrong app name in notifications 😢

@kennethnym
Copy link
Contributor Author

I think this is a known issue at the moment. Unfortunately I don't have the time at the moment to look into this, but when I do I will see what's going I'll see what I can do to fix it!

@xBLACKICEx
Copy link

hi @kennethnym is there any news for support on windows ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants