-
-
Notifications
You must be signed in to change notification settings - Fork 695
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
Toga with ability to make push notifications #907
Comments
@yusuf8ahmed Absolutely! We'd love to have an API for notification popups (often called "Toasts", because they pop-up like a piece of toast from a toaster) built into Toga! @danyeaw wrote up a blog post about the process of developing a new widget for BeeWare - he gave that content as a talk at PyCon US 2019. "Toast notifications" aren't strictly widgets, but the process will be very much the same. The first step is some research. It looks like you know how to do this in Windows; however, we need to make sure that the Toga API you propose is usable on other platforms. You don't have to write the implementation for macOS, Linux, Android and iOS - but we need to have some idea of the concepts that a generic API needs to cover. Are there platform limitations we need to be aware of? How long can push messages be? Do we have to provide title and description? Do we need to provide an icon? Are there any other features we may want to control programatically? Are there any OS-level registration requirements? Once you've got that research, you can propose an API. I'm guessing this will be an app-level API - i.e., an entry point on the App object - but if some other API makes sense to you, feel free to propose that. |
Thanks for the quick response. I am like 2 hours into basic research and all proposals are tentative and can change. I currently have a Toaster API that can work on Windows, macOS and Linux. Windows (currently complete and in testing phase): https://docs.microsoft.com/en-us/uwp/api/windows.ui.notifications.toasttemplatetype?view=winrt-18362 macOS (Build and then testing): https://pyobjc.readthedocs.io/en/latest/api/module-objc.html Linux (Build and then testing): For Linux I am specifically targeting Ubuntu for full toast Compatibility. https://manpages.ubuntu.com/manpages/xenial/man1/notify-send.1.html ios and android (Look for a place to start): Answers Are there platform limitations we need to be aware of? How long can push messages be? Do we have to provide a title and description? Do we need to provide an icon? Are there any other features we may want to control programmatically? Are there any OS-level registration requirements? -Windows users must have Powershell and .NET work correctly and Please message back as I would like to have some feedback on the current plan |
@yusuf8ahmed Thanks for doing that research - definitely a good start! Calling into shell commands isn't really an option here. We have access to the full system APIs, so we should be using those unless there is absolutely no other option. On macOS specifically, we use a library called Rubicon to invoke any Objective C calls that are needed. Rubicon and PyObjC are similar in terms of API, so the Stack Overflow examples you've presented should be portable without much effort. On Linux, the solution definitely won't be a command line tool - it will be something that integrates with the FreeDesktop.org D-BUS specification. The I suspect that investigating those APIs further will also reveal some gaps in your capabilities research. For example: Take the code snippet from the Stack Overflow macOS example:
That indicates that on macOS, you have the option for:
and the app can respond to that action. An icon isn't part of that example; but looking at docs, there's support for a (I'll also note that the Apple documentation suggests that NSUserNotification has been deprecated in favor of the UserNotifications framework, which appears to also work on iOS; however, it doesn't work on macOS before 10.14). So - which of those APIs are required? What in-practice limits exist to the length of text labels? The size of images? It's entirely understandable that you don't want to try and build everything at once - that's definitely a good idea; but we need to be sure that what we build now won't paint us into a corner later on. We need to be certain about what is absolutely required and what is optional. And If something is required on one platform but not another, what is our cross-platform story? Lastly - the OS limits you mention aren't a huge problem; but you mention Python 3.6 as a minimum version. Is there a technical reason for that limitation? Toga still supports Python 3.5; what feature/library necessary for this project isn't supported on Python 3.5? |
@freakboy3742 Thank you for the quick reply. This the current API layout/solution. Windows (testing phase): macOS (Building): Linux (Building): Currently, I am looking to build the project in parts as I have the whole summer and not to rush to push a defective code In the previous comment, I said python 3.6+ would be the OS-level registration requirement. As I want people to be on a stable version but technically this current solution should work with 3+. |
@yusuf8ahmed Before you start down a path of getting a C# implementation working for Windows, you may want to take a moment and look a the existing source of Toga. There's not a single line of C# in that codebase - it's all Python. We're using Python.net to bridge between Python and the .NET runtime. There shouldn't be any need for a C# codebase; and I'm unlikely to merge a patch that introduces one. As for Rubicon - I'm not sure what pointers you're looking for. Rubicon itself has fairly extensive documentation; but if you've got working PyObjC code, it should be a relatively straightforward transformation to get Rubicon working. You'll need to elaborate on the problems you're seeing or the conversion you don't understand. Pydbus might be a viable option on Linux - however it certainly wouldn't be my first choice. Firstly, it's a little concerning that it hasn't been updated in over 2 years. A 5 second Google search for "dbus python" revealed dbus-python, which describes itself as "the original Python binding for DBus", and has published versions as recently as January of this year. dbus-python also mentions GDBus as another option accessible through PyGI, which we already use. So - more research may be needed here. Also - before you get too deeply involved in implementations, you still need to present a design. There are still open questions about what features a "toast" API needs to have. |
@freakboy3742 Thank you for the quick response, I would be glad to present a design. Can you give me a quick overview of what you expect to see in it? C# is not included, there is only one .dll file. I specifically chose the dll file route as there is no other stable way to access the native toast API of Windows. I have tried and looked at many different ways such as: A dll is actually the most efficient to use as toga already uses Python for .NET which is need to load in the dll. To explain my rubicon-objc problem further I am having a problem accessing Apple App Service called UserNotifications specifically For Linux I 100% agree with you pydbus is not an option and that dbus-python is a way better option. Also are you able to send me more information on PyGI and GDBus. |
A proposal for an API. What methods will exist in the API? How will end-users access the API? And - you can't answer that question without addressing the original research question that I posed: what are the that a generic API needs to cover? You did some initial research, and I pointed out some gaps in that research - but you haven't addressed any of those gaps.
Yes, which is one more DLL than is currently shipped with the entire project. Do not underestimate the inherent complexity involved in "just" adding a DLL.
This is patently untrue. 5 minutes of Google research for "winforms notification API" lead me to the page on NotifyIcon.ShowBalloonTip; 5 minutes after that, I had the following Python code:
So no - a DLL is not the only option.
That... is not an explanation of anything. It's telling me the name of an Objective C class. It's not telling me:
or anything else that would allow me to help you.
I can't provide you with anything that can't be provided by Google. |
@yusuf8ahmed, if you would like to pointers on backend implementation for macOS and Linux, you can have a look at https://github.com/SamSchott/maestral/blob/master/maestral/utils/notify.py. Linux: This uses the dbus specification on Linux (through jeepney). python-gobject could be an alternative since toga already depends on it. macOS: This uses UNUserNotificationCenter on macOS (should also work on iOS) with a fallback to NSUserNotificationCenter on older releases. There is currently no implementation of buttons and callbacks when a notification is clicked, both would likely need some integration with an event loop. Of course, the API is very different from the toga APIs. But the backend should be helpful. |
Thank you very much |
Just for reference, I've recently recently released a Python library desktop_notifier for cross-platform desktop notifications, currently for Linux and macOS only. Features are:
The library is purely written in Python, with Python-only dependencies: it uses rubicon-objc on macOS and dbus-next on Linux. With toga, we could of course use python-gobject instead. Asyncio / event loop integration is used to react to user interaction with the notification. Regarding the API, it currently exposes only a single method, but this may be expanded in the future: from desktop_notifier import DesktopNotifier, NotificationLevel
notifier = DesktopNotifier(app_name="Sample App", notification_limit=10)
notifier.send(
title="Hello from Python!",
message="A horrible exception occured",
urgency=NotificationLevel.Critical,
icon="/path/to/icon.png",
action=lambda: print("notification clicked"),
buttons={
"Button 1": lambda: print("Button 1 clicked"),
"Button 2": lambda: print("Button 2 clicked"),
},
) For a toga API, I can see multiple options:
What do people think regarding the API? If there is some consensus, I'd be happy to work on a PR providing the core API and Linux + macOS implementations. |
I can contribute notifications for Android: |
@freakboy3742 Where would we place the notification code in Toga? |
How should we handle the icon? I think, it should be relatively easy to provide a default icon for every platform, probably the "info" icon or maybe (if I can find out how) the application icon of the beeware app. |
So - there isn't a system package at present, and I'm not sure what else you're anticipating being a "system" capability - but this seems (a) a much deeper package hierarchy than is needed ( I haven't done a whole lot of thinking about this beyond "this is something we need", so I can't say I have a well-thought-out API design in mind. @samschott's comment seems like a good starting point; my inclination is that we'd probably want to go with option (2) (or a variation similar to it -
... is there something wrong with
... is there something wrong with |
I'm thinking about clipboard access, power management (e.g. for keeping an Android app awake), permissions management.
For the Android notification, I need a resource ID (integer) to some compiled image. How do I get the resource ID of toga.App.icon? |
In Java you'd access the app's icon as |
@mhsmith I tried to use R.drawable.ic_launcher as Icon reference, but got following error: In Resources.getIdentifier(), I need to specify |
This might work as long as you're using the
"drawable" |
@mhsmith
|
hmm...but this works:
It seems that there really is no "ic_launcher" icon in the app, although I built it with a pretty recent briefcase (0.3.12).
|
@mhsmith So, we could use the application icon as default icon and let the user choose a custom icon using a string. |
Starting with Android 7.0, it is possible to use Icons built from a file as the notification's small icon. So, the icon parameter could be a file path for both, Windows and Android |
OK, Android 7.0 is BeeWare's minimum supported version anyway, and we want to encourage the programmer to write portable code, so how about this:
|
I'd suggest something slightly different (or, at least, in addition to this). Loading from file/data (same as Image) should be legal; but there's a third option of "system icon identifier". These are constants, and cover icons that are commonly provided by the system - the app icon, plus other utility icons like error, warning, info etc. These icons can be exposed as Icon.APP (although we might want to stick with toga.App.icon, rather than Icon.APP), Icon.ERROR, Icon.WARNING etc. Platforms can then choose how to satisfy those icon requirements - if Android needs to use a resource identifier, then that's an implementation detail, and only needs to be exposed in the backend API, not the public API. |
Yes, I like this idea. What data type would Icon.ERROR be? An Integer? |
I implemented Russel's suggestions regarding the icons in my tatogalib (only for Winforms, Android will follow): I would appreciate your comments on this implementation, so I can take those into account for my toga PR. Hmm...I just realized that AppIcon.ERROR is missing in the docs. I'll fix that soon. |
Why wouldn't it be
So - I'm only going off the documentation here, but: The API naming seems... verbose. In particular, why is there a I'm unclear what's going on with the It's also not clear why a NotificationManager class is needed; at an implementation layer, it might make sense, but as an exposed Python API this is something that should be handled with a singleton or Borg pattern, or something that is encompassed by attribute access. Lastly - in terms of the path forward into Toga itself; I'm not clear what you have in mind, but I'm unlikely to approve a PR that depends on |
I've just been reminded of #1890 - I'm not sure that discussion adds much more than what is here, but it's some more context. |
@freakboy3742 Thanks for your comments. I always learn a lot from your feedbacks. Of course I do not plan to create toga dependencies with tatogalib. My tatogalib library is meant for all the stuff that does not exist in toga. The fnLog / log is for debugging during development only. I will remove this in the PR. If I correctly understand you, we could implement the notifications similar to self.app.paths, right? So, we would then have a self.app.notifications member which would be an instance of NotificationManager (which we might still rename to something simpler) |
Yes - A |
Part of the current As for the permissions: I have not yet found out how to prompt the user for acceptance from within the app. So far, I started the app to have the channel created and then gave the permission "manually" in the app's Android settings. Maybe, we should use an explicit Or, Or, we go back to my original idea where the NotificationManager must explicitly be instanciated by the app if it wants to use notifications... |
Hmm...this is strange: The Windows notifications are displayed for a while and then, they disappear automatically. I would expect that I can still see them in the notification center, but this is not the case. At least, not anymore. They did stay when I still had the ExplorerPatcher for win11 installed. Now, after uninstalling ExplorerPatcher (and installing SystemTrayMenu), the notifications are shown, disappear automatically and are NOT in the notification center |
Most of the discussion above is related to Windows notification. May I know what is the best way to get, in a Toga generated App on Android (and later I would need also for MacOS), notifications in the mobile phone sent from a server and received by the phone ? Thanks |
At present, any implementation of notifications will be entirely platform-specific, invoking the platform-specific APIs to manifest a notification. |
I've played around with toga a little bit and it is amazing!
I'm building a personal app and I wanted the ability to create custom push notifications. I have the whole system built but I think this feature would be very beneficial for the broader toga community
I am willing to personally work on the PR for this feature. Can I get some guidance or advice on how to proceed? Appreciate it!
The text was updated successfully, but these errors were encountered: