├── .DS_Store
├── .gitignore
├── CHANGELOG.md
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── images
├── android-actions.png
├── android-chat.png
├── android-inbox.png
├── android-progress.png
├── android-reply-2.png
├── android-reply.png
├── android-stack.png
├── ios-actions.png
├── ios-basic.png
├── ios-permission.png
├── logo.png
└── windows-actions.png
├── package.json
├── plugin.xml
├── src
├── android
│ ├── ClearReceiver.java
│ ├── ClickReceiver.java
│ ├── LocalNotification.java
│ ├── RestoreReceiver.java
│ ├── TriggerReceiver.java
│ ├── build
│ │ └── localnotification.gradle
│ ├── notification
│ │ ├── Builder.java
│ │ ├── Manager.java
│ │ ├── Notification.java
│ │ ├── NotificationVolumeManager.java
│ │ ├── Options.java
│ │ ├── Request.java
│ │ ├── action
│ │ │ ├── Action.java
│ │ │ └── ActionGroup.java
│ │ ├── receiver
│ │ │ ├── AbstractClearReceiver.java
│ │ │ ├── AbstractClickReceiver.java
│ │ │ ├── AbstractNotificationReceiver.java
│ │ │ ├── AbstractRestoreReceiver.java
│ │ │ └── AbstractTriggerReceiver.java
│ │ ├── trigger
│ │ │ ├── DateTrigger.java
│ │ │ ├── IntervalTrigger.java
│ │ │ └── MatchTrigger.java
│ │ └── util
│ │ │ ├── AssetProvider.java
│ │ │ ├── AssetUtil.java
│ │ │ └── LaunchUtils.java
│ └── xml
│ │ └── localnotification_provider_paths.xml
├── ios
│ ├── APPLocalNotification.h
│ ├── APPLocalNotification.m
│ ├── APPNotificationCategory.h
│ ├── APPNotificationCategory.m
│ ├── APPNotificationContent.h
│ ├── APPNotificationContent.m
│ ├── APPNotificationOptions.h
│ ├── APPNotificationOptions.m
│ ├── UNNotificationRequest+APPLocalNotification.h
│ ├── UNNotificationRequest+APPLocalNotification.m
│ ├── UNUserNotificationCenter+APPLocalNotification.h
│ └── UNUserNotificationCenter+APPLocalNotification.m
└── windows
│ ├── LocalNotificationProxy.js
│ ├── LocalNotificationProxy
│ ├── .vs
│ │ └── LocalNotificationProxy
│ │ │ └── v15
│ │ │ └── .suo
│ ├── LocalNotificationProxy.sln
│ └── LocalNotificationProxy
│ │ ├── LocalNotification
│ │ ├── ActionGroup.cs
│ │ ├── Builder.cs
│ │ ├── Manager.cs
│ │ ├── Notification.cs
│ │ ├── Options.cs
│ │ ├── Request.cs
│ │ ├── Toast
│ │ │ ├── Button.cs
│ │ │ ├── Every.cs
│ │ │ ├── IAction.cs
│ │ │ ├── Input.cs
│ │ │ ├── ProgressBar.cs
│ │ │ └── Trigger.cs
│ │ └── Trigger
│ │ │ ├── DateTrigger.cs
│ │ │ ├── IntervalTrigger.cs
│ │ │ └── MatchTrigger.cs
│ │ ├── LocalNotificationProxy.cs
│ │ ├── LocalNotificationProxy.csproj
│ │ └── Properties
│ │ └── AssemblyInfo.cs
│ └── lib.UW
│ ├── ARM
│ ├── LocalNotificationProxy.winmd
│ └── Microsoft.Toolkit.Uwp.Notifications.dll
│ ├── x64
│ ├── LocalNotificationProxy.winmd
│ └── Microsoft.Toolkit.Uwp.Notifications.dll
│ └── x86
│ ├── LocalNotificationProxy.winmd
│ └── Microsoft.Toolkit.Uwp.Notifications.dll
└── www
└── local-notification.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /src/windows.old
2 | /src/windows/Microsoft.Toolkit.Uwp.Notifications.*
3 | /src/windows/**/.vs
4 | /src/windows/**/bin
5 | /src/windows/**/obj
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ChangeLog
2 | ---------
3 |
4 | #### Version 0.9.0-beta.4
5 | - Platform enhancements
6 | - Android 8-10 device support
7 | - Android 10 SDK support (using androidx libraries rather than support libraries)
8 | - Note: If you are not building with API 29 on Android, you can use https://www.npmjs.com/package/cordova-plugin-androidx for backwards compatibility.
9 | - Enhancements (Android)
10 | - Adjusted high priority notifications to fire at more exact time.
11 | - use setAlarmClock() rather than setExactAndAllowWhileIdle().
12 | - New `autoLaunch` attribute.
13 | - Notification launches application if closed (Android <= 9).
14 | - App has the option to run some logic and schedule (or not schedule) an immediate alarm.
15 | - Note, this will be overridden if fullScreenIntent is true. Doing that will use the fullScreenIntent behavior and not always autoLaunch.
16 | - Also note, this feature can cause alarms to not always fire on time.
17 | - New `alarmVolume` attribute. Can force application to increase device notification volume prior to playing sound.
18 | - New `resetDelay` attribute. Delay to reset alarmVolume on the device back to its original settings
19 | - New `wakeLockTimeout` attribute. Can be used to extend the wakelock to keep the device awake longer (in case an autoLaunch application trigger takes a while).
20 | - New `triggerInApp` attribute.
21 | - If set to true, notification will not fire. Instead it will fire a trigger event that can be listened to in the app.
22 | - This allows you to evaluate the notification in the application, and if you decide to fire it, you can remove the trigger, remove triggerInApp, and schedule it. (It should fire immediately).
23 | - This was previously coupled with autoLaunch, but I split it out for more flexibility.
24 | - Listening to the event can be done as follows:
25 |
26 | `window.cordova.plugins.notification.local.on('trigger', (notification) => {
27 | // do something with notification
28 | });`
29 |
30 | - Note: this functionality will be skipped (alarms will fire immediately with no trigger method) if any of the following are true:
31 | - Android 8+ is asleep and the app is not running (even if autoLaunch is true). As a timely execution of the app code can't be guaranteed in this state, the notification will fire immediately.
32 | - The app is not running and autoLaunch is false (any Android version). If the app is not running, we can't execute its code, so fire immediately.
33 | - New `fullScreenIntent` attribute.
34 | - If set to true, will use fullScreenIntent in AlarmManager to launch application.
35 | - Setting this to true will negate autoLaunch, and is the only way to automatically launch the app on Android 10+.
36 | - Note: OS/manufacturer has some options for how to deal with this configuration. It will not always launch the activity, but typically will launch it if the device is asleep and show a heads-up notification if it is not.
37 | - **Android Channel Support**
38 | - New `channelName` attribute for the name of the notification channel to use
39 | - New `channelId` attribute. If passed in, a notification channel will be created (using volume and vibration settings to determine importance)
40 | - Android: Support for excluding an application from battery optimization settings.
41 | - Android: Support for allowing an application permissions to override Do Not Disturb.
42 | - iOS: No longer remove notification from notification bar when alarms are rescheduled. Call cancel() explicitly to retain this behavior.
43 |
44 | ---
45 |
46 | Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information.
47 |
48 | #### Version 0.8.5 (22.05.2017)
49 | - iOS 10
50 |
51 | #### Version 0.8.4 (04.01.2016)
52 | - Bug fixes
53 | - SyntaxError: missing ) after argument list
54 |
55 | #### Version 0.8.3 (03.01.2016)
56 | - Platform enhancements
57 | - Support for the `Crosswalk Engine`
58 | - Support for `cordova-ios@4` and the `WKWebView Engine`
59 | - Support for `cordova-windows@4` and `Windows 10` without using hooks
60 | - Enhancements
61 | - New `color` attribute for Android (Thanks to @Eusebius1920)
62 | - New `quarter` intervall for iOS & Android
63 | - `smallIcon` is optional (Android)
64 | - `update` checks for permission like _schedule_
65 | - Decreased time-frame for trigger event (iOS)
66 | - Force `every:` to be a string on iOS
67 | - Bug fixes
68 | - Fixed #634 option to skip permission check
69 | - Fixed #588 crash when basename & extension can't be extracted (Android)
70 | - Fixed #732 loop between update and trigger (Android)
71 | - Fixed #710 crash due to >500 notifications (Android)
72 | - Fixed #682 crash while resuming app from notification (Android 6)
73 | - Fixed #612 cannot update icon or sound (Android)
74 | - Fixed crashing get(ID) if notification doesn't exist
75 | - Fixed #569 getScheduled returns two items per notification
76 | - Fixed #700 notifications appears on bootup
77 |
78 | #### Version 0.8.2 (08.11.2015)
79 | - Submitted to npm
80 | - Initial support for the `windows` platform
81 | - Re-add autoCancel option on Android
82 | - Warn about unknown properties
83 | - Fix crash on iOS 9
84 | - Fixed webView-Problems with cordova-android 4.0
85 | - Fix get* with single id
86 | - Fix issue when passing data in milliseconds
87 | - Update device plugin id
88 | - Several other fixes
89 |
90 | #### Version 0.8.1 (08.03.2015)
91 |
92 | - Fix incompatibility with cordova version 3.5-3.0
93 | - Fire `clear` instead of `cancel` event when clicked on repeating notifications
94 | - Do not fire `clear` or `cancel` event when clicked on persistent notifications
95 |
96 | ### Version 0.8.0 (05.03.2015)
97 |
98 | - Support for iOS 8, Android 2 (SDK >= 7) and Android 5
99 | - Windows Phone 8.1 will be added soon
100 | - New interfaces to ask for / register permissions required to schedule local notifications
101 | - `hasPermission()` and `registerPermission()`
102 | - _schedule()_ will register the permission automatically and schedule the notification if granted.
103 | - New interface to update already scheduled|triggered local notifications
104 | - `update()`
105 | - New interfaces to clear the notification center
106 | - `clear()` and `clearAll()`
107 | - New interfaces to query for local notifications, their properties, their IDs and their existence depend on their state
108 | - `isPresent()`, `isScheduled()`, `isTriggered()`
109 | - `getIds()`, `getAllIds()`, `getScheduledIds()`, `getTriggeredIds()`
110 | - `get()`, `getAll()`, `getScheduled()`, `getTriggered()`
111 | - Schedule multiple local notifications at once
112 | - `schedule( [{...},{...}] )`
113 | - Update multiple local notifications at once
114 | - `update( [{...},{...}] )`
115 | - Clear multiple local notifications at once
116 | - `clear( [1, 2] )`
117 | - Cancel multiple local notifications at once
118 | - `cancel( [1, 2] )`
119 | - New URI format to specify sound and image resources
120 | - `http(s):` for remote resources _(Android)_
121 | - `file:` for local resources relative to the _www_ folder
122 | - `res:` for native resources
123 | - New events
124 | - `schedule`, `update`, `clear`, `clearall` and `cancelall`
125 | - Enhanced event informations
126 | - Listener will get called with the local notification object instead of only the ID
127 | - Multiple listener for one event
128 | - `on(event, callback, scope)`
129 | - Unregister event listener
130 | - `un(event, callback)`
131 | - New Android specific properties
132 | - `led` properties
133 | - `sound` and `image` accepts remote resources
134 | - Callback function and scope for all interface methods
135 | - `schedule( notification, callback, scope )`
136 | - Renamed `add()` to `schedule()`
137 | - `autoCancel` property has been removed
138 | - Use `ongoing: true` for persistent local notifications on Android
139 | - Renamed repeat intervals
140 | - `second`, `minute`, `hour`, `day`, `week`, `month` and `year`
141 | - Renamed some local notification properties
142 | - `date`, `json`, `message` and `repeat`
143 | - Scheduling local notifications with the deprecated properties is still possible
144 | - [Kitchen Sink sample app](https://github.com/katzer/cordova-plugin-local-notifications/tree/example)
145 | - [Wiki](https://github.com/katzer/cordova-plugin-local-notifications/wiki)
146 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **WARNING: IF YOU IGNORE THIS TEMPLATE, WE'LL IGNORE YOUR ISSUE. YOU MUST FILL THIS IN!**
2 |
3 | Provide a general summary of the issue.
4 |
5 | ## Your Environment
6 |
7 | * Plugin version:
8 | * Platform:
9 | * OS version:
10 | * Device manufacturer / model:
11 | * Cordova version (```cordova -v```):
12 | * Cordova platform version (```cordova platform ls```):
13 | * Plugin config
14 | * Ionic Version (if using Ionic)
15 |
16 | ## Expected Behavior
17 |
18 | _Tell us what should happen_
19 |
20 | ## Actual Behavior
21 |
22 | _Tell us what happens instead_
23 |
24 | ## Steps to Reproduce
25 |
26 | _Reproduce this issue; include code to reproduce, if relevant_
27 |
28 | 1. ...
29 | 2. ...
30 | 3. ...
31 | 4. ....
32 |
33 | ## Context
34 |
35 | _What were you trying to do?_
36 |
37 | ## Debug logs
38 |
39 | _Include iOS / Android logs_
40 |
41 | * ios XCode logs
42 | * Android: $ adb logcat
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2013 appPlant GmbH
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/images/android-actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-actions.png
--------------------------------------------------------------------------------
/images/android-chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-chat.png
--------------------------------------------------------------------------------
/images/android-inbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-inbox.png
--------------------------------------------------------------------------------
/images/android-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-progress.png
--------------------------------------------------------------------------------
/images/android-reply-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-reply-2.png
--------------------------------------------------------------------------------
/images/android-reply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-reply.png
--------------------------------------------------------------------------------
/images/android-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/android-stack.png
--------------------------------------------------------------------------------
/images/ios-actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/ios-actions.png
--------------------------------------------------------------------------------
/images/ios-basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/ios-basic.png
--------------------------------------------------------------------------------
/images/ios-permission.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/ios-permission.png
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/logo.png
--------------------------------------------------------------------------------
/images/windows-actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/images/windows-actions.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova-plugin-local-notification",
3 | "version": "0.9.0-beta.4",
4 | "description": "Schedules and queries for local notifications",
5 | "cordova": {
6 | "id": "cordova-plugin-local-notification",
7 | "platforms": [
8 | "android",
9 | "ios",
10 | "windows"
11 | ]
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/katzer/cordova-plugin-local-notifications.git"
16 | },
17 | "keywords": [
18 | "appplant",
19 | "notification",
20 | "local notification",
21 | "user notification",
22 | "ecosystem:cordova",
23 | "cordova-ios",
24 | "cordova-android",
25 | "cordova-windows"
26 | ],
27 | "engines": [
28 | {
29 | "name": "cordova",
30 | "version": ">=3.6.0"
31 | },
32 | {
33 | "name": "cordova-android",
34 | "version": ">=6.0.0"
35 | },
36 | {
37 | "name": "cordova-windows",
38 | "version": ">=4.2.0"
39 | },
40 | {
41 | "name": "android-sdk",
42 | "version": ">=26"
43 | },
44 | {
45 | "name": "apple-ios",
46 | "version": ">=10.0.0"
47 | }
48 | ],
49 | "author": "Sebastián Katzer",
50 | "license": "Apache 2.0",
51 | "bugs": {
52 | "url": "https://github.com/katzer/cordova-plugin-local-notifications/issues"
53 | },
54 | "homepage": "https://github.com/katzer/cordova-plugin-local-notifications#readme"
55 | }
56 |
--------------------------------------------------------------------------------
/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
24 |
28 |
29 | LocalNotification
30 |
31 | Schedules and queries for local notifications
32 |
33 | https://github.com/katzer/cordova-plugin-local-notifications.git
34 |
35 | appplant, notification, local notification, user notification
36 |
37 | Apache 2.0
38 |
39 | Sebastián Katzer
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
109 |
112 |
113 |
114 |
117 |
118 |
121 |
122 |
125 |
126 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
146 |
147 |
150 |
151 |
154 |
155 |
158 |
159 |
162 |
163 |
166 |
167 |
170 |
171 |
174 |
175 |
178 |
179 |
182 |
183 |
186 |
187 |
190 |
191 |
194 |
195 |
198 |
199 |
202 |
203 |
206 |
207 |
210 |
211 |
214 |
215 |
218 |
219 |
222 |
223 |
226 |
227 |
230 |
231 |
234 |
235 |
238 |
239 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
--------------------------------------------------------------------------------
/src/android/ClearReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.localnotification;
23 |
24 | import android.os.Bundle;
25 |
26 | import de.appplant.cordova.plugin.notification.Notification;
27 | import de.appplant.cordova.plugin.notification.receiver.AbstractClearReceiver;
28 |
29 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent;
30 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isAppRunning;
31 | import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST;
32 |
33 | /**
34 | * The clear intent receiver is triggered when the user clears a
35 | * notification manually. It un-persists the cleared notification from the
36 | * shared preferences.
37 | */
38 | public class ClearReceiver extends AbstractClearReceiver {
39 |
40 | /**
41 | * Called when a local notification was cleared from outside of the app.
42 | *
43 | * @param notification Wrapper around the local notification.
44 | * @param bundle The bundled extras.
45 | */
46 | @Override
47 | public void onClear (Notification notification, Bundle bundle) {
48 | boolean isLast = bundle.getBoolean(EXTRA_LAST, false);
49 |
50 | if (isLast) {
51 | notification.cancel();
52 | } else {
53 | notification.clear();
54 | }
55 |
56 | if (isAppRunning()) {
57 | fireEvent("clear", notification);
58 | }
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/android/ClickReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.localnotification;
23 |
24 | import android.os.Bundle;
25 | import androidx.core.app.RemoteInput;
26 |
27 | import org.json.JSONException;
28 | import org.json.JSONObject;
29 |
30 | import de.appplant.cordova.plugin.notification.Notification;
31 | import de.appplant.cordova.plugin.notification.receiver.AbstractClickReceiver;
32 | import de.appplant.cordova.plugin.notification.util.LaunchUtils;
33 |
34 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent;
35 | import static de.appplant.cordova.plugin.notification.Options.EXTRA_LAUNCH;
36 | import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST;
37 |
38 | /**
39 | * The receiver activity is triggered when a notification is clicked by a user.
40 | * The activity calls the background callback and brings the launch intent
41 | * up to foreground.
42 | */
43 | public class ClickReceiver extends AbstractClickReceiver {
44 |
45 | /**
46 | * Called when local notification was clicked by the user.
47 | *
48 | * @param notification Wrapper around the local notification.
49 | * @param bundle The bundled extras.
50 | */
51 | @Override
52 | public void onClick(Notification notification, Bundle bundle) {
53 | String action = getAction();
54 | JSONObject data = new JSONObject();
55 |
56 | setTextInput(action, data);
57 | launchAppIf();
58 |
59 | fireEvent(action, notification, data);
60 |
61 | if (notification.getOptions().isSticky())
62 | return;
63 |
64 | if (isLast()) {
65 | notification.cancel();
66 | } else {
67 | notification.clear();
68 | }
69 | }
70 |
71 | /**
72 | * Set the text if any remote input is given.
73 | *
74 | * @param action The action where to look for.
75 | * @param data The object to extend.
76 | */
77 | private void setTextInput(String action, JSONObject data) {
78 | Bundle input = RemoteInput.getResultsFromIntent(getIntent());
79 |
80 | if (input == null)
81 | return;
82 |
83 | try {
84 | data.put("text", input.getCharSequence(action));
85 | } catch (JSONException e) {
86 | e.printStackTrace();
87 | }
88 | }
89 |
90 | /**
91 | * Launch app if requested by user.
92 | */
93 | private void launchAppIf() {
94 | boolean doLaunch = getIntent().getBooleanExtra(EXTRA_LAUNCH, true);
95 |
96 | if (!doLaunch)
97 | return;
98 |
99 | LaunchUtils.launchApp(getApplicationContext());
100 | }
101 |
102 | /**
103 | * If the notification was the last scheduled one by request.
104 | */
105 | private boolean isLast() {
106 | return getIntent().getBooleanExtra(EXTRA_LAST, false);
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/src/android/RestoreReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
3 | *
4 | * @APPPLANT_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPPLANT_LICENSE_HEADER_END@
22 | */
23 |
24 | package de.appplant.cordova.plugin.localnotification;
25 |
26 | import android.content.Context;
27 | import android.util.Log;
28 |
29 | import java.util.Date;
30 |
31 | import de.appplant.cordova.plugin.notification.Builder;
32 | import de.appplant.cordova.plugin.notification.Manager;
33 | import de.appplant.cordova.plugin.notification.Notification;
34 | import de.appplant.cordova.plugin.notification.Request;
35 | import de.appplant.cordova.plugin.notification.receiver.AbstractRestoreReceiver;
36 |
37 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent;
38 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isAppRunning;
39 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isInForeground;
40 |
41 | /**
42 | * This class is triggered upon reboot of the device. It needs to re-register
43 | * the alarms with the AlarmManager since these alarms are lost in case of
44 | * reboot.
45 | */
46 | public class RestoreReceiver extends AbstractRestoreReceiver {
47 | /**
48 | * Called when a local notification need to be restored.
49 | *
50 | * @param request Set of notification options.
51 | * @param toast Wrapper around the local notification.
52 | */
53 | @Override
54 | public void onRestore (Request request, Notification toast) {
55 | Date date = request.getTriggerDate();
56 | boolean after = date != null && date.after(new Date());
57 |
58 | if (!after && toast.isHighPrio()) {
59 | performNotification(toast);
60 | } else {
61 | // reschedule if we aren't firing here.
62 | // If we do fire, performNotification takes care of
63 | // next schedule.
64 |
65 | Context ctx = toast.getContext();
66 | Manager mgr = Manager.getInstance(ctx);
67 |
68 | if (after || toast.isRepeating()) {
69 | mgr.schedule(request, TriggerReceiver.class);
70 | }
71 | }
72 | }
73 |
74 | @Override
75 | public void dispatchAppEvent(String key, Notification notification) {
76 | fireEvent(key, notification);
77 | }
78 |
79 | @Override
80 | public boolean checkAppRunning() {
81 | return isAppRunning();
82 | }
83 |
84 | /**
85 | * Build notification specified by options.
86 | *
87 | * @param builder Notification builder.
88 | */
89 | @Override
90 | public Notification buildNotification (Builder builder) {
91 | return builder
92 | .setClickActivity(ClickReceiver.class)
93 | .setClearReceiver(ClearReceiver.class)
94 | .build();
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/android/TriggerReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.localnotification;
23 |
24 | import android.content.Context;
25 | import android.os.Bundle;
26 | import android.os.PowerManager;
27 |
28 | import java.util.Calendar;
29 |
30 | import de.appplant.cordova.plugin.notification.Builder;
31 | import de.appplant.cordova.plugin.notification.Manager;
32 | import de.appplant.cordova.plugin.notification.Notification;
33 | import de.appplant.cordova.plugin.notification.Options;
34 | import de.appplant.cordova.plugin.notification.Request;
35 | import de.appplant.cordova.plugin.notification.receiver.AbstractTriggerReceiver;
36 | import de.appplant.cordova.plugin.notification.util.LaunchUtils;
37 |
38 | import static android.content.Context.POWER_SERVICE;
39 | import static android.os.Build.VERSION.SDK_INT;
40 | import static android.os.Build.VERSION_CODES.LOLLIPOP;
41 | import static android.os.Build.VERSION_CODES.O;
42 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent;
43 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isAppRunning;
44 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isInForeground;
45 | import static java.util.Calendar.MINUTE;
46 |
47 | import static android.os.Build.VERSION_CODES.P;
48 |
49 | /**
50 | * The alarm receiver is triggered when a scheduled alarm is fired. This class
51 | * reads the information in the intent and displays this information in the
52 | * Android notification bar. The notification uses the default notification
53 | * sound and it vibrates the phone.
54 | */
55 | public class TriggerReceiver extends AbstractTriggerReceiver {
56 |
57 | /**
58 | * Called when a local notification was triggered. Does present the local
59 | * notification, re-schedule the alarm if necessary and fire trigger event.
60 | *
61 | * @param notification Wrapper around the local notification.
62 | * @param bundle The bundled extras.
63 | */
64 | @Override
65 | public void onTrigger(Notification notification, Bundle bundle) {
66 | performNotification(notification);
67 | }
68 |
69 | @Override
70 | public void dispatchAppEvent(String key, Notification notification) {
71 | fireEvent(key, notification);
72 | }
73 |
74 | @Override
75 | public boolean checkAppRunning() {
76 | return isAppRunning();
77 | }
78 |
79 | /**
80 | * Build notification specified by options.
81 | *
82 | * @param builder Notification builder.
83 | * @param bundle The bundled extras.
84 | */
85 | @Override
86 | public Notification buildNotification(Builder builder, Bundle bundle) {
87 | return builder.setClickActivity(ClickReceiver.class).setClearReceiver(ClearReceiver.class).setExtras(bundle)
88 | .build();
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/src/android/build/localnotification.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This file contains Original Code and/or Modifications of Original Code
3 | * as defined in and that are subject to the Apache License
4 | * Version 2.0 (the 'License'). You may not use this file except in
5 | * compliance with the License. Please obtain a copy of the License at
6 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
7 | * file.
8 | *
9 | * The Original Code and all software distributed under the License are
10 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
11 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
12 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
13 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
14 | * Please see the License for the specific language governing rights and
15 | * limitations under the License.
16 | */
17 |
18 | repositories {
19 | mavenCentral()
20 | jcenter()
21 | maven {
22 | url "https://maven.google.com"
23 | }
24 | }
25 |
26 | if (!project.ext.has('appShortcutBadgerVersion')) {
27 | ext.appShortcutBadgerVersion = '1.1.19'
28 | }
29 |
30 | dependencies {
31 | compile "me.leolin:ShortcutBadger:${appShortcutBadgerVersion}@aar"
32 | }
33 |
--------------------------------------------------------------------------------
/src/android/notification/NotificationVolumeManager.java:
--------------------------------------------------------------------------------
1 | package de.appplant.cordova.plugin.notification;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.NotificationManager;
5 | import android.content.Context;
6 | import android.content.SharedPreferences;
7 | import android.media.AudioManager;
8 | import android.util.Log;
9 |
10 | import java.util.Timer;
11 | import java.util.TimerTask;
12 |
13 | import static android.os.Build.VERSION.SDK_INT;
14 | import static android.os.Build.VERSION_CODES.M;
15 | import static java.lang.Thread.sleep;
16 |
17 | /**
18 | * Class to handle all notification volume changes
19 | */
20 | public class NotificationVolumeManager {
21 | /**
22 | * Amount of time to sleep while polling to see if all volume writers are closed.
23 | */
24 | final private int VOLUME_WRITER_POLLING_DURATION = 200;
25 |
26 | /**
27 | * Key for volume writer counter in shared preferences
28 | */
29 | final private String VOLUME_CONFIG_WRITER_COUNT_KEY = "volumeConfigWriterCount";
30 |
31 | /**
32 | * Tag for logs
33 | */
34 | final String TAG = "NotificationVolumeMgr";
35 |
36 | /**
37 | * Notification manager
38 | */
39 | private NotificationManager notificationManager;
40 |
41 | /**
42 | * Audio Manager
43 | */
44 | private AudioManager audioManager;
45 |
46 | /**
47 | * Shared preferences, used to store settings across processes
48 | */
49 | private SharedPreferences settings;
50 |
51 | /**
52 | * Options for the notification
53 | */
54 | private Options options;
55 |
56 | /**
57 | * Initialize the NotificationVolumeManager
58 | * @param context Application context
59 | */
60 | public NotificationVolumeManager (Context context, Options options) {
61 | this.settings = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
62 | this.notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
63 | this.audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
64 | this.options = options;
65 | }
66 |
67 | /**
68 | * Ensure that this is the only volume writer.
69 | * Wait until others have closed.
70 | * TODO: Better locking mechanism to ensure concurrency (file lock?)
71 | * @throws InterruptedException Throws an interrupted exception, required by sleep call.
72 | */
73 | @SuppressLint("ApplySharedPref")
74 | private void ensureOnlyVolumeWriter () throws InterruptedException {
75 | int writerCount = settings.getInt(VOLUME_CONFIG_WRITER_COUNT_KEY, 0) + 1;
76 | settings.edit().putInt(VOLUME_CONFIG_WRITER_COUNT_KEY, writerCount).commit();
77 |
78 | int resetDelay = options.getResetDelay();
79 | if (resetDelay == 0) {
80 | resetDelay = Options.DEFAULT_RESET_DELAY;
81 | }
82 |
83 | int resetDelayMs = resetDelay * 1000;
84 | int sleepTotal = 0;
85 |
86 | // Wait until we are the only writer left.
87 | while(writerCount > 1) {
88 | if (sleepTotal > resetDelayMs) {
89 | throw new InterruptedException("Volume writer timeout exceeded reset delay." +
90 | "Something must have gone wrong. Reset volume writer counts to 0 " +
91 | "and reset volume settings to user settings.");
92 | }
93 |
94 | sleep(VOLUME_WRITER_POLLING_DURATION);
95 | sleepTotal += VOLUME_WRITER_POLLING_DURATION;
96 |
97 | writerCount = settings.getInt(VOLUME_CONFIG_WRITER_COUNT_KEY, 0);
98 | }
99 | }
100 |
101 | /**
102 | * Remove one count from active volume writers. Used when writer is finished.
103 | */
104 | @SuppressLint("ApplySharedPref")
105 | private void decrementVolumeWriter () {
106 | int writerCount = settings.getInt(VOLUME_CONFIG_WRITER_COUNT_KEY, 0) - 1;
107 | settings.edit().putInt(VOLUME_CONFIG_WRITER_COUNT_KEY, Math.max(writerCount, 0)).commit();
108 | }
109 |
110 | /**
111 | * Reset volume writer counts to 0. To be used in error conditions.
112 | */
113 | @SuppressLint("ApplySharedPref")
114 | private void resetVolumeWriter () {
115 | settings.edit().putInt(VOLUME_CONFIG_WRITER_COUNT_KEY, 0).commit();
116 | }
117 |
118 | /**
119 | * Set the volume for our ringer
120 | * @param ringerMode ringer mode enum. Normal ringer or vibration.
121 | * @param volume volume.
122 | */
123 | private void setVolume (int ringerMode, int volume) {
124 | // After delay, user could have set phone to do not disturb.
125 | // If so and we can't change the ringer, quit so we don't create an error condition
126 | if (canChangeRinger()) {
127 | // Change ringer mode
128 | audioManager.setRingerMode(ringerMode);
129 |
130 | // Change to new Volume
131 | audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, volume, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
132 | }
133 | }
134 |
135 | /**
136 | * Set the volume to the last user settings from shared preferences.
137 | */
138 | private void setVolumeToUserSettings () {
139 | int ringMode = settings.getInt("userRingerMode", -1);
140 | int volume = settings.getInt("userVolume", -1);
141 |
142 | setVolume(ringMode, volume);
143 | }
144 |
145 | /**
146 | * Figure out if we can change the ringer.
147 | * In Android M+, we can't change out of do not disturb if we don't have explicit permission.
148 | * @return whether or not we can change the ringer.
149 | */
150 | private boolean canChangeRinger() {
151 | return SDK_INT < M || notificationManager.isNotificationPolicyAccessGranted()
152 | || audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT;
153 | }
154 |
155 | /**
156 | * Adjusts alarm Volume
157 | * Options object. Contains our volume, reset and vibration settings.
158 | */
159 | @SuppressLint("ApplySharedPref")
160 | public void adjustAlarmVolume () {
161 | Integer volume = options.getVolume();
162 |
163 | if (volume.equals(Options.VOLUME_NOT_SET) || !canChangeRinger()) {
164 | return;
165 | }
166 |
167 | try {
168 | ensureOnlyVolumeWriter();
169 |
170 | boolean vibrate = options.isWithVibration();
171 |
172 | int delay = options.getResetDelay();
173 |
174 | if (delay <= 0) {
175 | delay = Options.DEFAULT_RESET_DELAY;
176 | }
177 |
178 | // Count of all alarms currently sounding
179 | Integer count = settings.getInt("alarmCount", 0);
180 | settings.edit().putInt("alarmCount", count + 1).commit();
181 |
182 | // Get current phone volume
183 | int userVolume = audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
184 |
185 | // Get Ringer mode
186 | int userRingerMode = audioManager.getRingerMode();
187 |
188 | // If this is the first alarm store the users ringer and volume settings
189 | if (count.equals(0)) {
190 | settings.edit().putInt("userVolume", userVolume).apply();
191 | settings.edit().putInt("userRingerMode", userRingerMode).apply();
192 | }
193 |
194 | // Calculates a new volume based on the study configure volume percentage and the devices max volume integer
195 | if (volume > 0) {
196 | // Gets devices max volume integer
197 | int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION);
198 |
199 | // Calculates new volume based on devices max volume
200 | double newVolume = Math.ceil(maxVolume * (volume / 100.00));
201 |
202 | setVolume(AudioManager.RINGER_MODE_NORMAL, (int) newVolume);
203 | } else {
204 | // Volume of 0
205 | if (vibrate) {
206 | // Change mode to vibrate
207 | setVolume(AudioManager.RINGER_MODE_VIBRATE, 0);
208 | }
209 | }
210 |
211 | // Timer to change users sound back
212 | Timer timer = new Timer();
213 | timer.schedule(new TimerTask() {
214 | public void run() {
215 | int currentCount = settings.getInt("alarmCount", 0);
216 | currentCount = Math.max(currentCount - 1, 0);
217 | settings.edit().putInt("alarmCount", currentCount).apply();
218 |
219 | if (currentCount == 0) {
220 | setVolumeToUserSettings();
221 | }
222 | }
223 | }, delay * 1000);
224 | } catch (InterruptedException e) {
225 | Log.e(TAG, "interrupted waiting for volume set. "
226 | + "Reset to user setting, and set counts to 0: " + e.toString());
227 | resetVolumeWriter();
228 | setVolumeToUserSettings();
229 | } finally {
230 | decrementVolumeWriter();
231 | }
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/src/android/notification/Request.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
3 | *
4 | * @APPPLANT_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPPLANT_LICENSE_HEADER_END@
22 | */
23 |
24 | package de.appplant.cordova.plugin.notification;
25 |
26 | import org.json.JSONObject;
27 |
28 | import java.util.Arrays;
29 | import java.util.Calendar;
30 | import java.util.Date;
31 | import java.util.List;
32 |
33 | import de.appplant.cordova.plugin.notification.trigger.DateTrigger;
34 | import de.appplant.cordova.plugin.notification.trigger.IntervalTrigger;
35 | import de.appplant.cordova.plugin.notification.trigger.MatchTrigger;
36 |
37 | import static de.appplant.cordova.plugin.notification.trigger.IntervalTrigger.Unit;
38 |
39 | /**
40 | * An object you use to specify a notification’s content and the condition
41 | * that triggers its delivery.
42 | */
43 | public final class Request {
44 |
45 | // Key name for bundled extras
46 | static final String EXTRA_OCCURRENCE = "NOTIFICATION_OCCURRENCE";
47 |
48 | // Key name for bundled extras
49 | public static final String EXTRA_LAST = "NOTIFICATION_LAST";
50 |
51 | // The options spec
52 | private final Options options;
53 |
54 | // The right trigger for the options
55 | private final DateTrigger trigger;
56 |
57 | // How often the trigger shall occur
58 | private final int count;
59 |
60 | // The trigger spec
61 | private final JSONObject spec;
62 |
63 | // The current trigger date
64 | private Date triggerDate;
65 |
66 | /**
67 | * Create a request with a base date specified through the passed options.
68 | *
69 | * @param options The options spec.
70 | */
71 | public Request(Options options) {
72 | this.options = options;
73 | this.spec = options.getTrigger();
74 | this.count = Math.max(spec.optInt("count"), 1);
75 | this.trigger = buildTrigger();
76 | this.triggerDate = trigger.getNextTriggerDate(getBaseDate());
77 | }
78 |
79 | /**
80 | * Create a request with a base date specified via base argument.
81 | *
82 | * @param options The options spec.
83 | * @param base The base date from where to calculate the next trigger.
84 | */
85 | public Request(Options options, Date base) {
86 | this.options = options;
87 | this.spec = options.getTrigger();
88 | this.count = Math.max(spec.optInt("count"), 1);
89 | this.trigger = buildTrigger();
90 | this.triggerDate = trigger.getNextTriggerDate(base);
91 | }
92 |
93 | /**
94 | * Gets the options spec.
95 | */
96 | public Options getOptions() {
97 | return options;
98 | }
99 |
100 | /**
101 | * The identifier for the request.
102 | *
103 | * @return The notification ID as the string
104 | */
105 | String getIdentifier() {
106 | return options.getId().toString() + "-" + getOccurrence();
107 | }
108 |
109 | /**
110 | * The value of the internal occurrence counter.
111 | */
112 | int getOccurrence() {
113 | return trigger.getOccurrence();
114 | }
115 |
116 | /**
117 | * If there's one more trigger date to calculate.
118 | */
119 | private boolean hasNext() {
120 | return triggerDate != null && getOccurrence() <= count;
121 | }
122 |
123 | /**
124 | * Moves the internal occurrence counter by one.
125 | */
126 | boolean moveNext() {
127 | if (hasNext()) {
128 | triggerDate = getNextTriggerDate();
129 | } else {
130 | triggerDate = null;
131 | }
132 |
133 | return this.triggerDate != null;
134 | }
135 |
136 | /**
137 | * Gets the current trigger date.
138 | *
139 | * @return null if there's no trigger date.
140 | */
141 | public Date getTriggerDate() {
142 | Calendar now = Calendar.getInstance();
143 |
144 | if (triggerDate == null)
145 | return null;
146 |
147 | long time = triggerDate.getTime();
148 |
149 | if ((now.getTimeInMillis() - time) > 60000)
150 | return null;
151 |
152 | if (time >= spec.optLong("before", time + 1))
153 | return null;
154 |
155 | return triggerDate;
156 | }
157 |
158 | /**
159 | * Gets the next trigger date based on the current trigger date.
160 | */
161 | private Date getNextTriggerDate() {
162 | return trigger.getNextTriggerDate(triggerDate);
163 | }
164 |
165 | /**
166 | * Build the trigger specified in options.
167 | */
168 | private DateTrigger buildTrigger() {
169 | Object every = spec.opt("every");
170 |
171 | if (every instanceof JSONObject) {
172 | List cmp1 = getMatchingComponents();
173 | List cmp2 = getSpecialMatchingComponents();
174 |
175 | return new MatchTrigger(cmp1, cmp2);
176 | }
177 |
178 | Unit unit = getUnit();
179 | int ticks = getTicks();
180 |
181 | return new IntervalTrigger(ticks, unit);
182 | }
183 |
184 | /**
185 | * Gets the unit value.
186 | */
187 | private Unit getUnit() {
188 | Object every = spec.opt("every");
189 | String unit = "SECOND";
190 |
191 | if (spec.has("unit")) {
192 | unit = spec.optString("unit", "second");
193 | } else
194 | if (every instanceof String) {
195 | unit = spec.optString("every", "second");
196 | }
197 |
198 | return Unit.valueOf(unit.toUpperCase());
199 | }
200 |
201 | /**
202 | * Gets the tick value.
203 | */
204 | private int getTicks() {
205 | Object every = spec.opt("every");
206 | int ticks = 0;
207 |
208 | if (spec.has("at")) {
209 | ticks = 0;
210 | } else
211 | if (spec.has("in")) {
212 | ticks = spec.optInt("in", 0);
213 | } else
214 | if (every instanceof String) {
215 | ticks = 1;
216 | } else
217 | if (!(every instanceof JSONObject)) {
218 | ticks = spec.optInt("every", 0);
219 | }
220 |
221 | return ticks;
222 | }
223 |
224 | /**
225 | * Gets an array of all date parts to construct a datetime instance.
226 | *
227 | * @return [min, hour, day, month, year]
228 | */
229 | private List getMatchingComponents() {
230 | JSONObject every = spec.optJSONObject("every");
231 |
232 | return Arrays.asList(
233 | (Integer) every.opt("minute"),
234 | (Integer) every.opt("hour"),
235 | (Integer) every.opt("day"),
236 | (Integer) every.opt("month"),
237 | (Integer) every.opt("year")
238 | );
239 | }
240 |
241 | /**
242 | * Gets an array of all date parts to construct a datetime instance.
243 | *
244 | * @return [min, hour, day, month, year]
245 | */
246 | private List getSpecialMatchingComponents() {
247 | JSONObject every = spec.optJSONObject("every");
248 |
249 | return Arrays.asList(
250 | (Integer) every.opt("weekday"),
251 | (Integer) every.opt("weekdayOrdinal"),
252 | (Integer) every.opt("weekOfMonth"),
253 | (Integer) every.opt("quarter")
254 | );
255 | }
256 |
257 | /**
258 | * Gets the base date from where to calculate the next trigger date.
259 | */
260 | private Date getBaseDate() {
261 | if (spec.has("requestBaseDate")) {
262 | return new Date(spec.optLong("requestBaseDate"));
263 | } else
264 | if (spec.has("at")) {
265 | return new Date(spec.optLong("at", 0));
266 | } else
267 | if (spec.has("firstAt")) {
268 | return new Date(spec.optLong("firstAt", 0));
269 | } else
270 | if (spec.has("after")) {
271 | return new Date(spec.optLong("after", 0));
272 | } else {
273 | return new Date();
274 | }
275 | }
276 |
277 | }
278 |
--------------------------------------------------------------------------------
/src/android/notification/action/Action.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.action;
23 |
24 | import android.content.Context;
25 | import androidx.core.app.RemoteInput;
26 |
27 | import org.json.JSONArray;
28 | import org.json.JSONObject;
29 |
30 | import de.appplant.cordova.plugin.notification.util.AssetUtil;
31 |
32 | /**
33 | * Holds the icon and title components that would be used in a
34 | * NotificationCompat.Action object. Does not include the PendingIntent so
35 | * that it may be generated each time the notification is built. Necessary to
36 | * compensate for missing functionality in the support library.
37 | */
38 | public final class Action {
39 |
40 | // Key name for bundled extras
41 | public static final String EXTRA_ID = "NOTIFICATION_ACTION_ID";
42 |
43 | // The id for the click action
44 | public static final String CLICK_ACTION_ID = "click";
45 |
46 | // The application context
47 | private final Context context;
48 |
49 | // The action spec
50 | private final JSONObject options;
51 |
52 | /**
53 | * Structure to encapsulate a named action that can be shown as part of
54 | * this notification.
55 | *
56 | * @param context The application context.
57 | * @param options The action options.
58 | */
59 | Action (Context context, JSONObject options) {
60 | this.context = context;
61 | this.options = options;
62 | }
63 |
64 | /**
65 | * Gets the ID for the action.
66 | */
67 | public String getId() {
68 | return options.optString("id", getTitle());
69 | }
70 |
71 | /**
72 | * Gets the Title for the action.
73 | */
74 | public String getTitle() {
75 | return options.optString("title", "unknown");
76 | }
77 |
78 | /**
79 | * Gets the icon for the action.
80 | */
81 | public int getIcon() {
82 | AssetUtil assets = AssetUtil.getInstance(context);
83 | String resPath = options.optString("icon");
84 | int resId = assets.getResId(resPath);
85 |
86 | if (resId == 0) {
87 | resId = android.R.drawable.screen_background_dark;
88 | }
89 |
90 | return resId;
91 | }
92 |
93 | /**
94 | * Gets the value of the launch flag.
95 | */
96 | public boolean isLaunchingApp() {
97 | return options.optBoolean("launch", false);
98 | }
99 |
100 | /**
101 | * Gets the type for the action.
102 | */
103 | public boolean isWithInput() {
104 | String type = options.optString("type");
105 | return type.equals("input");
106 | }
107 |
108 | /**
109 | * Gets the input config in case of the action is of type input.
110 | */
111 | public RemoteInput getInput() {
112 | return new RemoteInput.Builder(getId())
113 | .setLabel(options.optString("emptyText"))
114 | .setAllowFreeFormInput(options.optBoolean("editable", true))
115 | .setChoices(getChoices())
116 | .build();
117 | }
118 |
119 | /**
120 | * List of possible choices for input actions.
121 | */
122 | private String[] getChoices() {
123 | JSONArray opts = options.optJSONArray("choices");
124 |
125 | if (opts == null)
126 | return null;
127 |
128 | String[] choices = new String[opts.length()];
129 |
130 | for (int i = 0; i < choices.length; i++) {
131 | choices[i] = opts.optString(i);
132 | }
133 |
134 | return choices;
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/src/android/notification/action/ActionGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.action;
23 |
24 | import android.content.Context;
25 | import android.util.Log;
26 |
27 | import org.json.JSONArray;
28 | import org.json.JSONObject;
29 |
30 | import java.util.ArrayList;
31 | import java.util.HashMap;
32 | import java.util.List;
33 | import java.util.Map;
34 |
35 | import static android.os.Build.VERSION.SDK_INT;
36 | import static android.os.Build.VERSION_CODES.N;
37 |
38 | public final class ActionGroup {
39 |
40 | // Saves all groups for later lookup.
41 | private static final Map groups = new HashMap();
42 |
43 | // The ID of the action group.
44 | private final String id;
45 |
46 | // List of actions
47 | private final Action[] actions;
48 |
49 | /**
50 | * Lookup the action groups with the specified group id.
51 | *
52 | * @param id The ID of the action group to find.
53 | *
54 | * @return Null if no group was found.
55 | */
56 | public static ActionGroup lookup(String id) {
57 | return groups.get(id);
58 | }
59 |
60 | /**
61 | * Register the action group for later lookup.
62 | *
63 | * @param group The action group to register.
64 | */
65 | public static void register (ActionGroup group) {
66 | groups.put(group.getId(), group);
67 | }
68 |
69 | /**
70 | * Unregister the action group.
71 | *
72 | * @param id The id of the action group to remove.
73 | */
74 | public static void unregister (String id) {
75 | groups.remove(id);
76 | }
77 |
78 | /**
79 | * Check if a action group with that id is registered.
80 | *
81 | * @param id The id of the action group to check for.
82 | */
83 | public static boolean isRegistered (String id) {
84 | return groups.containsKey(id);
85 | }
86 |
87 | /**
88 | * Creates an action group by parsing the specified action specs.
89 | *
90 | * @param list The list of actions.
91 | *
92 | * @return A new action group.
93 | */
94 | public static ActionGroup parse (Context context, JSONArray list) {
95 | return parse(context, null, list);
96 | }
97 |
98 | /**
99 | * Creates an action group by parsing the specified action specs.
100 | *
101 | * @param id The id for the action group.
102 | * @param list The list of actions.
103 | *
104 | * @return A new action group.
105 | */
106 | public static ActionGroup parse (Context context, String id, JSONArray list) {
107 | List actions = new ArrayList(list.length());
108 |
109 | for (int i = 0; i < list.length(); i++) {
110 | JSONObject opts = list.optJSONObject(i);
111 | String type = opts.optString("type", "button");
112 |
113 | if (type.equals("input") && SDK_INT < N) {
114 | Log.w("Action", "Type input is not supported");
115 | continue;
116 | }
117 |
118 | if (!(type.equals("button") || type.equals("input"))) {
119 | Log.w("Action", "Unknown type: " + type);
120 | continue;
121 | }
122 |
123 | actions.add(new Action(context, opts));
124 | }
125 |
126 | return new ActionGroup(id, actions.toArray(new Action[actions.size()]));
127 | }
128 |
129 | /**
130 | * Creates an action group.
131 | *
132 | * @param id The ID of the group.
133 | * @param actions The list of actions.
134 | */
135 | private ActionGroup(String id, Action[] actions) {
136 | this.id = id;
137 | this.actions = actions;
138 | }
139 |
140 | /**
141 | * Gets the action group id.
142 | */
143 | public String getId() {
144 | return id;
145 | }
146 |
147 | /**
148 | * Gets the action list.
149 | */
150 | public Action[] getActions() {
151 | return actions;
152 | }
153 |
154 | }
--------------------------------------------------------------------------------
/src/android/notification/receiver/AbstractClearReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.receiver;
23 |
24 | import android.content.BroadcastReceiver;
25 | import android.content.Context;
26 | import android.content.Intent;
27 | import android.os.Bundle;
28 |
29 | import de.appplant.cordova.plugin.notification.Manager;
30 | import de.appplant.cordova.plugin.notification.Notification;
31 |
32 | /**
33 | * Abstract delete receiver for local notifications. Creates the local
34 | * notification and calls the event functions for further proceeding.
35 | */
36 | abstract public class AbstractClearReceiver extends BroadcastReceiver {
37 |
38 | /**
39 | * Called when the notification was cleared from the notification center.
40 | *
41 | * @param context Application context
42 | * @param intent Received intent with content data
43 | */
44 | @Override
45 | public void onReceive(Context context, Intent intent) {
46 | Bundle bundle = intent.getExtras();
47 |
48 | if (bundle == null)
49 | return;
50 |
51 | int toastId = bundle.getInt(Notification.EXTRA_ID);
52 | Notification toast = Manager.getInstance(context).get(toastId);
53 |
54 | if (toast == null)
55 | return;
56 |
57 | onClear(toast, bundle);
58 | }
59 |
60 | /**
61 | * Called when a local notification was cleared from outside of the app.
62 | *
63 | * @param notification Wrapper around the local notification.
64 | * @param bundle The bundled extras.
65 | */
66 | abstract public void onClear (Notification notification, Bundle bundle);
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/android/notification/receiver/AbstractClickReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.receiver;
23 |
24 | import android.app.IntentService;
25 | import android.content.Context;
26 | import android.content.Intent;
27 | import android.os.Bundle;
28 |
29 | import de.appplant.cordova.plugin.notification.Manager;
30 | import de.appplant.cordova.plugin.notification.Notification;
31 |
32 | import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
33 | import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
34 | import static de.appplant.cordova.plugin.notification.action.Action.CLICK_ACTION_ID;
35 | import static de.appplant.cordova.plugin.notification.action.Action.EXTRA_ID;
36 |
37 | /**
38 | * Abstract content receiver activity for local notifications. Creates the
39 | * local notification and calls the event functions for further proceeding.
40 | */
41 | abstract public class AbstractClickReceiver extends IntentService {
42 |
43 | // Holds a reference to the intent to handle.
44 | private Intent intent;
45 |
46 | public AbstractClickReceiver() {
47 | super("LocalNotificationClickReceiver");
48 | }
49 |
50 | /**
51 | * Called when local notification was clicked to launch the main intent.
52 | */
53 | @Override
54 | protected void onHandleIntent(Intent intent) {
55 | this.intent = intent;
56 |
57 | if (intent == null)
58 | return;
59 |
60 | Bundle bundle = intent.getExtras();
61 | Context context = getApplicationContext();
62 |
63 | if (bundle == null)
64 | return;
65 |
66 | int toastId = bundle.getInt(Notification.EXTRA_ID);
67 | Notification toast = Manager.getInstance(context).get(toastId);
68 |
69 | if (toast == null)
70 | return;
71 |
72 | onClick(toast, bundle);
73 | this.intent = null;
74 | }
75 |
76 | /**
77 | * Called when local notification was clicked by the user.
78 | *
79 | * @param notification Wrapper around the local notification.
80 | * @param bundle The bundled extras.
81 | */
82 | abstract public void onClick (Notification notification, Bundle bundle);
83 |
84 | /**
85 | * The invoked action.
86 | */
87 | protected String getAction() {
88 | return getIntent().getExtras().getString(EXTRA_ID, CLICK_ACTION_ID);
89 | }
90 |
91 | /**
92 | * Getter for the received intent.
93 | */
94 | protected Intent getIntent() {
95 | return intent;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/android/notification/receiver/AbstractNotificationReceiver.java:
--------------------------------------------------------------------------------
1 | package de.appplant.cordova.plugin.notification.receiver;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.os.PowerManager;
6 | import android.util.Log;
7 |
8 | import org.json.JSONException;
9 | import org.json.JSONObject;
10 |
11 | import java.util.Calendar;
12 |
13 | import de.appplant.cordova.plugin.notification.Manager;
14 | import de.appplant.cordova.plugin.notification.Notification;
15 | import de.appplant.cordova.plugin.notification.Options;
16 | import de.appplant.cordova.plugin.notification.Request;
17 | import de.appplant.cordova.plugin.notification.util.LaunchUtils;
18 |
19 | import static android.content.Context.POWER_SERVICE;
20 | import static android.os.Build.VERSION.SDK_INT;
21 | import static android.os.Build.VERSION_CODES.O;
22 | import static android.os.Build.VERSION_CODES.P;
23 | import static java.util.Calendar.MINUTE;
24 |
25 | /**
26 | * The base class for any receiver that is trying to display a notification.
27 | */
28 | abstract public class AbstractNotificationReceiver extends BroadcastReceiver {
29 | private final String TAG = "AbstractNotification";
30 |
31 | /**
32 | * Perform a notification. All notification logic is here.
33 | * Determines whether to dispatch events, autoLaunch the app, use fullScreenIntents, etc.
34 | * @param notification reference to the notification to be fired
35 | */
36 | public void performNotification(Notification notification) {
37 | Context context = notification.getContext();
38 | Options options = notification.getOptions();
39 | Manager manager = Manager.getInstance(context);
40 | PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
41 | boolean autoLaunch = options.isAutoLaunchingApp() && SDK_INT <= P && !options.useFullScreenIntent();
42 |
43 | int badge = options.getBadgeNumber();
44 |
45 | if (badge > 0) {
46 | manager.setBadge(badge);
47 | }
48 |
49 | if (options.shallWakeUp()) {
50 | wakeUp(notification);
51 | }
52 |
53 | if (autoLaunch) {
54 | LaunchUtils.launchApp(context);
55 | }
56 |
57 | // Show notification if we should (triggerInApp is false)
58 | // or if we can't trigger in the app due to:
59 | // 1. No autoLaunch configured/supported and app is not running.
60 | // 2. Any SDK >= Oreo is asleep (must be triggered here)
61 | boolean didShowNotification = false;
62 | if (!options.triggerInApp() ||
63 | (!autoLaunch && !checkAppRunning())
64 | ) {
65 | didShowNotification = true;
66 | notification.show();
67 | }
68 |
69 | // run trigger function if triggerInApp() is true
70 | // and we did not send a notification.
71 | if (options.triggerInApp() && !didShowNotification) {
72 | // wake up even if we didn't set it to
73 | if (!options.shallWakeUp()) {
74 | wakeUp(notification);
75 | }
76 |
77 | dispatchAppEvent("trigger", notification);
78 | }
79 |
80 | if (!options.isInfiniteTrigger())
81 | return;
82 |
83 | Calendar cal = Calendar.getInstance();
84 | cal.add(MINUTE, 1);
85 |
86 | Request req = new Request(
87 | getOptionsWithBaseDate(options, cal.getTimeInMillis()),
88 | cal.getTime()
89 | );
90 |
91 | manager.schedule(req, this.getClass());
92 | }
93 |
94 | /**
95 | * Clone options with base date attached to trigger.
96 | * Used so that persisted objects know the last execution time.
97 | * @param baseDateMillis base date represented in milliseconds
98 | * @return new Options object with base time set in requestBaseDate.
99 | */
100 | private Options getOptionsWithBaseDate(Options options, long baseDateMillis) {
101 | JSONObject optionsDict = options.getDict();
102 | try {
103 | JSONObject triggerDict = optionsDict.getJSONObject("trigger");
104 | triggerDict.put("requestBaseDate", baseDateMillis);
105 | optionsDict.remove("trigger");
106 | optionsDict.put("trigger", triggerDict);
107 | } catch (JSONException e) {
108 | Log.e(TAG, "Unexpected error adding requestBaseDate to JSON structure: " + e.toString());
109 | }
110 | return new Options(optionsDict);
111 | }
112 |
113 | /**
114 | * Send the application an event using our notification
115 | * @param key key for our event in the app
116 | * @param notification reference to the notification
117 | */
118 | abstract public void dispatchAppEvent(String key, Notification notification);
119 |
120 | /**
121 | * Check if the application is running.
122 | * Should be developed in local class, which has access to things needed for this.
123 | * @return whether or not app is running
124 | */
125 | abstract public boolean checkAppRunning();
126 |
127 | /**
128 | * Wakeup the device.
129 | *
130 | * @param notification The notification used to wakeup the device.
131 | * contains context and timeout.
132 | */
133 | private void wakeUp(Notification notification) {
134 | Context context = notification.getContext();
135 | Options options = notification.getOptions();
136 | String wakeLockTag = context.getApplicationInfo().name + ":LocalNotification";
137 | PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
138 |
139 | if (pm == null)
140 | return;
141 |
142 | int level = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE;
143 |
144 | PowerManager.WakeLock wakeLock = pm.newWakeLock(level, wakeLockTag);
145 |
146 | wakeLock.setReferenceCounted(false);
147 | wakeLock.acquire(options.getWakeLockTimeout());
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/android/notification/receiver/AbstractRestoreReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
3 | *
4 | * @APPPLANT_LICENSE_HEADER_START@
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | *
21 | * @APPPLANT_LICENSE_HEADER_END@
22 | */
23 |
24 | package de.appplant.cordova.plugin.notification.receiver;
25 |
26 | import android.content.BroadcastReceiver;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.os.UserManager;
30 |
31 | import org.json.JSONObject;
32 |
33 | import java.util.List;
34 |
35 | import de.appplant.cordova.plugin.notification.Builder;
36 | import de.appplant.cordova.plugin.notification.Manager;
37 | import de.appplant.cordova.plugin.notification.Notification;
38 | import de.appplant.cordova.plugin.notification.Options;
39 | import de.appplant.cordova.plugin.notification.Request;
40 |
41 | import static android.content.Intent.ACTION_BOOT_COMPLETED;
42 | import static android.os.Build.VERSION.SDK_INT;
43 |
44 | /**
45 | * This class is triggered upon reboot of the device. It needs to re-register
46 | * the alarms with the AlarmManager since these alarms are lost in case of
47 | * reboot.
48 | */
49 | abstract public class AbstractRestoreReceiver extends AbstractNotificationReceiver {
50 |
51 | /**
52 | * Called on device reboot.
53 | *
54 | * @param context Application context
55 | * @param intent Received intent with content data
56 | */
57 | @Override
58 | public void onReceive (Context context, Intent intent) {
59 | String action = intent.getAction();
60 |
61 | if (SDK_INT >= 24) {
62 | UserManager um = (UserManager) context.getSystemService(UserManager.class);
63 | if (um == null || um.isUserUnlocked() == false) return;
64 | }
65 |
66 | Manager mgr = Manager.getInstance(context);
67 | List toasts = mgr.getOptions();
68 |
69 | for (JSONObject data : toasts) {
70 | Options options = new Options(context, data);
71 | Request request = new Request(options);
72 | Builder builder = new Builder(options);
73 | Notification toast = buildNotification(builder);
74 |
75 | onRestore(request, toast);
76 | }
77 | }
78 |
79 | /**
80 | * Called when a local notification need to be restored.
81 | *
82 | * @param request Set of notification options.
83 | * @param toast Wrapper around the local notification.
84 | */
85 | abstract public void onRestore (Request request, Notification toast);
86 |
87 | /**
88 | * Build notification specified by options.
89 | *
90 | * @param builder Notification builder.
91 | */
92 | abstract public Notification buildNotification (Builder builder);
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/android/notification/receiver/AbstractTriggerReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.receiver;
23 |
24 | import android.content.BroadcastReceiver;
25 | import android.content.Context;
26 | import android.content.Intent;
27 | import android.os.Bundle;
28 |
29 | import de.appplant.cordova.plugin.notification.Builder;
30 | import de.appplant.cordova.plugin.notification.Manager;
31 | import de.appplant.cordova.plugin.notification.Notification;
32 | import de.appplant.cordova.plugin.notification.Options;
33 |
34 | /**
35 | * Abstract broadcast receiver for local notifications. Creates the
36 | * notification options and calls the event functions for further proceeding.
37 | */
38 | abstract public class AbstractTriggerReceiver extends AbstractNotificationReceiver {
39 |
40 | /**
41 | * Called when an alarm was triggered.
42 | *
43 | * @param context Application context
44 | * @param intent Received intent with content data
45 | */
46 | @Override
47 | public void onReceive(Context context, Intent intent) {
48 | Bundle bundle = intent.getExtras();
49 |
50 | if (bundle == null)
51 | return;
52 |
53 | int toastId = bundle.getInt(Notification.EXTRA_ID, 0);
54 | Options options = Manager.getInstance(context).getOptions(toastId);
55 |
56 | if (options == null)
57 | return;
58 |
59 | Builder builder = new Builder(options);
60 | Notification toast = buildNotification(builder, bundle);
61 |
62 | if (toast == null)
63 | return;
64 |
65 | onTrigger(toast, bundle);
66 | }
67 |
68 | /**
69 | * Called when a local notification was triggered.
70 | *
71 | * @param notification Wrapper around the local notification.
72 | * @param bundle The bundled extras.
73 | */
74 | abstract public void onTrigger (Notification notification, Bundle bundle);
75 |
76 | /**
77 | * Build notification specified by options.
78 | *
79 | * @param builder Notification builder.
80 | * @param bundle The bundled extras.
81 | */
82 | abstract public Notification buildNotification (Builder builder,
83 | Bundle bundle);
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/android/notification/trigger/DateTrigger.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.trigger;
23 |
24 | import java.util.Calendar;
25 | import java.util.Date;
26 |
27 | abstract public class DateTrigger {
28 |
29 | // Default unit is SECOND
30 | public enum Unit { SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR }
31 |
32 | // Internal counter
33 | private int occurrence = 1;
34 |
35 | /**
36 | * Gets the next trigger date.
37 | *
38 | * @param base The date from where to calculate the trigger date.
39 | *
40 | * @return null if there's none next trigger date.
41 | */
42 | abstract public Date getNextTriggerDate(Date base);
43 |
44 | /**
45 | * The value of the occurrence.
46 | */
47 | public int getOccurrence() {
48 | return occurrence;
49 | }
50 |
51 | /**
52 | * Increase the occurrence by 1.
53 | */
54 | void incOccurrence() {
55 | occurrence += 1;
56 | }
57 |
58 | /**
59 | * Gets a calendar instance pointing to the specified date.
60 | *
61 | * @param date The date to point.
62 | */
63 | Calendar getCal (Date date) {
64 | Calendar cal = Calendar.getInstance();
65 | cal.setTime(date);
66 |
67 | return cal;
68 | }
69 |
70 | }
--------------------------------------------------------------------------------
/src/android/notification/trigger/IntervalTrigger.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | package de.appplant.cordova.plugin.notification.trigger;
23 |
24 | import java.util.Calendar;
25 | import java.util.Date;
26 |
27 | /**
28 | * Trigger class for interval based notification. Trigger by a fixed interval
29 | * from now.
30 | */
31 | public class IntervalTrigger extends DateTrigger {
32 |
33 | // The number of ticks per interval
34 | private final int ticks;
35 |
36 | // The unit of the ticks
37 | final Unit unit;
38 |
39 | /**
40 | * Interval trigger based from now.
41 | *
42 | * @param ticks The number of ticks per interval.
43 | * @param unit The unit of the ticks.
44 | */
45 | public IntervalTrigger(int ticks, Unit unit) {
46 | this.ticks = ticks;
47 | this.unit = unit;
48 | }
49 |
50 | /**
51 | * Gets the next trigger date.
52 | *
53 | * @param base The date from where to calculate the trigger date.
54 | *
55 | * @return null if there's none next trigger date.
56 | */
57 | @Override
58 | public Date getNextTriggerDate(Date base) {
59 | Calendar cal = getCal(base);
60 |
61 | addInterval(cal);
62 | incOccurrence();
63 |
64 | return cal.getTime();
65 | }
66 |
67 | /**
68 | * Adds the amount of ticks to the calendar.
69 | *
70 | * @param cal The calendar to manipulate.
71 | */
72 | void addInterval(Calendar cal) {
73 | switch (unit) {
74 | case SECOND:
75 | cal.add(Calendar.SECOND, ticks);
76 | break;
77 | case MINUTE:
78 | cal.add(Calendar.MINUTE, ticks);
79 | break;
80 | case HOUR:
81 | cal.add(Calendar.HOUR_OF_DAY, ticks);
82 | break;
83 | case DAY:
84 | cal.add(Calendar.DAY_OF_YEAR, ticks);
85 | break;
86 | case WEEK:
87 | cal.add(Calendar.WEEK_OF_YEAR, ticks);
88 | break;
89 | case MONTH:
90 | cal.add(Calendar.MONTH, ticks);
91 | break;
92 | case QUARTER:
93 | cal.add(Calendar.MONTH, ticks * 3);
94 | break;
95 | case YEAR:
96 | cal.add(Calendar.YEAR, ticks);
97 | break;
98 | }
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/src/android/notification/util/AssetProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | package de.appplant.cordova.plugin.notification.util;
21 |
22 | import androidx.core.content.FileProvider;
23 |
24 | public class AssetProvider extends FileProvider {
25 | // Nothing to do here
26 | }
27 |
--------------------------------------------------------------------------------
/src/android/notification/util/LaunchUtils.java:
--------------------------------------------------------------------------------
1 | package de.appplant.cordova.plugin.notification.util;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 |
6 | import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
7 | import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
8 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
9 |
10 | public final class LaunchUtils {
11 |
12 | /***
13 | * Launch main intent from package.
14 | */
15 | public static void launchApp(Context context) {
16 | String pkgName = context.getPackageName();
17 |
18 | Intent intent = context
19 | .getPackageManager()
20 | .getLaunchIntentForPackage(pkgName);
21 |
22 | if (intent == null)
23 | return;
24 |
25 | intent.addFlags(
26 | FLAG_ACTIVITY_REORDER_TO_FRONT
27 | | FLAG_ACTIVITY_SINGLE_TOP
28 | | FLAG_ACTIVITY_NEW_TASK
29 | );
30 |
31 | context.startActivity(intent);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/android/xml/localnotification_provider_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/ios/APPLocalNotification.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import
23 |
24 | @import UserNotifications;
25 |
26 | @interface APPLocalNotification : CDVPlugin
27 |
28 | - (void) launch:(CDVInvokedUrlCommand*)command;
29 | - (void) ready:(CDVInvokedUrlCommand*)command;
30 |
31 | - (void) actions:(CDVInvokedUrlCommand*)command;
32 |
33 | - (void) check:(CDVInvokedUrlCommand*)command;
34 | - (void) request:(CDVInvokedUrlCommand*)command;
35 |
36 | - (void) schedule:(CDVInvokedUrlCommand*)command;
37 | - (void) update:(CDVInvokedUrlCommand*)command;
38 |
39 | - (void) clear:(CDVInvokedUrlCommand*)command;
40 | - (void) clearAll:(CDVInvokedUrlCommand*)command;
41 |
42 | - (void) cancel:(CDVInvokedUrlCommand*)command;
43 | - (void) cancelAll:(CDVInvokedUrlCommand*)command;
44 |
45 | - (void) type:(CDVInvokedUrlCommand*)command;
46 |
47 | - (void) ids:(CDVInvokedUrlCommand*)command;
48 |
49 | - (void) notification:(CDVInvokedUrlCommand*)command;
50 | - (void) notifications:(CDVInvokedUrlCommand*)command;
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/src/ios/APPNotificationCategory.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | @import UserNotifications;
23 |
24 | @interface APPNotificationCategory : NSObject
25 |
26 | + (UNNotificationCategory*) parse:(NSArray*)list withId:(NSString*)groupId;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/src/ios/APPNotificationCategory.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationCategory.h"
23 |
24 | @import UserNotifications;
25 |
26 | @implementation APPNotificationCategory : NSObject
27 |
28 | #pragma mark -
29 | #pragma mark Public
30 |
31 | /**
32 | * Parse the provided spec map into an action group.
33 | *
34 | * @param [ NSDictionary* ] spec A key-value property map.
35 | * Must contain an id and a list of actions.
36 | *
37 | * @return [ UNNotificationCategory* ]
38 | */
39 | + (UNNotificationCategory*) parse:(NSArray*)list withId:(NSString*)groupId
40 | {
41 | NSArray* actions = [self parseActions:list];
42 |
43 | return [UNNotificationCategory categoryWithIdentifier:groupId
44 | actions:actions
45 | intentIdentifiers:@[]
46 | options:UNNotificationCategoryOptionCustomDismissAction];
47 | }
48 |
49 | #pragma mark -
50 | #pragma mark Private
51 |
52 | /**
53 | * The actions of the action group.
54 | *
55 | * @return [ NSArray* ]
56 | */
57 | + (NSArray *) parseActions:(NSArray*)items
58 | {
59 | NSMutableArray* actions = [[NSMutableArray alloc] init];
60 |
61 | for (NSDictionary* item in items) {
62 | NSString* id = item[@"id"];
63 | NSString* title = item[@"title"];
64 | NSString* type = item[@"type"];
65 |
66 | UNNotificationActionOptions options = UNNotificationActionOptionNone;
67 | UNNotificationAction* action;
68 |
69 | if ([item[@"launch"] boolValue]) {
70 | options = UNNotificationActionOptionForeground;
71 | }
72 |
73 | if ([item[@"ui"] isEqualToString:@"decline"]) {
74 | options = options | UNNotificationActionOptionDestructive;
75 | }
76 |
77 | if ([item[@"needsAuth"] boolValue]) {
78 | options = options | UNNotificationActionOptionAuthenticationRequired;
79 | }
80 |
81 | if ([type isEqualToString:@"input"]) {
82 | NSString* submitTitle = item[@"submitTitle"];
83 | NSString* placeholder = item[@"emptyText"];
84 |
85 | if (!submitTitle.length) {
86 | submitTitle = @"Submit";
87 | }
88 |
89 | action = [UNTextInputNotificationAction actionWithIdentifier:id
90 | title:title
91 | options:options
92 | textInputButtonTitle:submitTitle
93 | textInputPlaceholder:placeholder];
94 | } else
95 | if (!type.length || [type isEqualToString:@"button"]) {
96 | action = [UNNotificationAction actionWithIdentifier:id
97 | title:title
98 | options:options];
99 | } else {
100 | NSLog(@"Unknown action type: %@", type);
101 | }
102 |
103 | if (action) {
104 | [actions addObject:action];
105 | }
106 | }
107 |
108 | return actions;
109 | }
110 |
111 | @end
112 |
--------------------------------------------------------------------------------
/src/ios/APPNotificationContent.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationOptions.h"
23 |
24 | @import UserNotifications;
25 |
26 | @interface APPNotificationContent : UNMutableNotificationContent
27 |
28 | - (id) initWithOptions:(NSDictionary*)dict;
29 | - (APPNotificationOptions*) options;
30 | - (UNNotificationRequest*) request;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/src/ios/APPNotificationContent.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationContent.h"
23 | #import "APPNotificationOptions.h"
24 | #import
25 |
26 | @import UserNotifications;
27 |
28 | static char optionsKey;
29 |
30 | @implementation APPNotificationContent : UNMutableNotificationContent
31 |
32 | #pragma mark -
33 | #pragma mark Init
34 |
35 | /**
36 | * Initialize a notification with the given options.
37 | *
38 | * @param [ NSDictionary* ] dict A key-value property map.
39 | *
40 | * @return [ UNMutableNotificationContent ]
41 | */
42 | - (id) initWithOptions:(NSDictionary*)dict
43 | {
44 | self = [self init];
45 |
46 | [self setUserInfo:dict];
47 | [self __init];
48 |
49 | return self;
50 | }
51 |
52 | /**
53 | * Initialize a notification by using the options found under userInfo.
54 | *
55 | * @return [ Void ]
56 | */
57 | - (void) __init
58 | {
59 | APPNotificationOptions* options = self.options;
60 |
61 | self.title = options.title;
62 | self.subtitle = options.subtitle;
63 | self.body = options.text;
64 | self.sound = options.sound;
65 | self.badge = options.badge;
66 | self.attachments = options.attachments;
67 | self.categoryIdentifier = options.actionGroupId;
68 | }
69 |
70 | #pragma mark -
71 | #pragma mark Public
72 |
73 | /**
74 | * The options used to initialize the notification.
75 | *
76 | * @return [ APPNotificationOptions* ] options
77 | */
78 | - (APPNotificationOptions*) options
79 | {
80 | APPNotificationOptions* options = [self getOptions];
81 |
82 | if (!options) {
83 | options = [[APPNotificationOptions alloc]
84 | initWithDict:[self userInfo]];
85 |
86 | [self setOptions:options];
87 | }
88 |
89 | return options;
90 | }
91 |
92 | /**
93 | * The notifcations request ready to add to the notification center including
94 | * all informations about trigger behavior.
95 | *
96 | * @return [ UNNotificationRequest* ]
97 | */
98 | - (UNNotificationRequest*) request
99 | {
100 | APPNotificationOptions* opts = [self getOptions];
101 |
102 | return [UNNotificationRequest requestWithIdentifier:opts.identifier
103 | content:self
104 | trigger:opts.trigger];
105 | }
106 |
107 | #pragma mark -
108 | #pragma mark Private
109 |
110 | /**
111 | * The options used to initialize the notification.
112 | *
113 | * @return [ APPNotificationOptions* ]
114 | */
115 | - (APPNotificationOptions*) getOptions
116 | {
117 | return objc_getAssociatedObject(self, &optionsKey);
118 | }
119 |
120 | /**
121 | * Set the options used to initialize the notification.
122 | *
123 | * @param [ NSDictionary* ] dict A key-value property map.
124 | *
125 | * @return [ Void ]
126 | */
127 | - (void) setOptions:(APPNotificationOptions*)options
128 | {
129 | objc_setAssociatedObject(self, &optionsKey,
130 | options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
131 | }
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/src/ios/APPNotificationOptions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | @import UserNotifications;
23 |
24 | @interface APPNotificationOptions : NSObject
25 |
26 | @property (readonly, getter=id) NSNumber* id;
27 | @property (readonly, getter=identifier) NSString* identifier;
28 | @property (readonly, getter=actionGroupId) NSString* actionGroupId;
29 | @property (readonly, getter=title) NSString* title;
30 | @property (readonly, getter=subtitle) NSString* subtitle;
31 | @property (readonly, getter=badge) NSNumber* badge;
32 | @property (readonly, getter=text) NSString* text;
33 | @property (readonly, getter=silent) BOOL silent;
34 | @property (readonly, getter=priority) int priority;
35 | @property (readonly, getter=sound) UNNotificationSound* sound;
36 | @property (readonly, getter=userInfo) NSDictionary* userInfo;
37 | @property (readonly, getter=attachments) NSArray*attachments;
38 |
39 | - (id) initWithDict:(NSDictionary*) dict;
40 | - (UNNotificationTrigger*) trigger;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/src/ios/UNNotificationRequest+APPLocalNotification.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationOptions.h"
23 |
24 | @import UserNotifications;
25 |
26 | @interface UNNotificationRequest (APPLocalNotification)
27 |
28 | - (APPNotificationOptions*) options;
29 | - (BOOL) wasUpdated;
30 | - (NSString*) encodeToJSON;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/src/ios/UNNotificationRequest+APPLocalNotification.m:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationOptions.h"
23 | #import "UNNotificationRequest+APPLocalNotification.h"
24 | #import "APPNotificationContent.h"
25 | #import
26 |
27 | @import UserNotifications;
28 |
29 | static char optionsKey;
30 |
31 | @implementation UNNotificationRequest (APPLocalNotification)
32 |
33 | /**
34 | * Get associated option object
35 | */
36 | - (APPNotificationOptions*) getOptions
37 | {
38 | return objc_getAssociatedObject(self, &optionsKey);
39 | }
40 |
41 | /**
42 | * Set associated option object
43 | */
44 | - (void) setOptions:(APPNotificationOptions*)options
45 | {
46 | objc_setAssociatedObject(self, &optionsKey,
47 | options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
48 | }
49 |
50 | /**
51 | * The options provided by the plug-in.
52 | */
53 | - (APPNotificationOptions*) options
54 | {
55 | APPNotificationOptions* options = [self getOptions];
56 |
57 | if (!options) {
58 | options = [[APPNotificationOptions alloc]
59 | initWithDict:[self.content userInfo]];
60 |
61 | [self setOptions:options];
62 | }
63 |
64 | return options;
65 | }
66 |
67 | /**
68 | * If the notification was updated.
69 | *
70 | * @return [ BOOL ]
71 | */
72 | - (BOOL) wasUpdated
73 | {
74 | return [self.content userInfo][@"updatedAt"] != NULL;
75 | }
76 |
77 | /**
78 | * Encode the user info dict to JSON.
79 | */
80 | - (NSString*) encodeToJSON
81 | {
82 | NSString* json;
83 | NSData* data;
84 | NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
85 |
86 | [obj removeObjectForKey:@"updatedAt"];
87 |
88 | if (obj == NULL || obj.count == 0)
89 | return json;
90 |
91 | data = [NSJSONSerialization dataWithJSONObject:obj
92 | options:NSJSONWritingPrettyPrinted
93 | error:NULL];
94 |
95 | json = [[NSString alloc] initWithData:data
96 | encoding:NSUTF8StringEncoding];
97 |
98 | return [json stringByReplacingOccurrencesOfString:@"\n"
99 | withString:@""];
100 | }
101 |
102 | @end
103 |
--------------------------------------------------------------------------------
/src/ios/UNUserNotificationCenter+APPLocalNotification.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | #import "APPNotificationContent.h"
23 |
24 | @interface UNUserNotificationCenter (APPLocalNotification)
25 |
26 | extern NSString * const kAPPGeneralCategory;
27 |
28 | typedef NS_ENUM(NSUInteger, APPNotificationType) {
29 | NotifcationTypeAll = 0,
30 | NotifcationTypeScheduled = 1,
31 | NotifcationTypeTriggered = 2,
32 | NotifcationTypeUnknown = 3
33 | };
34 |
35 | #define APPNotificationType_DEFINED
36 |
37 | @property (readonly, getter=getNotifications) NSArray* localNotifications;
38 | @property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
39 |
40 | - (void) registerGeneralNotificationCategory;
41 | - (void) addActionGroup:(UNNotificationCategory*)category;
42 | - (void) removeActionGroup:(NSString*)identifier;
43 | - (BOOL) hasActionGroup:(NSString*)identifier;
44 |
45 | - (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
46 |
47 | - (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
48 | - (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id;
49 |
50 | - (NSArray*) getNotificationOptions;
51 | - (NSArray*) getNotificationOptionsById:(NSArray*)ids;
52 | - (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
53 |
54 | - (void) clearNotification:(UNNotificationRequest*)notification;
55 | - (void) clearNotifications;
56 |
57 | - (void) cancelNotification:(UNNotificationRequest*)notification;
58 | - (void) cancelNotifications;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/.vs/LocalNotificationProxy/v15/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/LocalNotificationProxy/.vs/LocalNotificationProxy/v15/.suo
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26430.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalNotificationProxy", "LocalNotificationProxy\LocalNotificationProxy.csproj", "{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|ARM = Debug|ARM
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|Any CPU = Release|Any CPU
15 | Release|ARM = Release|ARM
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.ActiveCfg = Debug|ARM
23 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.Build.0 = Debug|ARM
24 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.ActiveCfg = Debug|x64
25 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.Build.0 = Debug|x64
26 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.ActiveCfg = Debug|x86
27 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.Build.0 = Debug|x86
28 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.ActiveCfg = Release|ARM
31 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.Build.0 = Release|ARM
32 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.ActiveCfg = Release|x64
33 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.Build.0 = Release|x64
34 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.ActiveCfg = Release|x86
35 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.Build.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/ActionGroup.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification
23 | {
24 | using System.Collections.Generic;
25 | using System.Runtime.InteropServices.WindowsRuntime;
26 | using global::LocalNotificationProxy.LocalNotification.Toast;
27 |
28 | public sealed class ActionGroup
29 | {
30 | ///
31 | /// Saves all groups for later lookup.
32 | ///
33 | private static Dictionary groups = new Dictionary();
34 |
35 | ///
36 | /// Initializes a new instance of the class.
37 | ///
38 | /// The ID of the action group.
39 | /// The list of actions to group for.
40 | public ActionGroup(string id, [ReadOnlyArray] IAction[] actions)
41 | {
42 | this.Id = id;
43 | this.Actions = actions;
44 | }
45 |
46 | ///
47 | /// Gets or sets the action group ID.
48 | ///
49 | public string Id { get; set; }
50 |
51 | ///
52 | /// Gets or sets the notification actions.
53 | ///
54 | public IAction[] Actions { get; set; }
55 |
56 | ///
57 | /// Lookup the action groups with the specified group id.
58 | ///
59 | /// The ID of the action group to find.
60 | /// Null if no group was found.
61 | public static ActionGroup Lookup(string id)
62 | {
63 | return groups[id];
64 | }
65 |
66 | ///
67 | /// Register the provided set of actions under the specified group id.
68 | ///
69 | /// The action group to register.
70 | public static void Register(ActionGroup group)
71 | {
72 | groups.Add(group.Id, group);
73 | }
74 |
75 | ///
76 | /// Unregister the action group.
77 | ///
78 | /// The id of the action group to remove.
79 | public static void Unregister(string id)
80 | {
81 | groups.Remove(id);
82 | }
83 |
84 | ///
85 | /// Check if a action group with that id is registered.
86 | ///
87 | /// The id of the action group to check for.
88 | /// True if a group with the ID could be found.
89 | public static bool IsRegistered(string id)
90 | {
91 | return groups.ContainsKey(id);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Builder.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification
23 | {
24 | using System.Diagnostics;
25 | using Microsoft.Toolkit.Uwp.Notifications;
26 | using Windows.UI.Notifications;
27 |
28 | internal class Builder
29 | {
30 | ///
31 | /// The provided trigger request.
32 | ///
33 | private readonly Request request;
34 |
35 | ///
36 | /// Initializes a new instance of the class.
37 | ///
38 | /// Trigger request.
39 | public Builder(Request request)
40 | {
41 | this.request = request;
42 | this.Content = new Notification(request.Options);
43 | }
44 |
45 | ///
46 | /// Gets the content.
47 | ///
48 | public Notification Content { get; private set; }
49 |
50 | ///
51 | /// Gets the options.
52 | ///
53 | private Options Options { get => this.Content.Options; }
54 |
55 | ///
56 | /// Build a toast notification specified by the options.
57 | ///
58 | /// A fully configured toast notification instance.
59 | public ScheduledToastNotification Build()
60 | {
61 | var toast = this.InitToast();
62 |
63 | this.AddProgressBarToToast(toast);
64 | this.AddAttachmentsToToast(toast);
65 | this.AddActionsToToast(toast);
66 |
67 | return this.ConvertToastToNotification(toast);
68 | }
69 |
70 | ///
71 | /// Gets the initialize skeleton for a toast notification.
72 | ///
73 | /// Basic skeleton with sound, image and text.
74 | private ToastContent InitToast()
75 | {
76 | return new ToastContent()
77 | {
78 | Launch = this.Content.GetXml(),
79 | Audio = this.Content.Sound,
80 |
81 | Visual = new ToastVisual()
82 | {
83 | BindingGeneric = new ToastBindingGeneric()
84 | {
85 | Children =
86 | {
87 | new AdaptiveText()
88 | {
89 | Text = this.Options.Title
90 | },
91 |
92 | new AdaptiveText()
93 | {
94 | Text = this.Options.Text
95 | }
96 | },
97 |
98 | AppLogoOverride = this.Content.Icon
99 | }
100 | },
101 |
102 | Actions = new ToastActionsCustom()
103 | {
104 | Buttons = { },
105 | Inputs = { }
106 | }
107 | };
108 | }
109 |
110 | ///
111 | /// Adds optional progress bar to the toast.
112 | ///
113 | /// Tho toast to extend for.
114 | private void AddProgressBarToToast(ToastContent toast)
115 | {
116 | var progressBar = this.Content.ProgressBar;
117 |
118 | if (progressBar != null)
119 | {
120 | toast.Visual.BindingGeneric.Children.Add(progressBar);
121 | }
122 | }
123 |
124 | ///
125 | /// Adds attachments to the toast.
126 | ///
127 | /// Tho toast to extend for.
128 | private void AddAttachmentsToToast(ToastContent toast)
129 | {
130 | foreach (var image in this.Content.Attachments)
131 | {
132 | toast.Visual.BindingGeneric.Children.Add(image);
133 | }
134 | }
135 |
136 | ///
137 | /// Adds buttons and input fields to the toast.
138 | ///
139 | /// Tho toast to extend for.
140 | private void AddActionsToToast(ToastContent toast)
141 | {
142 | foreach (var btn in this.Content.Inputs)
143 | {
144 | (toast.Actions as ToastActionsCustom).Inputs.Add(btn);
145 | }
146 |
147 | foreach (var btn in this.Content.Buttons)
148 | {
149 | (toast.Actions as ToastActionsCustom).Buttons.Add(btn);
150 | }
151 | }
152 |
153 | ///
154 | /// Converts the toast into a notification.
155 | ///
156 | /// The toast to convert.
157 | /// A notification ready to schedule.
158 | private ScheduledToastNotification ConvertToastToNotification(ToastContent toast)
159 | {
160 | var xml = toast.GetXml();
161 | var at = this.request.TriggerDate;
162 | ScheduledToastNotification notification;
163 |
164 | Debug.WriteLine("[local-notification] Next trigger at: " + at);
165 |
166 | if (!at.HasValue)
167 | {
168 | return null;
169 | }
170 |
171 | try
172 | {
173 | notification = new ScheduledToastNotification(xml, at.Value);
174 | }
175 | catch
176 | {
177 | return null;
178 | }
179 |
180 | notification.Id = this.Content.Id;
181 | notification.Tag = this.Options.Id.ToString();
182 | notification.SuppressPopup = this.Options.Silent;
183 |
184 | if (this.request.Occurrence > 2)
185 | {
186 | notification.Group = notification.Tag;
187 | }
188 |
189 | return notification;
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Notification.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification
23 | {
24 | using System;
25 | using System.Collections.Generic;
26 | using global::LocalNotificationProxy.LocalNotification.Toast;
27 | using Microsoft.Toolkit.Uwp.Notifications;
28 | using Windows.UI.Notifications;
29 |
30 | internal class Notification
31 | {
32 | ///
33 | /// Initializes a new instance of the class.
34 | ///
35 | /// The options hash map from JS side.
36 | public Notification(Options options)
37 | {
38 | this.Options = options;
39 | }
40 |
41 | ///
42 | /// Initializes a new instance of the class.
43 | ///
44 | /// The options as a xml string.
45 | public Notification(string xml)
46 | {
47 | this.Options = Options.Parse(xml);
48 | }
49 |
50 | ///
51 | /// Initializes a new instance of the class.
52 | ///
53 | /// The options as a toast object.
54 | public Notification(ScheduledToastNotification toast)
55 | {
56 | this.Options = Options.Parse(toast.Content.GetXml());
57 | }
58 |
59 | ///
60 | /// Initializes a new instance of the class.
61 | ///
62 | /// The options as a toast object.
63 | public Notification(ToastNotification toast)
64 | {
65 | var xml = toast.Content.DocumentElement.GetAttribute("launch");
66 | this.Options = Options.Parse(xml);
67 | }
68 |
69 | public enum Type
70 | {
71 | All, Scheduled, Triggered, Unknown
72 | }
73 |
74 | ///
75 | /// Gets the wrapped notification options.
76 | ///
77 | public Options Options { get; private set; }
78 |
79 | ///
80 | /// Gets the unique identifier for the toast.
81 | ///
82 | public string Id => $"{this.Options.Id}#{this.Options.Trigger.Occurrence}";
83 |
84 | ///
85 | /// Gets a ToastAudio object based on the specified sound uri.
86 | ///
87 | public ToastAudio Sound
88 | {
89 | get
90 | {
91 | var sound = new ToastAudio();
92 | var path = this.Options.Sound;
93 |
94 | if (path == null || path.Length == 0 || path.Equals("false"))
95 | {
96 | sound.Silent = true;
97 | }
98 | else
99 | if (path.StartsWith("file:///") || path.StartsWith("http"))
100 | {
101 | sound.Src = new Uri(path, UriKind.Absolute);
102 | }
103 | else
104 | if (path.StartsWith("file://"))
105 | {
106 | sound.Src = new Uri(path.Replace("file:/", "ms-appx:///www"));
107 | }
108 | else
109 | if (path.StartsWith("res://"))
110 | {
111 | sound.Src = new Uri(path.Replace("res://", "ms-winsoundevent:notification."));
112 | }
113 | else
114 | if (path.StartsWith("app://"))
115 | {
116 | sound.Src = new Uri(path.Replace("app:/", "ms-appdata://"));
117 | }
118 |
119 | return sound;
120 | }
121 | }
122 |
123 | ///
124 | /// Gets a GenericAppLogo object based on the specified icon uri.
125 | ///
126 | public ToastGenericAppLogo Icon
127 | {
128 | get
129 | {
130 | var image = new ToastGenericAppLogo();
131 | var path = this.Options.Icon;
132 |
133 | if (path == null || path.StartsWith("res://logo"))
134 | {
135 | image.Source = string.Empty;
136 | }
137 | else
138 | if (path.StartsWith("file:///") || path.StartsWith("http"))
139 | {
140 | image.Source = path;
141 | }
142 | else
143 | if (path.StartsWith("file://"))
144 | {
145 | image.Source = path.Replace("file:/", "ms-appx:///www");
146 | }
147 | else
148 | if (path.StartsWith("res://"))
149 | {
150 | image.Source = path.Replace("res://", "ms-appx:///images");
151 | }
152 | else
153 | if (path.StartsWith("app://"))
154 | {
155 | image.Source = path.Replace("app:/", "ms-appdata://local");
156 | }
157 | else
158 | {
159 | image.Source = string.Empty;
160 | }
161 |
162 | if (image.Source.EndsWith("?crop=none"))
163 | {
164 | image.HintCrop = ToastGenericAppLogoCrop.None;
165 | }
166 | else
167 | if (image.Source.EndsWith("?crop=cirlce"))
168 | {
169 | image.HintCrop = ToastGenericAppLogoCrop.Circle;
170 | }
171 |
172 | return image;
173 | }
174 | }
175 |
176 | ///
177 | /// Gets the parsed image attachments.
178 | ///
179 | public List Attachments
180 | {
181 | get
182 | {
183 | var images = new List();
184 |
185 | if (this.Options.Attachments == null)
186 | {
187 | return images;
188 | }
189 |
190 | foreach (string path in this.Options.Attachments)
191 | {
192 | var image = new AdaptiveImage();
193 |
194 | if (path.StartsWith("file:///") || path.StartsWith("http"))
195 | {
196 | image.Source = path;
197 | }
198 | else
199 | if (path.StartsWith("file://"))
200 | {
201 | image.Source = path.Replace("file:/", "ms-appx:///www");
202 | }
203 | else
204 | if (path.StartsWith("res://"))
205 | {
206 | image.Source = path.Replace("res://", "ms-appx:///images");
207 | }
208 | else
209 | if (path.StartsWith("app://"))
210 | {
211 | image.Source = path.Replace("app:/", "ms-appdata://local");
212 | }
213 |
214 | if (image.Source != null)
215 | {
216 | images.Add(image);
217 | }
218 | }
219 |
220 | return images;
221 | }
222 | }
223 |
224 | ///
225 | /// Gets all toast buttons.
226 | ///
227 | public List Buttons
228 | {
229 | get
230 | {
231 | var buttons = new List();
232 |
233 | foreach (var action in this.Options.Actions)
234 | {
235 | if (action is Button)
236 | {
237 | buttons.Add(new ToastButton(action.Title, this.Options.GetXml(action.ID))
238 | {
239 | ActivationType = action.Launch ? ToastActivationType.Foreground : ToastActivationType.Background
240 | });
241 | }
242 | else if (action is Input && (action as Input).SubmitTitle != null)
243 | {
244 | var input = action as Input;
245 |
246 | buttons.Add(new ToastButton(input.SubmitTitle, this.Options.GetXml(input.ID))
247 | {
248 | ActivationType = input.Launch ? ToastActivationType.Foreground : ToastActivationType.Background,
249 | TextBoxId = input.ID
250 | });
251 | }
252 | }
253 |
254 | return buttons;
255 | }
256 | }
257 |
258 | ///
259 | /// Gets all toast inputs.
260 | ///
261 | public List Inputs
262 | {
263 | get
264 | {
265 | var inputs = new List();
266 |
267 | foreach (var action in this.Options.Actions)
268 | {
269 | if (!(action is Input))
270 | {
271 | continue;
272 | }
273 |
274 | inputs.Add(new ToastTextBox(action.ID)
275 | {
276 | Title = action.Title,
277 | PlaceholderContent = (action as Input).EmptyText,
278 | DefaultInput = (action as Input).DefaultValue
279 | });
280 | }
281 |
282 | return inputs;
283 | }
284 | }
285 |
286 | ///
287 | /// Gets the progress bar widget.
288 | ///
289 | public AdaptiveProgressBar ProgressBar
290 | {
291 | get
292 | {
293 | var bar = this.Options.ProgressBar;
294 |
295 | if (!bar.Enabled)
296 | {
297 | return null;
298 | }
299 |
300 | return new AdaptiveProgressBar()
301 | {
302 | Title = bar.Title,
303 | Value = new BindableProgressBarValue("progress.value"),
304 | ValueStringOverride = new BindableString("progress.description"),
305 | Status = new BindableString("progress.status")
306 | };
307 | }
308 | }
309 |
310 | ///
311 | /// Gets the instance as an serialized xml element.
312 | ///
313 | /// Element with all property values set as attributes.
314 | public string GetXml()
315 | {
316 | return this.Options.GetXml();
317 | }
318 | }
319 | }
320 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Options.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification
23 | {
24 | using global::LocalNotificationProxy.LocalNotification.Toast;
25 | using Windows.Data.Xml.Dom;
26 |
27 | public sealed class Options
28 | {
29 | ///
30 | /// Gets notification event.
31 | ///
32 | public string Action { get; private set; } = "click";
33 |
34 | ///
35 | /// Gets or sets notification ID.
36 | ///
37 | public int Id { get; set; } = 0;
38 |
39 | ///
40 | /// Gets or sets notification title.
41 | ///
42 | public string Title { get; set; }
43 |
44 | ///
45 | /// Gets or sets notification text.
46 | ///
47 | public string Text { get; set; }
48 |
49 | ///
50 | /// Gets or sets app badge number.
51 | ///
52 | public int Badge { get; set; }
53 |
54 | ///
55 | /// Gets or sets the notification sound.
56 | ///
57 | public string Sound { get; set; }
58 |
59 | ///
60 | /// Gets or sets the notification image.
61 | ///
62 | public string Icon { get; set; }
63 |
64 | ///
65 | /// Gets or sets a value indicating whether the popup shall be visible.
66 | ///
67 | public bool Silent { get; set; } = false;
68 |
69 | ///
70 | /// Gets or sets the notification trigger.
71 | ///
72 | public Toast.Trigger Trigger { get; set; }
73 |
74 | ///
75 | /// Gets or sets the notification user data.
76 | ///
77 | public string Data { get; set; }
78 |
79 | ///
80 | /// Gets or sets the notification attachments.
81 | ///
82 | public string[] Attachments { get; set; }
83 |
84 | ///
85 | /// Gets or sets the notification actions.
86 | ///
87 | public IAction[] Actions { get; set; }
88 |
89 | ///
90 | /// Gets or sets the notification progress bar.
91 | ///
92 | public ProgressBar ProgressBar { get; set; }
93 |
94 | ///
95 | /// Deserializes the XML string into an instance of Options.
96 | ///
97 | /// The serialized instance of Options as an xml string.
98 | /// An instance where all properties have been assigned.
99 | public static Options Parse(string identifier)
100 | {
101 | var doc = new XmlDocument();
102 | doc.LoadXml(identifier);
103 |
104 | var options = new Options();
105 | var node = doc.DocumentElement;
106 |
107 | options.Id = int.Parse(node.GetAttribute("id"));
108 | options.Badge = int.Parse(node.GetAttribute("badge"));
109 | options.Trigger = Toast.Trigger.Parse(node.GetAttribute("trigger"));
110 |
111 | if (node.GetAttributeNode("text") != null)
112 | {
113 | options.Text = node.GetAttribute("text");
114 | }
115 |
116 | if (node.GetAttributeNode("title") != null)
117 | {
118 | options.Title = node.GetAttribute("title");
119 | }
120 |
121 | if (node.GetAttributeNode("sound") != null)
122 | {
123 | options.Sound = node.GetAttribute("sound");
124 | }
125 |
126 | if (node.GetAttributeNode("image") != null)
127 | {
128 | options.Icon = node.GetAttribute("image");
129 | }
130 |
131 | if (node.GetAttributeNode("data") != null)
132 | {
133 | options.Data = node.GetAttribute("data");
134 | }
135 |
136 | if (node.GetAttributeNode("attachments") != null)
137 | {
138 | options.Attachments = node.GetAttribute("attachments").Split(',');
139 | }
140 |
141 | if (node.GetAttributeNode("silent") != null)
142 | {
143 | options.Silent = true;
144 | }
145 |
146 | if (node.GetAttributeNode("action") != null)
147 | {
148 | options.Action = node.GetAttribute("action");
149 | }
150 |
151 | return options;
152 | }
153 |
154 | ///
155 | /// Gets the instance as an serialized xml element.
156 | ///
157 | /// Element with all property values set as attributes.
158 | public string GetXml()
159 | {
160 | return this.GetXml(null);
161 | }
162 |
163 | ///
164 | /// Gets the instance as an serialized xml element.
165 | ///
166 | /// Optional (internal) event name.
167 | /// Element with all property values set as attributes.
168 | internal string GetXml(string action)
169 | {
170 | var node = new XmlDocument().CreateElement("options");
171 |
172 | node.SetAttribute("id", this.Id.ToString());
173 | node.SetAttribute("badge", this.Badge.ToString());
174 | node.SetAttribute("trigger", this.Trigger.GetXml());
175 |
176 | if (this.Title != null)
177 | {
178 | node.SetAttribute("title", this.Title);
179 | }
180 |
181 | if (this.Text != null)
182 | {
183 | node.SetAttribute("text", this.Text);
184 | }
185 |
186 | if (this.Sound != null)
187 | {
188 | node.SetAttribute("sound", this.Sound);
189 | }
190 |
191 | if (this.Icon != null)
192 | {
193 | node.SetAttribute("image", this.Icon);
194 | }
195 |
196 | if (this.Data != null)
197 | {
198 | node.SetAttribute("data", this.Data);
199 | }
200 |
201 | if (this.Attachments != null)
202 | {
203 | node.SetAttribute("attachments", string.Join(",", this.Attachments));
204 | }
205 |
206 | if (this.Silent)
207 | {
208 | node.SetAttribute("silent", "1");
209 | }
210 |
211 | if (action != null)
212 | {
213 | node.SetAttribute("action", action);
214 | }
215 |
216 | return node.GetXml();
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Request.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification
23 | {
24 | using System;
25 |
26 | internal class Request
27 | {
28 | ///
29 | /// The right trigger for the options
30 | ///
31 | private readonly Trigger.DateTrigger trigger;
32 |
33 | ///
34 | /// How often the trigger shall occur.
35 | ///
36 | private readonly int count;
37 |
38 | ///
39 | /// The trigger spec.
40 | ///
41 | private readonly Toast.Trigger spec;
42 |
43 | ///
44 | /// The current trigger date.
45 | ///
46 | private DateTime? triggerDate;
47 |
48 | ///
49 | /// Initializes a new instance of the class.
50 | ///
51 | /// The options spec.
52 | public Request(Options options)
53 | {
54 | this.Options = options;
55 | this.spec = options.Trigger;
56 | this.count = Math.Max(this.spec.Count, 1);
57 | this.trigger = this.BuildTrigger();
58 | this.triggerDate = this.trigger.GetNextTriggerDate(this.GetBaseDate());
59 | }
60 |
61 | ///
62 | /// Gets the options spec.
63 | ///
64 | public Options Options { get; private set; }
65 |
66 | ///
67 | /// Gets the value of the internal occurrence counter.
68 | ///
69 | public int Occurrence { get => this.trigger.Occurrence; }
70 |
71 | ///
72 | /// Gets a value indicating whether there's one more trigger date to calculate.
73 | ///
74 | public bool HasNext { get => this.triggerDate.HasValue && this.Occurrence <= this.count; }
75 |
76 | ///
77 | /// Gets the current trigger date.
78 | ///
79 | public DateTime? TriggerDate
80 | {
81 | get
82 | {
83 | if (!this.triggerDate.HasValue)
84 | {
85 | return null;
86 | }
87 |
88 | if (this.spec.Before != 0)
89 | {
90 | var before = this.ToDateTime(this.spec.Before);
91 |
92 | if (this.triggerDate.Value >= before)
93 | {
94 | return null;
95 | }
96 | }
97 |
98 | var minDate = DateTime.Now.AddSeconds(0.2);
99 |
100 | if (this.triggerDate >= minDate)
101 | {
102 | return this.triggerDate;
103 | }
104 |
105 | if ((minDate - this.triggerDate).Value.TotalMinutes <= 1)
106 | {
107 | return minDate;
108 | }
109 |
110 | return null;
111 | }
112 | }
113 |
114 | ///
115 | /// Moves the internal occurrence counter by one.
116 | ///
117 | /// false if it wasnt possible anymore to move ahead.
118 | public bool MoveNext()
119 | {
120 | if (this.HasNext)
121 | {
122 | this.triggerDate = this.GetNextTriggerDate();
123 | }
124 | else
125 | {
126 | this.triggerDate = null;
127 | }
128 |
129 | return this.triggerDate.HasValue;
130 | }
131 |
132 | ///
133 | /// Gets the next trigger date based on the current trigger date.
134 | ///
135 | /// null if there's no next one.
136 | private DateTime? GetNextTriggerDate()
137 | {
138 | if (this.triggerDate.HasValue)
139 | {
140 | return this.trigger.GetNextTriggerDate(this.triggerDate.Value);
141 | }
142 | else
143 | {
144 | return null;
145 | }
146 | }
147 |
148 | ///
149 | /// Build the trigger specified in options.
150 | ///
151 | /// Configured trigger instance
152 | private Trigger.DateTrigger BuildTrigger()
153 | {
154 | if (this.spec.Every is Toast.Every)
155 | {
156 | var matchers = this.GetMatchers();
157 | var specials = this.GetSpecials();
158 |
159 | return new Trigger.MatchTrigger(matchers, specials);
160 | }
161 |
162 | var unit = this.GetUnit();
163 | var ticks = this.GetTicks();
164 |
165 | return new Trigger.IntervalTrigger(ticks, unit);
166 | }
167 |
168 | ///
169 | /// Gets the unit value.
170 | ///
171 | /// SECOND by default.
172 | private Trigger.DateTrigger.Unit GetUnit()
173 | {
174 | var unit = "SECOND";
175 |
176 | if (!string.IsNullOrEmpty(this.spec.Unit))
177 | {
178 | unit = this.spec.Unit;
179 | }
180 | else if (this.spec.Every is string)
181 | {
182 | unit = this.spec.Every as string;
183 | }
184 |
185 | return (Trigger.DateTrigger.Unit)Enum.Parse(
186 | typeof(Trigger.DateTrigger.Unit), unit.ToUpper());
187 | }
188 |
189 | ///
190 | /// Gets the tick value.
191 | ///
192 | /// Defaults to 0
193 | private int GetTicks()
194 | {
195 | if (this.spec.At != 0)
196 | {
197 | return 0;
198 | }
199 | else if (this.spec.In != 0)
200 | {
201 | return this.spec.In;
202 | }
203 | else if (this.spec.Every is string)
204 | {
205 | return 1;
206 | }
207 | else if (this.spec.Every is double)
208 | {
209 | return Convert.ToInt32(this.spec.Every);
210 | }
211 |
212 | return 0;
213 | }
214 |
215 | ///
216 | /// Gets an array of all date parts to construct a datetime instance.
217 | ///
218 | /// [min, hour, day, month, year]
219 | private int?[] GetMatchers()
220 | {
221 | var every = this.spec.Every as Toast.Every;
222 |
223 | return new int?[]
224 | {
225 | every.Minute, every.Hour, every.Day, every.Month, every.Year
226 | };
227 | }
228 |
229 | ///
230 | /// Gets an array of all date parts to construct a datetime instance.
231 | ///
232 | /// [weekday, weekdayOrdinal, weekOfMonth, quarter]
233 | private int?[] GetSpecials()
234 | {
235 | var every = this.spec.Every as Toast.Every;
236 |
237 | return new int?[]
238 | {
239 | every.Weekday, every.WeekdayOrdinal, every.WeekOfMonth, every.Quarter
240 | };
241 | }
242 |
243 | ///
244 | /// Gets the base date from where to calculate the next trigger date.
245 | ///
246 | /// Usually points to now
247 | private DateTime GetBaseDate()
248 | {
249 | if (this.spec.At != 0)
250 | {
251 | return this.ToDateTime(this.spec.At);
252 | }
253 | else if (this.spec.FirstAt != 0)
254 | {
255 | return this.ToDateTime(this.spec.FirstAt);
256 | }
257 | else if (this.spec.After != 0)
258 | {
259 | return this.ToDateTime(this.spec.After);
260 | }
261 |
262 | return DateTime.Now;
263 | }
264 |
265 | ///
266 | /// Unix time from milliseconds.
267 | ///
268 | /// Milliseconds
269 | /// DateTime object.
270 | private DateTime ToDateTime(long ms)
271 | {
272 | return DateTimeOffset.FromUnixTimeMilliseconds(ms).LocalDateTime;
273 | }
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Button.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | public sealed class Button : IAction
25 | {
26 | ///
27 | /// Gets or sets the ID.
28 | ///
29 | public string ID { get; set; }
30 |
31 | ///
32 | /// Gets or sets the title.
33 | ///
34 | public string Title { get; set; }
35 |
36 | ///
37 | /// Gets or sets a value indicating whether to launch the app.
38 | ///
39 | public bool Launch { get; set; } = true;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Every.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | using System;
25 | using Windows.Data.Xml.Dom;
26 |
27 | public sealed class Every
28 | {
29 | ///
30 | /// Gets or sets the minute.
31 | ///
32 | public int? Minute { get; set; }
33 |
34 | ///
35 | /// Gets or sets the hour.
36 | ///
37 | public int? Hour { get; set; }
38 |
39 | ///
40 | /// Gets or sets the day.
41 | ///
42 | public int? Day { get; set; }
43 |
44 | ///
45 | /// Gets or sets the day of week.
46 | ///
47 | public int? Weekday { get; set; }
48 |
49 | ///
50 | /// Gets or sets the week of year.
51 | ///
52 | public int? Week { get; set; }
53 |
54 | ///
55 | /// Gets or sets the day of ordinal week.
56 | ///
57 | public int? WeekdayOrdinal { get; set; }
58 |
59 | ///
60 | /// Gets or sets the week of month.
61 | ///
62 | public int? WeekOfMonth { get; set; }
63 |
64 | ///
65 | /// Gets or sets the month.
66 | ///
67 | public int? Month { get; set; }
68 |
69 | ///
70 | /// Gets or sets the quarter.
71 | ///
72 | public int? Quarter { get; set; }
73 |
74 | ///
75 | /// Gets or sets the year.
76 | ///
77 | public int? Year { get; set; }
78 |
79 | ///
80 | /// Deserializes the XML string into an instance of Every.
81 | ///
82 | /// The serialized instance of Options as an xml string.
83 | /// An instance where all properties have been assigned.
84 | internal static Every Parse(string xml)
85 | {
86 | var doc = new XmlDocument();
87 | doc.LoadXml(xml);
88 |
89 | var every = new Every();
90 | var node = doc.DocumentElement;
91 |
92 | if (node.GetAttributeNode("minute") != null)
93 | {
94 | every.Minute = Convert.ToInt32(node.GetAttribute("minute"));
95 | }
96 |
97 | if (node.GetAttributeNode("hour") != null)
98 | {
99 | every.Hour = Convert.ToInt32(node.GetAttribute("hour"));
100 | }
101 |
102 | if (node.GetAttributeNode("day") != null)
103 | {
104 | every.Day = Convert.ToInt32(node.GetAttribute("day"));
105 | }
106 |
107 | if (node.GetAttributeNode("weekday") != null)
108 | {
109 | every.Weekday = Convert.ToInt32(node.GetAttribute("weekday"));
110 | }
111 |
112 | if (node.GetAttributeNode("week") != null)
113 | {
114 | every.Week = Convert.ToInt32(node.GetAttribute("week"));
115 | }
116 |
117 | if (node.GetAttributeNode("weekdayordinal") != null)
118 | {
119 | every.WeekdayOrdinal = Convert.ToInt32(node.GetAttribute("weekdayOrdinal"));
120 | }
121 |
122 | if (node.GetAttributeNode("weekOfMonth") != null)
123 | {
124 | every.WeekOfMonth = Convert.ToInt32(node.GetAttribute("weekOfMonth"));
125 | }
126 |
127 | if (node.GetAttributeNode("month") != null)
128 | {
129 | every.Month = Convert.ToInt32(node.GetAttribute("month"));
130 | }
131 |
132 | if (node.GetAttributeNode("year") != null)
133 | {
134 | every.Year = Convert.ToInt32(node.GetAttribute("year"));
135 | }
136 |
137 | return every;
138 | }
139 |
140 | ///
141 | /// Gets the instance as an serialized xml element.
142 | ///
143 | /// Element with all property values set as attributes.
144 | internal string GetXml()
145 | {
146 | var node = new XmlDocument().CreateElement("every");
147 |
148 | if (this.Minute.HasValue)
149 | {
150 | node.SetAttribute("minute", this.Minute.ToString());
151 | }
152 |
153 | if (this.Hour.HasValue)
154 | {
155 | node.SetAttribute("hour", this.Hour.ToString());
156 | }
157 |
158 | if (this.Day.HasValue)
159 | {
160 | node.SetAttribute("day", this.Day.ToString());
161 | }
162 |
163 | if (this.Weekday.HasValue)
164 | {
165 | node.SetAttribute("weekday", this.Weekday.ToString());
166 | }
167 |
168 | if (this.Week.HasValue)
169 | {
170 | node.SetAttribute("week", this.Week.ToString());
171 | }
172 |
173 | if (this.WeekdayOrdinal.HasValue)
174 | {
175 | node.SetAttribute("weekdayOrdinal", this.WeekdayOrdinal.ToString());
176 | }
177 |
178 | if (this.WeekOfMonth.HasValue)
179 | {
180 | node.SetAttribute("weekOfMonth", this.WeekOfMonth.ToString());
181 | }
182 |
183 | if (this.Month.HasValue)
184 | {
185 | node.SetAttribute("month", this.Month.ToString());
186 | }
187 |
188 | if (this.Year.HasValue)
189 | {
190 | node.SetAttribute("year", this.Year.ToString());
191 | }
192 |
193 | return node.GetXml();
194 | }
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/IAction.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | public interface IAction
25 | {
26 | ///
27 | /// Gets or sets the ID.
28 | ///
29 | string ID { get; set; }
30 |
31 | ///
32 | /// Gets or sets the title.
33 | ///
34 | string Title { get; set; }
35 |
36 | ///
37 | /// Gets or sets a value indicating whether to launch the app.
38 | ///
39 | bool Launch { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Input.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | public sealed class Input : IAction
25 | {
26 | ///
27 | /// Gets or sets the ID.
28 | ///
29 | public string ID { get; set; }
30 |
31 | ///
32 | /// Gets or sets the title.
33 | ///
34 | public string Title { get; set; }
35 |
36 | ///
37 | /// Gets or sets the title of the submit button.
38 | ///
39 | public string SubmitTitle { get; set; }
40 |
41 | ///
42 | /// Gets or sets placeholder text.
43 | ///
44 | public string EmptyText { get; set; }
45 |
46 | ///
47 | /// Gets or sets the default text.
48 | ///
49 | public string DefaultValue { get; set; }
50 |
51 | ///
52 | /// Gets or sets a value indicating whether to launch the app.
53 | ///
54 | public bool Launch { get; set; } = true;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/ProgressBar.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | public sealed class ProgressBar
25 | {
26 | ///
27 | /// Gets or sets a value indicating whether the notification has a progress bar.
28 | ///
29 | public bool Enabled { get; set; } = false;
30 |
31 | ///
32 | /// Gets or sets the title.
33 | ///
34 | public string Title { get; set; } = string.Empty;
35 |
36 | ///
37 | /// Gets or sets the value.
38 | ///
39 | public double Value { get; set; } = 0;
40 |
41 | ///
42 | /// Gets or sets the status.
43 | ///
44 | public string Status { get; set; } = string.Empty;
45 |
46 | ///
47 | /// Gets or sets the description.
48 | ///
49 | public string Description { get; set; } = string.Empty;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Trigger.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Toast
23 | {
24 | using Windows.Data.Xml.Dom;
25 |
26 | public sealed class Trigger
27 | {
28 | // private DateTime? triggerDate;
29 |
30 | ///
31 | /// Gets the trigger type.
32 | ///
33 | public string Type { get; } = "calendar";
34 |
35 | ///
36 | /// Gets or sets the fix trigger date.
37 | ///
38 | public long At { get; set; } = 0;
39 |
40 | ///
41 | /// Gets or sets the first trigger date.
42 | ///
43 | public long FirstAt { get; set; } = 0;
44 |
45 | ///
46 | /// Gets or sets the before trigger date.
47 | ///
48 | public long Before { get; set; } = 0;
49 |
50 | ///
51 | /// Gets or sets the after trigger date.
52 | ///
53 | public long After { get; set; } = 0;
54 |
55 | ///
56 | /// Gets or sets the relative trigger date from now.
57 | ///
58 | public int In { get; set; } = 0;
59 |
60 | ///
61 | /// Gets or sets the trigger count.
62 | ///
63 | public int Count { get; set; } = 1;
64 |
65 | ///
66 | /// Gets the trigger occurrence.
67 | ///
68 | public int Occurrence { get; internal set; } = 1;
69 |
70 | ///
71 | /// Gets or sets the trigger interval.
72 | ///
73 | public object Every { get; set; }
74 |
75 | ///
76 | /// Gets or sets the trigger unit.
77 | ///
78 | public string Unit { get; set; }
79 |
80 | ///
81 | /// Deserializes the XML string into an instance of Trigger.
82 | ///
83 | /// The serialized instance of Options as an xml string.
84 | /// An instance where all properties have been assigned.
85 | internal static Trigger Parse(string xml)
86 | {
87 | var doc = new XmlDocument();
88 | doc.LoadXml(xml);
89 |
90 | var trigger = new Trigger();
91 | var node = doc.DocumentElement;
92 |
93 | trigger.At = long.Parse(node.GetAttribute("at"));
94 | trigger.FirstAt = long.Parse(node.GetAttribute("firstAt"));
95 | trigger.Before = long.Parse(node.GetAttribute("before"));
96 | trigger.After = long.Parse(node.GetAttribute("after"));
97 | trigger.In = int.Parse(node.GetAttribute("in"));
98 | trigger.Count = int.Parse(node.GetAttribute("count"));
99 | trigger.Occurrence = int.Parse(node.GetAttribute("occurrence"));
100 |
101 | if (node.GetAttributeNode("unit") != null)
102 | {
103 | trigger.Unit = node.GetAttribute("unit");
104 | }
105 |
106 | if (node.GetAttributeNode("strEvery") != null)
107 | {
108 | trigger.Every = node.GetAttribute("strEvery");
109 | }
110 | else if (node.GetAttributeNode("hshEvery") != null)
111 | {
112 | trigger.Every = Toast.Every.Parse(node.GetAttribute("hshEvery"));
113 | }
114 |
115 | return trigger;
116 | }
117 |
118 | ///
119 | /// Gets the instance as an serialized xml element.
120 | ///
121 | /// Element with all property values set as attributes.
122 | internal string GetXml()
123 | {
124 | var node = new XmlDocument().CreateElement("trigger");
125 |
126 | node.SetAttribute("at", this.At.ToString());
127 | node.SetAttribute("firstAt", this.FirstAt.ToString());
128 | node.SetAttribute("before", this.Before.ToString());
129 | node.SetAttribute("after", this.After.ToString());
130 | node.SetAttribute("in", this.In.ToString());
131 | node.SetAttribute("count", this.Count.ToString());
132 | node.SetAttribute("occurrence", this.Occurrence.ToString());
133 |
134 | if (!string.IsNullOrEmpty(this.Unit))
135 | {
136 | node.SetAttribute("unit", this.Unit);
137 | }
138 |
139 | if (this.Every != null)
140 | {
141 | if (this.Every is Every)
142 | {
143 | node.SetAttribute("hshEvery", (this.Every as Every).GetXml());
144 | }
145 | else
146 | {
147 | node.SetAttribute("strEvery", this.Every.ToString());
148 | }
149 | }
150 |
151 | return node.GetXml();
152 | }
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Trigger/DateTrigger.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Trigger
23 | {
24 | using System;
25 |
26 | internal abstract class DateTrigger
27 | {
28 | ///
29 | /// Default unit is SECOND
30 | ///
31 | public enum Unit : byte
32 | {
33 | NULL, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR
34 | }
35 |
36 | ///
37 | /// Gets or sets the occurrence counter.
38 | ///
39 | public int Occurrence { get; protected set; } = 1;
40 |
41 | ///
42 | /// Gets the next trigger date.
43 | ///
44 | /// The date from where to calculate the next one.
45 | /// Null if there is no next trigger date.
46 | public abstract DateTime? GetNextTriggerDate(DateTime date);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Trigger/IntervalTrigger.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy.LocalNotification.Trigger
23 | {
24 | using System;
25 |
26 | internal class IntervalTrigger : DateTrigger
27 | {
28 | ///
29 | /// The number of ticks per interval.
30 | ///
31 | private readonly int ticks;
32 |
33 | ///
34 | /// Initializes a new instance of the class.
35 | ///
36 | /// The number of ticks per interval.
37 | /// The unit of the ticks.
38 | public IntervalTrigger(int ticks, Unit unit)
39 | {
40 | this.ticks = ticks;
41 | this.Unit = unit;
42 | }
43 |
44 | ///
45 | /// Gets the unit of the ticks
46 | ///
47 | internal new Unit Unit { get; private set; }
48 |
49 | ///
50 | /// Gets the next trigger date.
51 | ///
52 | /// The date from where to calculate the next one.
53 | /// Null if there is no next trigger date.
54 | public override DateTime? GetNextTriggerDate(DateTime date)
55 | {
56 | this.Occurrence += 1;
57 | return this.AddInterval(date);
58 | }
59 |
60 | ///
61 | /// Adds the interval to the specified date.
62 | ///
63 | /// The date where to add the interval of ticks
64 | /// A new datetime instance
65 | protected DateTime AddInterval(DateTime date)
66 | {
67 | switch (this.Unit)
68 | {
69 | case Unit.SECOND:
70 | return date.AddSeconds(this.ticks);
71 | case Unit.MINUTE:
72 | return date.AddMinutes(this.ticks);
73 | case Unit.HOUR:
74 | return date.AddHours(this.ticks);
75 | case Unit.DAY:
76 | return date.AddDays(this.ticks);
77 | case Unit.WEEK:
78 | return date.AddDays(this.ticks * 7);
79 | case Unit.MONTH:
80 | return date.AddMonths(this.ticks);
81 | case Unit.QUARTER:
82 | return date.AddMonths(this.ticks * 3);
83 | case Unit.YEAR:
84 | return date.AddYears(this.ticks);
85 | default:
86 | return date;
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotificationProxy.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache 2.0 License
3 | *
4 | * Copyright (c) Sebastian Katzer 2017
5 | *
6 | * This file contains Original Code and/or Modifications of Original Code
7 | * as defined in and that are subject to the Apache License
8 | * Version 2.0 (the 'License'). You may not use this file except in
9 | * compliance with the License. Please obtain a copy of the License at
10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this
11 | * file.
12 | *
13 | * The Original Code and all software distributed under the License are
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 | * Please see the License for the specific language governing rights and
19 | * limitations under the License.
20 | */
21 |
22 | namespace LocalNotificationProxy
23 | {
24 | using System.Runtime.InteropServices.WindowsRuntime;
25 | using LocalNotification;
26 |
27 | public sealed class LocalNotificationProxy
28 | {
29 | ///
30 | /// Manager wrapps the native SDK methods.
31 | ///
32 | private Manager manager = new Manager();
33 |
34 | ///
35 | /// Check permission to schedule notifications.
36 | ///
37 | /// True if settings are enabled
38 | public bool HasPermission()
39 | {
40 | return this.manager.Enabled;
41 | }
42 |
43 | ///
44 | /// Schedule notifications.
45 | ///
46 | /// List of key-value properties
47 | public void Schedule([ReadOnlyArray] Options[] notifications)
48 | {
49 | this.manager.Schedule(notifications);
50 | }
51 |
52 | ///
53 | /// Update notifications.
54 | ///
55 | /// List of key-value properties
56 | public void Update([ReadOnlyArray] Options[] notifications)
57 | {
58 | this.manager.Update(notifications);
59 | }
60 |
61 | ///
62 | /// Clear the notifications specified by id.
63 | ///
64 | /// The IDs of the notification to clear.
65 | /// The cleared notifications.
66 | public Options[] Clear([ReadOnlyArray] int[] ids)
67 | {
68 | return this.manager.Clear(ids).ToArray();
69 | }
70 |
71 | ///
72 | /// Clear all notifications.
73 | ///
74 | public void ClearAll()
75 | {
76 | this.manager.ClearAll();
77 | }
78 |
79 | ///
80 | /// Cancel the notifications specified by id.
81 | ///
82 | /// The IDs of the notification to clear.
83 | /// The cleared notifications.
84 | public Options[] Cancel([ReadOnlyArray] int[] ids)
85 | {
86 | return this.manager.Cancel(ids).ToArray();
87 | }
88 |
89 | ///
90 | /// Cancel all notifications.
91 | ///
92 | public void CancelAll()
93 | {
94 | this.manager.CancelAll();
95 | }
96 |
97 | ///
98 | /// Gets the type of the notification specified by ID.
99 | ///
100 | /// The ID of the notification to find for.
101 | /// The type (scheduled, triggered or unknown).
102 | public string Type(int id)
103 | {
104 | return this.manager.GetType(id.ToString()).ToString().ToLower();
105 | }
106 |
107 | ///
108 | /// List of all notifiation by id.
109 | ///
110 | /// The type of the notifications to return for.
111 | /// List of numbers
112 | public int[] Ids(int code)
113 | {
114 | var type = Notification.Type.Unknown;
115 |
116 | switch (code)
117 | {
118 | case 0:
119 | type = Notification.Type.All;
120 | break;
121 | case 1:
122 | type = Notification.Type.Scheduled;
123 | break;
124 | case 2:
125 | type = Notification.Type.Triggered;
126 | break;
127 | }
128 |
129 | return this.manager.GetIdsByType(type).ToArray();
130 | }
131 |
132 | #pragma warning disable SA1300 // Element must begin with upper-case letter
133 | ///
134 | /// Gets a single notifiation specified by id.
135 | ///
136 | /// The ID of the notification to find.
137 | /// List of options instances
138 | public Options notification(int id)
139 | {
140 | var toast = this.manager.Get(id);
141 |
142 | return toast != null ? toast.Options : null;
143 | }
144 | #pragma warning restore SA1300 // Element must begin with upper-case letter
145 |
146 | ///
147 | /// List of (all) notifiation specified by id.
148 | ///
149 | /// The type of the notifications to return for.
150 | /// Optional list of IDs to find.
151 | /// List of options instances
152 | public Options[] Notifications(int code, [ReadOnlyArray] int[] ids)
153 | {
154 | var type = Notification.Type.Unknown;
155 |
156 | switch (code)
157 | {
158 | case 0:
159 | type = Notification.Type.All;
160 | break;
161 | case 1:
162 | type = Notification.Type.Scheduled;
163 | break;
164 | case 2:
165 | type = Notification.Type.Triggered;
166 | break;
167 | case 3:
168 | return this.manager.GetOptions(ids).ToArray();
169 | }
170 |
171 | return this.manager.GetOptionsByType(type).ToArray();
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotificationProxy.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}
8 | winmdobj
9 | Properties
10 | LocalNotificationProxy
11 | LocalNotificationProxy
12 | de-DE
13 | UAP
14 | 10.0.16299.0
15 | 10.0.15063.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | false
20 |
21 |
22 | AnyCPU
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
28 | prompt
29 | 4
30 |
31 |
32 | AnyCPU
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE;NETFX_CORE;WINDOWS_UWP
37 | prompt
38 | 4
39 |
40 |
41 | x86
42 | true
43 | bin\x86\Debug\
44 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
45 | ;2008
46 | full
47 | x86
48 | false
49 | prompt
50 |
51 |
52 | x86
53 | bin\x86\Release\
54 | TRACE;NETFX_CORE;WINDOWS_UWP
55 | true
56 | ;2008
57 | pdbonly
58 | x86
59 | false
60 | prompt
61 |
62 |
63 | ARM
64 | true
65 | bin\ARM\Debug\
66 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
67 | ;2008
68 | full
69 | ARM
70 | false
71 | prompt
72 | false
73 | false
74 |
75 |
76 | ARM
77 | bin\ARM\Release\
78 | TRACE;NETFX_CORE;WINDOWS_UWP
79 | true
80 | ;2008
81 | pdbonly
82 | ARM
83 | false
84 | prompt
85 | false
86 |
87 |
88 | x64
89 | true
90 | bin\x64\Debug\
91 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
92 | ;2008
93 | full
94 | x64
95 | false
96 | prompt
97 |
98 |
99 | x64
100 | bin\x64\Release\
101 | TRACE;NETFX_CORE;WINDOWS_UWP
102 | true
103 | ;2008
104 | pdbonly
105 | x64
106 | false
107 | prompt
108 |
109 |
110 | PackageReference
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | 5.0.2
134 |
135 |
136 | 1.0.2
137 |
138 |
139 |
140 |
141 | {fb381278-f4ad-4703-a12a-c43ee0b231bd}
142 | Microsoft.Toolkit.Uwp.Notifications.UWP
143 |
144 |
145 |
146 |
147 | 14.0
148 |
149 |
150 |
157 |
--------------------------------------------------------------------------------
/src/windows/LocalNotificationProxy/LocalNotificationProxy/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("LocalNotificationProxy")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("LocalNotificationProxy")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/src/windows/lib.UW/ARM/LocalNotificationProxy.winmd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/ARM/LocalNotificationProxy.winmd
--------------------------------------------------------------------------------
/src/windows/lib.UW/ARM/Microsoft.Toolkit.Uwp.Notifications.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/ARM/Microsoft.Toolkit.Uwp.Notifications.dll
--------------------------------------------------------------------------------
/src/windows/lib.UW/x64/LocalNotificationProxy.winmd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/x64/LocalNotificationProxy.winmd
--------------------------------------------------------------------------------
/src/windows/lib.UW/x64/Microsoft.Toolkit.Uwp.Notifications.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/x64/Microsoft.Toolkit.Uwp.Notifications.dll
--------------------------------------------------------------------------------
/src/windows/lib.UW/x86/LocalNotificationProxy.winmd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/x86/LocalNotificationProxy.winmd
--------------------------------------------------------------------------------
/src/windows/lib.UW/x86/Microsoft.Toolkit.Uwp.Notifications.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timkellypa/cordova-plugin-local-notifications/083ccca0f4eee8fbec0cde1edd32207c286d2a04/src/windows/lib.UW/x86/Microsoft.Toolkit.Uwp.Notifications.dll
--------------------------------------------------------------------------------