Commit e62fff29 by Sebastián Katzer

Added plugin without --link option

parent 2ded84a9
/Users/sebastian/Documents/github/cordova-plugin-local-notifications
\ No newline at end of file
ChangeLog
---------
Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information.
#### Version 0.8.5 (22.05.2017)
- iOS 10
#### Version 0.8.4 (04.01.2016)
- Bug fixes
- SyntaxError: missing ) after argument list
#### Version 0.8.3 (03.01.2016)
- Platform enhancements
- Support for the `Crosswalk Engine`
- Support for `cordova-ios@4` and the `WKWebView Engine`
- Support for `cordova-windows@4` and `Windows 10` without using hooks
- Enhancements
- New `color` attribute for Android (Thanks to @Eusebius1920)
- New `quarter` intervall for iOS & Android
- `smallIcon` is optional (Android)
- `update` checks for permission like _schedule_
- Decreased time-frame for trigger event (iOS)
- Force `every:` to be a string on iOS
- Bug fixes
- Fixed #634 option to skip permission check
- Fixed #588 crash when basename & extension can't be extracted (Android)
- Fixed #732 loop between update and trigger (Android)
- Fixed #710 crash due to >500 notifications (Android)
- Fixed #682 crash while resuming app from notification (Android 6)
- Fixed #612 cannot update icon or sound (Android)
- Fixed crashing get(ID) if notification doesn't exist
- Fixed #569 getScheduled returns two items per notification
- Fixed #700 notifications appears on bootup
#### Version 0.8.2 (08.11.2015)
- Submitted to npm
- Initial support for the `windows` platform
- Re-add autoCancel option on Android
- Warn about unknown properties
- Fix crash on iOS 9
- Fixed webView-Problems with cordova-android 4.0
- Fix get* with single id
- Fix issue when passing data in milliseconds
- Update device plugin id
- Several other fixes
#### Version 0.8.1 (08.03.2015)
- Fix incompatibility with cordova version 3.5-3.0
- Fire `clear` instead of `cancel` event when clicked on repeating notifications
- Do not fire `clear` or `cancel` event when clicked on persistent notifications
### Version 0.8.0 (05.03.2015)
- Support for iOS 8, Android 2 (SDK >= 7) and Android 5
- Windows Phone 8.1 will be added soon
- New interfaces to ask for / register permissions required to schedule local notifications
- `hasPermission()` and `registerPermission()`
- _schedule()_ will register the permission automatically and schedule the notification if granted.
- New interface to update already scheduled|triggered local notifications
- `update()`
- New interfaces to clear the notification center
- `clear()` and `clearAll()`
- New interfaces to query for local notifications, their properties, their IDs and their existence depend on their state
- `isPresent()`, `isScheduled()`, `isTriggered()`
- `getIds()`, `getAllIds()`, `getScheduledIds()`, `getTriggeredIds()`
- `get()`, `getAll()`, `getScheduled()`, `getTriggered()`
- Schedule multiple local notifications at once
- `schedule( [{...},{...}] )`
- Update multiple local notifications at once
- `update( [{...},{...}] )`
- Clear multiple local notifications at once
- `clear( [1, 2] )`
- Cancel multiple local notifications at once
- `cancel( [1, 2] )`
- New URI format to specify sound and image resources
- `http(s):` for remote resources _(Android)_
- `file:` for local resources relative to the _www_ folder
- `res:` for native resources
- New events
- `schedule`, `update`, `clear`, `clearall` and `cancelall`
- Enhanced event informations
- Listener will get called with the local notification object instead of only the ID
- Multiple listener for one event
- `on(event, callback, scope)`
- Unregister event listener
- `un(event, callback)`
- New Android specific properties
- `led` properties
- `sound` and `image` accepts remote resources
- Callback function and scope for all interface methods
- `schedule( notification, callback, scope )`
- Renamed `add()` to `schedule()`
- `autoCancel` property has been removed
- Use `ongoing: true` for persistent local notifications on Android
- Renamed repeat intervals
- `second`, `minute`, `hour`, `day`, `week`, `month` and `year`
- Renamed some local notification properties
- `date`, `json`, `message` and `repeat`
- Scheduling local notifications with the deprecated properties is still possible
- [Kitchen Sink sample app](https://github.com/katzer/cordova-plugin-local-notifications/tree/example)
- [Wiki](https://github.com/katzer/cordova-plugin-local-notifications/wiki)
[![npm version](https://badge.fury.io/js/de.appplant.cordova.plugin.local-notification.svg)](http://badge.fury.io/js/de.appplant.cordova.plugin.local-notification)
[![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
Cordova Local-Notification Plugin
=================================
The essential purpose of local notifications is to enable an application to inform its users that it has something for them — for example, a message or an upcoming appointment — when the application isn’t running in the foreground.<br>
They are scheduled by an application and delivered on the same device.
<img width="35%" align="right" hspace="19" vspace="12" src="https://raw.githubusercontent.com/katzer/cordova-plugin-local-notifications/example/images/android.png"></img>
### How they appear to the user
Users see notifications in the following ways:
- Displaying an alert or banner
- Badging the app’s icon
- Playing a sound
### Examples of Notification Usage
Local notifications are ideally suited for applications with time-based behaviors, such as calendar and to-do list applications. Applications that run in the background for the limited period allowed by iOS might also find local notifications useful.<br>
For example, applications that depend on servers for messages or data can poll their servers for incoming items while running in the background; if a message is ready to view or an update is ready to download, they can then present a local notification immediately to inform their users.
## Supported Platforms
The current 0.8 branch supports the following platforms:
- __iOS__ _(>= 8)_<br>
- __Android__ _(SDK >=7)_
- __Windows 8.1__ _(added with v0.8.2)_
- __Windows Phone 8.1__ _(added with v0.8.2)_
- __Windows 10__ _(added with v0.8.3)_
Find out more informations [here][wiki_platforms] in our wiki.
## Installation
The plugin is installable from source and available on Cordova Plugin Registry and PhoneGap Build.
Find out more informations [here][wiki_installation] in our wiki.
## I want to get a quick overview
All wiki pages contain samples, but for a quick overview the sample section may be the fastest way.
Find out more informations [here][wiki_samples] in our wiki.
## I want to get a deep overview
The plugin supports scheduling local notifications in various ways with a single interface. It also allows you to update, clear or cancel them. There are different interfaces to query for local notifications and a complete set of events to hook into the life cycle of local notifications.
Find out more about how to schedule single, multiple, delayed or repeating local notifications [here][wiki_schedule].<br>
Informations about events like _click_ or _trigger_ can be found [here][wiki_events].
To get a deep overview we recommend to read about all the topics in our [wiki][wiki] and try out the [Kitchen Sink App][wiki_kitchensink]
## I want to see the plugin in action
The plugin offers a kitchen sink sample app. Check out the cordova project and run the app directly from your command line or preferred IDE.
Find out more informations [here][wiki_kitchensink] in our wiki.
## What's new
We are proud to announce our newest release version 0.8.x. Beside the hard work at the office and at the weekends it contains a lot of goodies, new features and easy to use APIs.
Find out more informations [here][wiki_changelog] in our wiki.
## Sample
The sample demonstrates how to schedule a local notification which repeats every week. The listener will be called when the user has clicked on the local notification.
```javascript
cordova.plugins.notification.local.schedule({
id: 1,
title: "Production Jour fixe",
text: "Duration 1h",
firstAt: monday_9_am,
every: "week",
sound: "file://sounds/reminder.mp3",
icon: "http://icons.com/?cal_id=1",
data: { meetingId:"123#fg8" }
});
cordova.plugins.notification.local.on("click", function (notification) {
joinMeeting(notification.data.meetingId);
});
```
Find out more informations [here][wiki_samples] in our wiki.
## I would like to propose new features
We appreciate any feature proposal and support for their development. Please describe them [here][feature_proposal_issue].
Find out more informations [here][wiki_next] in our wiki.
## Supporting
Your support is needed. If you use the plugin please send us a drop through the donation button.
Thank you!
[![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## License
This software is released under the [Apache 2.0 License][apache2_license].
© 2013-2016 appPlant UG, Inc. All rights reserved
[cordova]: https://cordova.apache.org
[wiki]: https://github.com/katzer/cordova-plugin-local-notifications/wiki
[wiki_platforms]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/02.-Platforms
[wiki_installation]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/03.-Installation
[wiki_kitchensink]: https://github.com/katzer/cordova-plugin-local-notifications/tree/example
[wiki_schedule]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/04.-Scheduling
[wiki_events]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/09.-Events
[wiki_samples]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/11.-Samples
[wiki_changelog]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide
[wiki_next]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/Feature-Requests
[feature_proposal_issue]: https://github.com/katzer/cordova-plugin-local-notifications/issues/451
[apache2_license]: http://opensource.org/licenses/Apache-2.0
{
"name": "de.appplant.cordova.plugin.local-notification",
"cordova_name": "Cordova LocalNotification Plugin",
"version": "0.8.5",
"description": "Schedules and queries for local notifications",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/katzer/cordova-plugin-local-notifications.git#ios10"
},
"keywords": [
"appplant",
"notification",
"local notification",
"cordova",
"ecosystem:cordova",
"cordova-android",
"cordova-ios",
"cordova-windows"
],
"platforms": [
"ios",
"android",
"windows"
],
"engines": [
{
"name": "cordova",
"version": ">=3.6.0"
},
{
"name": "cordova-plugman",
"version": ">=4.3.0"
},
{
"name": "cordova-windows",
"version": ">=4.2.0"
}
],
"dependencies": {
"cordova-plugin-device": "*",
"cordova-plugin-app-event": ">=1.1.0"
},
"author": "Sebastián Katzer",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/katzer/cordova-plugin-local-notifications/issues"
},
"homepage": "https://github.com/katzer/cordova-plugin-local-notifications#readme"
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
-->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-local-notifications"
version="0.0.0">
<name>LocalNotification</name>
<description>The plugin supports scheduling local notifications in various ways with a single interface. It also allows you to update, clear or cancel them. There are different interfaces to query for local notifications and a complete set of events to hook into the life cycle of local notifications. To get a deep overview we recommend to read about all the topics in our wiki and try out the Kitchen Sink App</description>
<repo>https://github.com/katzer/cordova-plugin-local-notifications.git</repo>
<keywords>appplant, notification, local notification, user notification</keywords>
<license>Apache 2.0</license>
<author>Sebastián Katzer</author>
<!-- cordova -->
<engines>
<engine name="cordova" version=">=3.6.0" />
<engine name="cordova-plugman" version=">=4.3.0" />
<engine name="cordova-windows" version=">=4.2.0" />
<engine name="apple-ios" version=">=10.0.0" />
</engines>
<!-- dependencies -->
<dependency id="cordova-plugin-device" />
<!-- js -->
<js-module src="www/local-notification.js" name="LocalNotification">
<clobbers target="cordova.plugins.notification.local" />
</js-module>
<js-module src="www/local-notification-core.js" name="LocalNotification.Core">
<clobbers target="cordova.plugins.notification.local.core" />
<clobbers target="plugin.notification.local.core" />
</js-module>
<js-module src="www/local-notification-util.js" name="LocalNotification.Util">
<merges target="cordova.plugins.notification.local.core" />
<merges target="plugin.notification.local.core" />
</js-module>
<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="LocalNotification">
<param name="ios-package" value="APPLocalNotification" onload="true" />
<param name="onload" value="true" />
</feature>
</config-file>
<framework src="UserNotifications.framework" />
<framework src="CoreLocation.framework" />
<header-file src="src/ios/APPLocalNotification.h" />
<source-file src="src/ios/APPLocalNotification.m" />
<header-file src="src/ios/APPNotificationContent.h" />
<source-file src="src/ios/APPNotificationContent.m" />
<header-file src="src/ios/APPNotificationOptions.h" />
<source-file src="src/ios/APPNotificationOptions.m" />
<header-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.h" />
<source-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.m" />
<header-file src="src/ios/UNNotificationRequest+APPLocalNotification.h" />
<source-file src="src/ios/UNNotificationRequest+APPLocalNotification.m" />
</platform>
<!-- android -->
<!-- <platform name="android">
<framework src="com.android.support:support-v4:+" value="gradle" />
<config-file target="res/xml/config.xml" parent="/*">
<feature name="LocalNotification">
<param name="android-package" value="de.appplant.cordova.plugin.localnotification.LocalNotification"/>
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<receiver
android:name="de.appplant.cordova.plugin.localnotification.TriggerReceiver"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.localnotification.ClearReceiver"
android:exported="false" />
<activity
android:name="de.appplant.cordova.plugin.localnotification.ClickActivity"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.NoDisplay"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.notification.TriggerReceiver"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.notification.ClearReceiver"
android:exported="false" />
<receiver android:name="de.appplant.cordova.plugin.localnotification.RestoreReceiver" android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="de.appplant.cordova.plugin.notification.ClickActivity"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.NoDisplay"
android:exported="false" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<source-file
src="src/android/LocalNotification.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/TriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/ClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/ClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/RestoreReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/notification/AbstractClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractRestoreReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractTriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AssetUtil.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Builder.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/ClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/ClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Manager.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Notification.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Options.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/TriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
</platform> -->
<!-- windows -->
<platform name="windows">
<config-file target="config.xml" parent="/*" >
<preference name="WindowsToastCapable" value="true" />
</config-file>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="x86" arch="x86" custom="true"/>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="x64" arch="x64" custom="true"/>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="ARM" arch="ARM" custom="true"/>
<js-module src="src/windows/LocalNotificationProxy.js" name="LocalNotification.Proxy" >
<merges target="" />
</js-module>
</platform>
</plugin>
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Notification;
/**
* The clear intent receiver is triggered when the user clears a
* notification manually. It un-persists the cleared notification from the
* shared preferences.
*/
public class ClearReceiver extends de.appplant.cordova.plugin.notification.ClearReceiver {
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClear (Notification notification) {
super.onClear(notification);
LocalNotification.fireEvent("clear", notification);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.TriggerReceiver;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickActivity extends de.appplant.cordova.plugin.notification.ClickActivity {
/**
* Called when local notification was clicked by the user.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClick(Notification notification) {
LocalNotification.fireEvent("click", notification);
super.onClick(notification);
if (notification.getOptions().isOngoing())
return;
String event = notification.isRepeating() ? "clear" : "cancel";
LocalNotification.fireEvent(event, notification);
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.build();
}
}
/*
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.AbstractRestoreReceiver;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
/**
* This class is triggered upon reboot of the device. It needs to re-register
* the alarms with the AlarmManager since these alarms are lost in case of
* reboot.
*/
public class RestoreReceiver extends AbstractRestoreReceiver {
/**
* Called when a local notification need to be restored.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onRestore (Notification notification) {
if (notification.isScheduled()) {
notification.schedule();
} else {
notification.cancel();
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.setClearReceiver(ClearReceiver.class)
.setClickActivity(ClickActivity.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
* reads the information in the intent and displays this information in the
* Android notification bar. The notification uses the default notification
* sound and it vibrates the phone.
*/
public class TriggerReceiver extends de.appplant.cordova.plugin.notification.TriggerReceiver {
/**
* Called when a local notification was triggered. Does present the local
* notification, re-schedule the alarm if necessary and fire trigger event.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
@Override
public void onTrigger (Notification notification, boolean updated) {
super.onTrigger(notification, updated);
if (!updated) {
LocalNotification.fireEvent("trigger", notification);
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.setClickActivity(ClickActivity.class)
.setClearReceiver(ClearReceiver.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Abstract delete receiver for local notifications. Creates the local
* notification and calls the event functions for further proceeding.
*/
abstract public class AbstractClearReceiver extends BroadcastReceiver {
/**
* Called when the notification was cleared from the notification center.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
JSONObject options;
try {
String data = bundle.getString(Options.EXTRA);
options = new JSONObject(data);
} catch (JSONException e) {
e.printStackTrace();
return;
}
Notification notification =
new Builder(context, options).build();
onClear(notification);
}
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onClear (Notification notification);
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Abstract content receiver activity for local notifications. Creates the
* local notification and calls the event functions for further proceeding.
*/
abstract public class AbstractClickActivity extends Activity {
/**
* Called when local notification was clicked to launch the main intent.
*
* @param state
* Saved instance state
*/
@Override
public void onCreate (Bundle state) {
super.onCreate(state);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
Context context = getApplicationContext();
try {
String data = bundle.getString(Options.EXTRA);
JSONObject options = new JSONObject(data);
Builder builder =
new Builder(context, options);
Notification notification =
buildNotification(builder);
onClick(notification);
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Fixes "Unable to resume activity" error.
* Theme_NoDisplay: Activities finish themselves before being resumed.
*/
@Override
protected void onResume() {
super.onResume();
finish();
}
/**
* Called when local notification was clicked by the user.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onClick (Notification notification);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
/**
* Launch main intent from package.
*/
public void launchApp() {
Context context = getApplicationContext();
String pkgName = context.getPackageName();
Intent intent = context
.getPackageManager()
.getLaunchIntentForPackage(pkgName);
intent.addFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
}
}
/*
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.json.JSONObject;
import java.util.List;
/**
* This class is triggered upon reboot of the device. It needs to re-register
* the alarms with the AlarmManager since these alarms are lost in case of
* reboot.
*/
abstract public class AbstractRestoreReceiver extends BroadcastReceiver {
/**
* Called on device reboot.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive (Context context, Intent intent) {
Manager notificationMgr =
Manager.getInstance(context);
List<JSONObject> options =
notificationMgr.getOptions();
for (JSONObject data : options) {
Builder builder = new Builder(context, data);
Notification notification =
buildNotification(builder);
onRestore(notification);
}
}
/**
* Called when a local notification need to be restored.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onRestore (Notification notification);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Calendar;
/**
* Abstract broadcast receiver for local notifications. Creates the
* notification options and calls the event functions for further proceeding.
*/
abstract public class AbstractTriggerReceiver extends BroadcastReceiver {
/**
* Called when an alarm was triggered.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Options options;
try {
String data = bundle.getString(Options.EXTRA);
JSONObject dict = new JSONObject(data);
options = new Options(context).parse(dict);
} catch (JSONException e) {
e.printStackTrace();
return;
}
if (options == null)
return;
if (isFirstAlarmInFuture(options))
return;
Builder builder = new Builder(options);
Notification notification = buildNotification(builder);
boolean updated = notification.isUpdate(false);
onTrigger(notification, updated);
}
/**
* Called when a local notification was triggered.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
abstract public void onTrigger (Notification notification, boolean updated);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
/*
* If you set a repeating alarm at 11:00 in the morning and it
* should trigger every morning at 08:00 o'clock, it will
* immediately fire. E.g. Android tries to make up for the
* 'forgotten' reminder for that day. Therefore we ignore the event
* if Android tries to 'catch up'.
*/
private Boolean isFirstAlarmInFuture (Options options) {
Notification notification = new Builder(options).build();
if (!notification.isRepeating())
return false;
Calendar now = Calendar.getInstance();
Calendar alarm = Calendar.getInstance();
alarm.setTime(notification.getOptions().getTriggerDate());
int alarmHour = alarm.get(Calendar.HOUR_OF_DAY);
int alarmMin = alarm.get(Calendar.MINUTE);
int currentHour = now.get(Calendar.HOUR_OF_DAY);
int currentMin = now.get(Calendar.MINUTE);
return (currentHour != alarmHour && currentMin != alarmMin);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import org.json.JSONObject;
import java.util.Random;
/**
* Builder class for local notifications. Build fully configured local
* notification specified by JSON object passed from JS side.
*/
public class Builder {
// Application context passed by constructor
private final Context context;
// Notification options passed by JS
private final Options options;
// Receiver to handle the trigger event
private Class<?> triggerReceiver;
// Receiver to handle the clear event
private Class<?> clearReceiver = ClearReceiver.class;
// Activity to handle the click event
private Class<?> clickActivity = ClickActivity.class;
/**
* Constructor
*
* @param context
* Application context
* @param options
* Notification options
*/
public Builder(Context context, JSONObject options) {
this.context = context;
this.options = new Options(context).parse(options);
}
/**
* Constructor
*
* @param options
* Notification options
*/
public Builder(Options options) {
this.context = options.getContext();
this.options = options;
}
/**
* Set trigger receiver.
*
* @param receiver
* Broadcast receiver
*/
public Builder setTriggerReceiver(Class<?> receiver) {
this.triggerReceiver = receiver;
return this;
}
/**
* Set clear receiver.
*
* @param receiver
* Broadcast receiver
*/
public Builder setClearReceiver(Class<?> receiver) {
this.clearReceiver = receiver;
return this;
}
/**
* Set click activity.
*
* @param activity
* Activity
*/
public Builder setClickActivity(Class<?> activity) {
this.clickActivity = activity;
return this;
}
/**
* Creates the notification with all its options passed through JS.
*/
public Notification build() {
Uri sound = options.getSoundUri();
int smallIcon = options.getSmallIcon();
int ledColor = options.getLedColor();
NotificationCompat.Builder builder;
builder = new NotificationCompat.Builder(context)
.setDefaults(0)
.setContentTitle(options.getTitle())
.setContentText(options.getText())
.setNumber(options.getBadgeNumber())
.setTicker(options.getText())
.setAutoCancel(options.isAutoClear())
.setOngoing(options.isOngoing())
.setColor(options.getColor());
if (ledColor != 0) {
builder.setLights(ledColor, 100, 100);
}
if (sound != null) {
builder.setSound(sound);
}
if (smallIcon == 0) {
builder.setSmallIcon(options.getIcon());
} else {
builder.setSmallIcon(options.getSmallIcon());
builder.setLargeIcon(options.getIconBitmap());
}
applyDeleteReceiver(builder);
applyContentReceiver(builder);
return new Notification(context, options, builder, triggerReceiver);
}
/**
* Set intent to handle the delete event. Will clean up some persisted
* preferences.
*
* @param builder
* Local notification builder instance
*/
private void applyDeleteReceiver(NotificationCompat.Builder builder) {
if (clearReceiver == null)
return;
Intent intent = new Intent(context, clearReceiver)
.setAction(options.getIdStr())
.putExtra(Options.EXTRA, options.toString());
PendingIntent deleteIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setDeleteIntent(deleteIntent);
}
/**
* Set intent to handle the click event. Will bring the app to
* foreground.
*
* @param builder
* Local notification builder instance
*/
private void applyContentReceiver(NotificationCompat.Builder builder) {
if (clickActivity == null)
return;
Intent intent = new Intent(context, clickActivity)
.putExtra(Options.EXTRA, options.toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
int reqCode = new Random().nextInt();
PendingIntent contentIntent = PendingIntent.getActivity(
context, reqCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The clear intent receiver is triggered when the user clears a
* notification manually. It un-persists the cleared notification from the
* shared preferences.
*/
public class ClearReceiver extends AbstractClearReceiver {
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClear (Notification notification) {
notification.clear();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickActivity extends AbstractClickActivity {
/**
* Called when local notification was clicked by the user. Will
* move the app to foreground.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClick(Notification notification) {
launchApp();
if (notification.isRepeating()) {
notification.clear();
} else {
notification.cancel();
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
public Notification buildNotification (Builder builder) {
return builder.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
* Wrapper class around OS notification class. Handles basic operations
* like show, delete, cancel for a single local notification instance.
*/
public class Notification {
// Used to differ notifications by their life cycle state
public enum Type {
ALL, SCHEDULED, TRIGGERED
}
// Default receiver to handle the trigger event
private static Class<?> defaultReceiver = TriggerReceiver.class;
// Key for private preferences
static final String PREF_KEY = "LocalNotification";
// Application context passed by constructor
private final Context context;
// Notification options passed by JS
private final Options options;
// Builder with full configuration
private final NotificationCompat.Builder builder;
// Receiver to handle the trigger event
private Class<?> receiver = defaultReceiver;
/**
* Constructor
*
* @param context
* Application context
* @param options
* Parsed notification options
* @param builder
* Pre-configured notification builder
*/
protected Notification (Context context, Options options,
NotificationCompat.Builder builder, Class<?> receiver) {
this.context = context;
this.options = options;
this.builder = builder;
this.receiver = receiver != null ? receiver : defaultReceiver;
}
/**
* Get application context.
*/
public Context getContext () {
return context;
}
/**
* Get notification options.
*/
public Options getOptions () {
return options;
}
/**
* Get notification ID.
*/
public int getId () {
return options.getId();
}
/**
* If it's a repeating notification.
*/
public boolean isRepeating () {
return getOptions().getRepeatInterval() > 0;
}
/**
* If the notification was in the past.
*/
public boolean wasInThePast () {
return new Date().after(options.getTriggerDate());
}
/**
* If the notification is scheduled.
*/
public boolean isScheduled () {
return isRepeating() || !wasInThePast();
}
/**
* If the notification is triggered.
*/
public boolean isTriggered () {
return wasInThePast();
}
/**
* If the notification is an update.
*
* @param keepFlag
* Set to false to remove the flag from the option map
*/
protected boolean isUpdate (boolean keepFlag) {
boolean updated = options.getDict().optBoolean("updated", false);
if (!keepFlag) {
options.getDict().remove("updated");
}
return updated;
}
/**
* Notification type can be one of pending or scheduled.
*/
public Type getType () {
return isScheduled() ? Type.SCHEDULED : Type.TRIGGERED;
}
/**
* Schedule the local notification.
*/
public void schedule() {
long triggerTime = options.getTriggerTime();
persist();
// Intent gets called when the Notification gets fired
Intent intent = new Intent(context, receiver)
.setAction(options.getIdStr())
.putExtra(Options.EXTRA, options.toString());
PendingIntent pi = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (isRepeating()) {
getAlarmMgr().setRepeating(AlarmManager.RTC_WAKEUP,
triggerTime, options.getRepeatInterval(), pi);
} else {
getAlarmMgr().set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
}
}
/**
* Clear the local notification without canceling repeating alarms.
*/
public void clear () {
if (!isRepeating() && wasInThePast())
unpersist();
if (!isRepeating())
getNotMgr().cancel(getId());
}
/**
* Cancel the local notification.
*
* Create an intent that looks similar, to the one that was registered
* using schedule. Making sure the notification id in the action is the
* same. Now we can search for such an intent using the 'getService'
* method and cancel it.
*/
public void cancel() {
Intent intent = new Intent(context, receiver)
.setAction(options.getIdStr());
PendingIntent pi = PendingIntent.
getBroadcast(context, 0, intent, 0);
getAlarmMgr().cancel(pi);
getNotMgr().cancel(options.getId());
unpersist();
}
/**
* Present the local notification to user.
*/
public void show () {
// TODO Show dialog when in foreground
showNotification();
}
/**
* Show as local notification when in background.
*/
@SuppressWarnings("deprecation")
private void showNotification () {
int id = getOptions().getId();
if (Build.VERSION.SDK_INT <= 15) {
// Notification for HoneyComb to ICS
getNotMgr().notify(id, builder.getNotification());
} else {
// Notification for Jellybean and above
getNotMgr().notify(id, builder.build());
}
}
/**
* Count of triggers since schedule.
*/
public int getTriggerCountSinceSchedule() {
long now = System.currentTimeMillis();
long triggerTime = options.getTriggerTime();
if (!wasInThePast())
return 0;
if (!isRepeating())
return 1;
return (int) ((now - triggerTime) / options.getRepeatInterval());
}
/**
* Encode options to JSON.
*/
public String toString() {
JSONObject dict = options.getDict();
JSONObject json = new JSONObject();
try {
json = new JSONObject(dict.toString());
} catch (JSONException e) {
e.printStackTrace();
}
json.remove("firstAt");
json.remove("updated");
json.remove("soundUri");
json.remove("iconUri");
return json.toString();
}
/**
* Persist the information of this notification to the Android Shared
* Preferences. This will allow the application to restore the notification
* upon device reboot, app restart, retrieve notifications, aso.
*/
private void persist () {
SharedPreferences.Editor editor = getPrefs().edit();
editor.putString(options.getIdStr(), options.toString());
if (Build.VERSION.SDK_INT < 9) {
editor.commit();
} else {
editor.apply();
}
}
/**
* Remove the notification from the Android shared Preferences.
*/
private void unpersist () {
SharedPreferences.Editor editor = getPrefs().edit();
editor.remove(options.getIdStr());
if (Build.VERSION.SDK_INT < 9) {
editor.commit();
} else {
editor.apply();
}
}
/**
* Shared private preferences for the application.
*/
private SharedPreferences getPrefs () {
return context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
}
/**
* Notification manager for the application.
*/
private NotificationManager getNotMgr () {
return (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
}
/**
* Alarm manager for the application.
*/
private AlarmManager getAlarmMgr () {
return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
/**
* Set default receiver to handle the trigger event.
*
* @param receiver
* broadcast receiver
*/
public static void setDefaultTriggerReceiver (Class<?> receiver) {
defaultReceiver = receiver;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.AlarmManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
* Wrapper around the JSON object passed through JS which contains all
* possible option values. Class provides simple readers and more advanced
* methods to convert independent values into platform specific values.
*/
public class Options {
// Key name for bundled extras
static final String EXTRA = "NOTIFICATION_OPTIONS";
// The original JSON object
private JSONObject options = new JSONObject();
// Repeat interval
private long interval = 0;
// Application context
private final Context context;
// Asset util instance
private final AssetUtil assets;
/**
* Constructor
*
* @param context
* Application context
*/
public Options(Context context){
this.context = context;
this.assets = AssetUtil.getInstance(context);
}
/**
* Parse given JSON properties.
*
* @param options
* JSON properties
*/
public Options parse (JSONObject options) {
this.options = options;
parseInterval();
parseAssets();
return this;
}
/**
* Parse repeat interval.
*/
private void parseInterval() {
String every = options.optString("every").toLowerCase();
if (every.isEmpty()) {
interval = 0;
} else
if (every.equals("second")) {
interval = 1000;
} else
if (every.equals("minute")) {
interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES / 15;
} else
if (every.equals("hour")) {
interval = AlarmManager.INTERVAL_HOUR;
} else
if (every.equals("day")) {
interval = AlarmManager.INTERVAL_DAY;
} else
if (every.equals("week")) {
interval = AlarmManager.INTERVAL_DAY * 7;
} else
if (every.equals("month")) {
interval = AlarmManager.INTERVAL_DAY * 31;
} else
if (every.equals("quarter")) {
interval = AlarmManager.INTERVAL_HOUR * 2190;
} else
if (every.equals("year")) {
interval = AlarmManager.INTERVAL_DAY * 365;
} else {
try {
interval = Integer.parseInt(every) * 60000;
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Parse asset URIs.
*/
private void parseAssets() {
if (options.has("iconUri") && !options.optBoolean("updated"))
return;
Uri iconUri = assets.parse(options.optString("icon", "res://icon"));
Uri soundUri = assets.parseSound(options.optString("sound", null));
try {
options.put("iconUri", iconUri.toString());
options.put("soundUri", soundUri.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Application context.
*/
public Context getContext () {
return context;
}
/**
* Wrapped JSON object.
*/
JSONObject getDict () {
return options;
}
/**
* Text for the local notification.
*/
public String getText() {
return options.optString("text", "");
}
/**
* Repeat interval (day, week, month, year, aso.)
*/
public long getRepeatInterval() {
return interval;
}
/**
* Badge number for the local notification.
*/
public int getBadgeNumber() {
return options.optInt("badge", 0);
}
/**
* ongoing flag for local notifications.
*/
public Boolean isOngoing() {
return options.optBoolean("ongoing", false);
}
/**
* autoClear flag for local notifications.
*/
public Boolean isAutoClear() {
return options.optBoolean("autoClear", false);
}
/**
* ID for the local notification as a number.
*/
public Integer getId() {
return options.optInt("id", 0);
}
/**
* ID for the local notification as a string.
*/
public String getIdStr() {
return getId().toString();
}
/**
* Trigger date.
*/
public Date getTriggerDate() {
return new Date(getTriggerTime());
}
/**
* Trigger date in milliseconds.
*/
public long getTriggerTime() {
return options.optLong("at", 0) * 1000;
}
/**
* Title for the local notification.
*/
public String getTitle() {
String title = options.optString("title", "");
if (title.isEmpty()) {
title = context.getApplicationInfo().loadLabel(
context.getPackageManager()).toString();
}
return title;
}
/**
* @return
* The notification color for LED
*/
public int getLedColor() {
String hex = options.optString("led", null);
if (hex == null) {
return 0;
}
int aRGB = Integer.parseInt(hex, 16);
return aRGB + 0xFF000000;
}
/**
* @return
* The notification background color for the small icon
* Returns null, if no color is given.
*/
public int getColor() {
String hex = options.optString("color", null);
if (hex == null) {
return NotificationCompat.COLOR_DEFAULT;
}
int aRGB = Integer.parseInt(hex, 16);
return aRGB + 0xFF000000;
}
/**
* Sound file path for the local notification.
*/
public Uri getSoundUri() {
Uri uri = null;
try{
uri = Uri.parse(options.optString("soundUri"));
} catch (Exception e){
e.printStackTrace();
}
return uri;
}
/**
* Icon bitmap for the local notification.
*/
public Bitmap getIconBitmap() {
Bitmap bmp;
try {
Uri uri = Uri.parse(options.optString("iconUri"));
bmp = assets.getIconFromUri(uri);
} catch (Exception e){
e.printStackTrace();
bmp = assets.getIconFromDrawable("icon");
}
return bmp;
}
/**
* Icon resource ID for the local notification.
*/
public int getIcon () {
String icon = options.optString("icon", "");
int resId = assets.getResIdForDrawable(icon);
if (resId == 0) {
resId = getSmallIcon();
}
if (resId == 0) {
resId = android.R.drawable.ic_popup_reminder;
}
return resId;
}
/**
* Small icon resource ID for the local notification.
*/
public int getSmallIcon () {
String icon = options.optString("smallIcon", "");
return assets.getResIdForDrawable(icon);
}
/**
* JSON object as string.
*/
public String toString() {
return options.toString();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
* reads the information in the intent and displays this information in the
* Android notification bar. The notification uses the default notification
* sound and it vibrates the phone.
*/
public class TriggerReceiver extends AbstractTriggerReceiver {
/**
* Called when a local notification was triggered. Does present the local
* notification and re-schedule the alarm if necessary.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
@Override
public void onTrigger (Notification notification, boolean updated) {
notification.show();
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import <Cordova/CDVPlugin.h>
@import UserNotifications;
@interface APPLocalNotification : CDVPlugin <UNUserNotificationCenterDelegate>
// Set launchDetails object
- (void) launchDetails:(CDVInvokedUrlCommand*)command;
// Execute all queued events
- (void) deviceready:(CDVInvokedUrlCommand*)command;
// Check permission to show notifications
- (void) check:(CDVInvokedUrlCommand*)command;
// Request permission to show notifications
- (void) request:(CDVInvokedUrlCommand*)command;
// Register/update an action group
- (void) registerCategory:(CDVInvokedUrlCommand*)command;
// Schedule notifications
- (void) schedule:(CDVInvokedUrlCommand*)command;
//// Update set of notifications
//- (void) update:(CDVInvokedUrlCommand*)command;
// Clear notifications by id
- (void) clear:(CDVInvokedUrlCommand*)command;
// Clear all notifications
- (void) clearAll:(CDVInvokedUrlCommand*)command;
// Cancel notifications by id
- (void) cancel:(CDVInvokedUrlCommand*)command;
// Cancel all notifications
- (void) cancelAll:(CDVInvokedUrlCommand*)command;
// Notification type
- (void) type:(CDVInvokedUrlCommand*)command;
// List of all notification IDs
- (void) ids:(CDVInvokedUrlCommand*)command;
// List of all scheduled notification IDs
- (void) scheduledIds:(CDVInvokedUrlCommand*)command;
// List of all triggered notification IDs
- (void) triggeredIds:(CDVInvokedUrlCommand*)command;
// Notification by id
- (void) notification:(CDVInvokedUrlCommand*)command;
// List of notifications by id
- (void) notifications:(CDVInvokedUrlCommand*)command;
// List of scheduled notifications by id
- (void) scheduledNotifications:(CDVInvokedUrlCommand*)command;
// List of triggered notifications by id
- (void) triggeredNotifications:(CDVInvokedUrlCommand*)command;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
@import UserNotifications;
@interface APPNotificationContent : UNMutableNotificationContent
- (id) initWithOptions:(NSDictionary*)dict;
- (APPNotificationOptions*) options;
- (UNNotificationRequest*) request;
- (UNNotificationCategory*) category;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
#import "APPNotificationOptions.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation APPNotificationContent : UNMutableNotificationContent
#pragma mark -
#pragma mark Init
/**
* Initialize a notification with the given options.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ UNMutableNotificationContent ]
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [self init];
[self setUserInfo:dict];
[self __init];
return self;
}
/**
* Initialize a notification by using the options found under userInfo.
*
* @return [ Void ]
*/
- (void) __init
{
APPNotificationOptions* options = self.options;
self.title = options.title;
self.subtitle = options.subtitle;
self.body = options.text;
self.sound = options.sound;
self.badge = options.badge;
self.attachments = options.attachments;
self.categoryIdentifier = options.categoryId;
}
#pragma mark -
#pragma mark Public
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ] options
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
}
return options;
}
/**
* The notifcations request ready to add to the notification center including
* all informations about trigger behavior.
*
* @return [ UNNotificationRequest* ]
*/
- (UNNotificationRequest*) request
{
APPNotificationOptions* opts = [self getOptions];
return [UNNotificationRequest requestWithIdentifier:opts.identifier
content:self
trigger:opts.trigger];
}
/**
* The category for the notification with all the actions.
*
* @return [ UNNotificationCategory* ]
*/
- (UNNotificationCategory*) category
{
NSString* categoryId = self.categoryIdentifier;
NSArray* actions = self.options.actions;
if (!actions.count)
return NULL;
return [UNNotificationCategory categoryWithIdentifier:categoryId
actions:actions
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
}
#pragma mark -
#pragma mark Private
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ]
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set the options used to initialize the notification.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ Void ]
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
@import UserNotifications;
@interface APPNotificationOptions : NSObject
@property (readonly, getter=id) NSNumber* id;
@property (readonly, getter=identifier) NSString* identifier;
@property (readonly, getter=categoryId) NSString* categoryId;
@property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text;
@property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
@property (readonly, getter=actions) NSArray<UNNotificationAction *> * actions;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
- (id) initWithDict:(NSDictionary*)dict;
- (UNNotificationTrigger*) trigger;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
@import UserNotifications;
@interface UNNotificationRequest (APPLocalNotification)
// The options provided by the plug-in
- (APPNotificationOptions*) options;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import "APPNotificationContent.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation UNNotificationRequest (APPLocalNotification)
/**
* Get associated option object
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set associated option object
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
* The options provided by the plug-in.
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self.content userInfo]];
[self setOptions:options];
}
return options;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
@interface UNUserNotificationCenter (APPLocalNotification)
extern NSString * const kAPPGeneralCategory;
typedef NS_ENUM(NSUInteger, APPNotificationType) {
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2,
NotifcationTypeUnknown = 3
};
#define APPNotificationType_DEFINED
@property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// Register general notification category to listen for dismiss actions
- (void) registerGeneralNotificationCategory;
// Add the specified category to the list of categories
- (void) addNotificationCategory:(UNNotificationCategory*)category;
// List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
// Find notification by ID
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
// Find notification type by ID
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id;
// Property list from all local notifications
- (NSArray*) getNotificationOptions;
// Property list from given local notifications
- (NSArray*) getNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
// Clear specified notfication
- (void) clearNotification:(UNNotificationRequest*)notification;
// Clear all notfications
- (void) clearAllNotifications;
// Cancel specified notfication
- (void) cancelNotification:(UNNotificationRequest*)notification;
// Cancel all notfications
- (void) cancelAllNotifications;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
@import UserNotifications;
NSString * const kAPPGeneralCategory = @"GENERAL";
@implementation UNUserNotificationCenter (APPLocalNotification)
#pragma mark -
#pragma mark NotificationCategory
/**
* Register general notification category to listen for dismiss actions.
*
* @return [ Void ]
*/
- (void) registerGeneralNotificationCategory
{
UNNotificationCategory* category;
category = [UNNotificationCategory
categoryWithIdentifier:kAPPGeneralCategory
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
[self setNotificationCategories:[NSSet setWithObject:category]];
}
/**
* Add the specified category to the list of categories.
*
* @param [ UNNotificationCategory* ] category The category to add.
*
* @return [ Void ]
*/
- (void) addNotificationCategory:(UNNotificationCategory*)category
{
if (!category)
return;
[self getNotificationCategoriesWithCompletionHandler:^(NSSet<UNNotificationCategory *> *set) {
NSMutableSet* categories = [NSMutableSet setWithSet:set];
for (UNNotificationCategory* item in categories) {
if ([category.identifier isEqualToString:item.identifier]) {
[categories removeObject:item];
break;
}
}
[categories addObject:category];
[self setNotificationCategories:categories];
}];
}
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all delivered or still pending notifications.
*/
- (NSArray*) getNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
[notifications addObjectsFromArray:[self getPendingNotifications]];
[notifications addObjectsFromArray:[self getDeliveredNotifications]];
return notifications;
}
/**
* List of all triggered notifications.
*/
- (NSArray*) getDeliveredNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *delivered) {
for (UNNotification* notification in delivered) {
[notifications addObject:notification.request];
}
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all pending notifications.
*/
- (NSArray*) getPendingNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
[notifications addObjectsFromArray:requests];
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all notifications from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationsByType:(APPNotificationType)type
{
switch (type) {
case NotifcationTypeScheduled:
return [self getPendingNotifications];
case NotifcationTypeTriggered:
return [self getDeliveredNotifications];
default:
return [self getNotifications];
}
}
/**
* List of all local notifications IDs.
*/
- (NSArray*) getNotificationIds
{
NSArray* notifications = [self getNotifications];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* List of all notifications IDs from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* Find notification by ID.
*
* @param id
* Notification ID
*/
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id
{
NSArray* notifications = [self getNotifications];
for (UNNotificationRequest* notification in notifications)
{
NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
return NULL;
}
/**
* Find notification type by ID
*/
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id
{
NSArray* ids = [self getNotificationIdsByType:NotifcationTypeTriggered];
if ([ids containsObject:id])
return NotifcationTypeTriggered;
ids = [self getNotificationIdsByType:NotifcationTypeScheduled];
if ([ids containsObject:id])
return NotifcationTypeScheduled;
return NotifcationTypeUnknown;
}
/**
* List of properties from all notifications.
*/
- (NSArray*) getNotificationOptions
{
return [self getNotificationOptionsByType:NotifcationTypeAll];
}
/**
* List of properties from all notifications of given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[options addObject:notification.options.userInfo];
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param ids
* Notification IDs
*/
- (NSArray*) getNotificationOptionsById:(NSArray*)ids
{
NSArray* notifications = [self getNotifications];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
if ([ids containsObject:notification.options.id]) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/*
* Clear all notfications.
*/
- (void) clearAllNotifications
{
[self removeAllDeliveredNotifications];
}
/*
* Clear Specified notfication.
*
* @param notification
* The notification object
*/
- (void) clearNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
}
/*
* Cancel all notfications.
*/
- (void) cancelAllNotifications
{
[self removeAllPendingNotificationRequests];
[self removeAllDeliveredNotifications];
}
/*
* Cancel specified notfication.
*
* @param notification
* The notification object
*/
- (void) cancelNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
[self removePendingNotificationRequestsWithIdentifiers:ids];
}
@end
/*
Copyright 2013-2015 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/**
* Executes all queued events.
*/
exports.deviceready = function () {
exports.core.deviceready();
};
/**
* Schedule a new local notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {Object[]} notifications
* Array of local notifications
*/
exports.schedule = function (success, error, notifications) {
exports.core.schedule(notifications, 'schedule');
success();
};
/**
* Update existing notifications specified by IDs in options.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {Object[]} notifications
* Array of local notifications
*/
exports.update = function (success, error, notifications) {
exports.core.update(notifications);
success();
};
/**
* Clear the specified notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.clear = function (success, error, ids) {
exports.core.clear(ids, true);
success();
};
/**
* Clear all previously sheduled notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.clearAll = function (success, error) {
exports.core.clearAll();
success();
};
/**
* Cancel the specified notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.cancel = function (success, error, ids) {
exports.core.cancel(ids, true);
success();
};
/**
* Remove all previously registered notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.cancelAll = function (success, error) {
exports.core.cancelAll();
success();
};
/**
* Check if a notification with an ID is present.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isPresent = function (success, error, args) {
var found = exports.core.isPresent(args[0]);
success(found);
};
/**
* Check if a notification with an ID is scheduled.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isScheduled = function (success, error, args) {
var found = exports.core.isScheduled(args[0]);
success(found);
};
/**
* Check if a notification with an ID was triggered.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isTriggered = function (success, error, args) {
var found = exports.core.isTriggered(args[0]);
success(found);
};
/**
* List all local notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getAllIds = function (success, error) {
var ids = exports.core.getAllIds();
success(ids);
};
/**
* List all scheduled notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getScheduledIds = function (success, error) {
var ids = exports.core.getScheduledIds();
success(ids);
};
/**
* List all triggered notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getTriggeredIds = function (success, error) {
var ids = exports.core.getTriggeredIds();
success(ids);
};
/**
* Propertys for given notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingle = function (success, error, ids) {
var notification = exports.core.getAll(ids)[0];
success(notification);
};
/**
* Propertys for given scheduled notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingleScheduled = function (success, error, ids) {
var notification = exports.core.getScheduled(ids)[0];
success(notification);
};
/**
* Propertys for given triggered notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingleTriggered = function (success, error, ids) {
var notification = exports.core.getTriggered(ids)[0];
success(notification);
};
/**
* Property list for given notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getAll = function (success, error, ids) {
var notifications = exports.core.getAll(ids);
success(notifications);
};
/**
* Property list for given triggered notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getScheduled = function (success, error, ids) {
var notifications = exports.core.getScheduled(ids);
success(notifications);
};
/**
* Property list for given triggered notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getTriggered = function (success, error, ids) {
var notifications = exports.core.getTriggered(ids);
success(notifications);
};
cordova.commandProxy.add('LocalNotification', exports);
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var LocalNotification = LocalNotificationProxy.LocalNotification,
ActivationKind = Windows.ApplicationModel.Activation.ActivationKind;
var impl = new LocalNotificationProxy.LocalNotificationProxy();
/**
* Check permission to show notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.check = function (success, error) {
var granted = impl.hasPermission();
success(granted);
};
/**
* Request permission to show notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.request = function (success, error) {
exports.check(success, error);
};
/**
* Schedule notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.schedule = function (success, error, args) {
var options = [], actions = [];
for (var i = 0, props, opts; i < args.length; i++) {
props = args[i];
opts = new LocalNotification.Options();
for (var prop in opts) {
if (prop != 'actions' && props[prop]) opts[prop] = props[prop];
}
for (var j = 0, action, btn; j < props.actions.length; j++) {
action = props.actions[j];
if (!action.type || action.type == 'button') {
btn = new LocalNotification.Button();
} else
if (action.type == 'input') {
btn = new LocalNotification.Input();
}
for (prop in btn) {
if (action[prop]) btn[prop] = action[prop];
}
actions.push(btn);
}
opts.actions = actions;
options.push(opts);
}
impl.schedule(options);
for (i = 0; i < options.length; i++) {
exports.fireEvent('add', options[i]);
}
success();
};
/**
* Clear the notifications specified by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.clear = function (success, error, args) {
var toasts = impl.clear(args) || [];
for (var i = 0; i < toasts.length; i++) {
exports.fireEvent('clear', toasts[i]);
}
success();
};
/**
* Clear all notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.clearAll = function (success, error) {
impl.clearAll();
exports.fireEvent('clearall');
success();
};
/**
* Cancel the notifications specified by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.cancel = function (success, error, args) {
var toasts = impl.cancel(args) || [];
for (var i = 0; i < toasts.length; i++) {
exports.fireEvent('cancel', toasts[i]);
}
success();
};
/**
* Cancel all notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.cancelAll = function (success, error) {
impl.cancelAll();
exports.fireEvent('cancelall');
success();
};
/**
* Get the type of notification.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.type = function (success, error, args) {
var type = impl.type(args[0]);
success(type);
};
/**
* List of all notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.ids = function (success, error) {
var ids = impl.ids() || [];
success(Array.from(ids));
};
/**
* List of all scheduled notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.scheduledIds = function (success, error) {
var ids = impl.scheduledIds() || [];
success(Array.from(ids));
};
/**
* List of all triggered notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.triggeredIds = function (success, error) {
var ids = impl.triggeredIds() || [];
success(Array.from(ids));
};
/**
* Get a single notification by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.notification = function (success, error, args) {
var obj = impl.notification(args[0]);
success(exports.clone(obj));
};
/**
* List of (all) notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.notifications = function (success, error, args) {
var objs = impl.notifications(args) || [];
success(exports.cloneAll(objs));
};
/**
* List of all scheduled notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.scheduledNotifications = function (success, error) {
var objs = impl.scheduledNotifications() || [];
success(exports.cloneAll(objs));
};
/**
* List of all triggered notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.triggeredNotifications = function (success, error) {
var objs = impl.triggeredNotifications() || [];
success(exports.cloneAll(objs));
};
/**
* Inform the user through the click event that a notification was clicked.
*
* @param [ String ] xml The launch identifier.
*
* @return [ Void ]
*/
exports.clicked = function (xml, input) {
var toast = LocalNotification.Options.parse(xml),
event = toast.action || 'click',
meta = Object.assign({}, input);
if (input && input.size > 0) {
meta.text = input.first().current.value;
}
exports.fireEvent(event, toast, meta);
};
/**
* Invoke listeners for the given event.
*
* @param [ String ] event The name of the event.
* @param [ Object ] toast Optional notification object.
* @param [ Object ] data Optional meta data about the event.
*
* @return [ Void ]
*/
exports.fireEvent = function (event, toast, data) {
var meta = Object.assign({ event: event }, data),
plugin = cordova.plugins.notification.local.core;
if (toast) {
plugin.fireEvent(event, exports.clone(toast), meta);
} else {
plugin.fireEvent(event, meta);
}
};
/**
* Clone the objects and delete internal properties.
*
* @param [ Array<Object> ] objs The objects to clone for.
*
* @return [ Array<Object> ]
*/
exports.cloneAll = function (objs) {
var clones = [];
for (var i = 0; i < objs.length; i++) {
clones.push(exports.clone(objs[i]));
}
return clones;
};
/**
* Clone the object and delete internal properties.
*
* @param [ Object ] obj The object to clone for.
*
* @return [ Object ]
*/
exports.clone = function (obj) {
var ignore = ['action'],
clone = {};
for (var prop in obj) {
if (ignore.includes(prop) || typeof obj[prop] === 'function')
continue;
try {
clone[prop] = obj[prop];
} catch (e) {
clone[prop] = null;
}
}
return clone;
};
// Handle onclick event
document.addEventListener('activated', function (e) {
if (e.kind == ActivationKind.toastNotification) {
exports.clicked(e.raw.argument, e.raw.userInput);
}
}, false);
cordova.commandProxy.add('LocalNotification', exports);

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalNotificationProxy", "LocalNotificationProxy\LocalNotificationProxy.csproj", "{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.ActiveCfg = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.Build.0 = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.ActiveCfg = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.Build.0 = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.ActiveCfg = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.Build.0 = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.Build.0 = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.ActiveCfg = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.Build.0 = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.ActiveCfg = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.Build.0 = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.ActiveCfg = Release|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;
internal class Builder
{
/// <summary>
/// Initializes a new instance of the <see cref="Builder"/> class.
/// </summary>
/// <param name="options">Notification properties to set.</param>
internal Builder(Options options)
{
this.Content = new Notification(options);
}
/// <summary>
/// Gets content
/// </summary>
public Notification Content { get; private set; }
/// <summary>
/// Gets options
/// </summary>
private Options Options { get => this.Content.Options; }
/// <summary>
/// Build a toast notification specified by the options.
/// </summary>
/// <returns>A fully configured toast notification instance.</returns>
public ScheduledToastNotification Build()
{
var toast = this.InitToast();
this.AddAttachmentsToToast(toast);
this.AddActionsToToast(toast);
return this.ConvertToastToNotification(toast);
}
/// <summary>
/// Gets the initialize skeleton for a toast notification.
/// </summary>
/// <returns>Basic skeleton with sound, image and text.</returns>
private ToastContent InitToast()
{
return new ToastContent()
{
Launch = this.Content.GetXml(),
Audio = this.Content.Sound,
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = this.Options.Title
},
new AdaptiveText()
{
Text = this.Options.Text
}
},
AppLogoOverride = this.Content.Image
}
},
Actions = new ToastActionsCustom()
{
Buttons = { },
Inputs = { }
}
};
}
/// <summary>
/// Adds attachments to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddAttachmentsToToast(ToastContent toast)
{
foreach (var image in this.Content.Attachments)
{
toast.Visual.BindingGeneric.Children.Add(image);
}
}
/// <summary>
/// Adds buttons and input fields to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddActionsToToast(ToastContent toast)
{
foreach (var btn in this.Content.Inputs)
{
(toast.Actions as ToastActionsCustom).Inputs.Add(btn);
}
foreach (var btn in this.Content.Buttons)
{
(toast.Actions as ToastActionsCustom).Buttons.Add(btn);
}
}
/// <summary>
/// Converts the toast into a notification.
/// </summary>
/// <param name="toast">The toast to convert.</param>
/// <returns>A notification ready to schedule.</returns>
private ScheduledToastNotification ConvertToastToNotification(ToastContent toast)
{
var xml = toast.GetXml();
var at = this.Content.Date;
ScheduledToastNotification notification;
if (this.Content.IsRepeating())
{
var interval = this.Content.Interval;
notification = new ScheduledToastNotification(xml, at, interval, 5);
}
else
{
notification = new ScheduledToastNotification(xml, at);
}
notification.Id = this.Options.ID.ToString();
notification.Tag = notification.Id;
return notification;
}
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Button : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public interface IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
bool Launch { get; set; }
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Input : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the title of the submit button.
/// </summary>
public string SubmitTitle { get; set; }
/// <summary>
/// Gets or sets placeholder text.
/// </summary>
public string EmptyText { get; set; }
/// <summary>
/// Gets or sets the default text.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Windows.Data.Xml.Dom;
public sealed class Options
{
/// <summary>
/// Gets notification event.
/// </summary>
public string Action { get; private set; } = "click";
/// <summary>
/// Gets or sets notification ID.
/// </summary>
public int ID { get; set; }
/// <summary>
/// Gets or sets notification title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets notification text.
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets or sets app badge number.
/// </summary>
public int Badge { get; set; }
/// <summary>
/// Gets or sets the notification sound.
/// </summary>
public string Sound { get; set; }
/// <summary>
/// Gets or sets the notification image.
/// </summary>
public string Image { get; set; }
/// <summary>
/// Gets or sets the notification fire date.
/// </summary>
public long At { get; set; }
/// <summary>
/// Gets or sets the notification repeat interval.
/// </summary>
public string Every { get; set; }
/// <summary>
/// Gets or sets the notification user data.
/// </summary>
public string Data { get; set; }
/// <summary>
/// Gets or sets the notification attachments.
/// </summary>
public string[] Attachments { get; set; }
/// <summary>
/// Gets or sets the notification actions.
/// </summary>
public IAction[] Actions { get; set; }
/// <summary>
/// Deserializes the XML string into an instance of Options.
/// </summary>
/// <param name="identifier">The serialized instance of Options as an xml string.</param>
/// <returns>An instance where all properties have been assigned.</returns>
public static Options Parse(string identifier)
{
var doc = new XmlDocument();
doc.LoadXml(identifier);
var options = new Options();
var node = doc.DocumentElement;
options.ID = int.Parse(node.GetAttribute("id"));
options.Badge = int.Parse(node.GetAttribute("badge"));
options.At = int.Parse(node.GetAttribute("at"));
if (node.GetAttributeNode("text") != null)
{
options.Text = node.GetAttribute("text");
}
if (node.GetAttributeNode("title") != null)
{
options.Title = node.GetAttribute("title");
}
if (node.GetAttributeNode("sound") != null)
{
options.Sound = node.GetAttribute("sound");
}
if (node.GetAttributeNode("image") != null)
{
options.Image = node.GetAttribute("image");
}
if (node.GetAttributeNode("every") != null)
{
options.Every = node.GetAttribute("every");
}
if (node.GetAttributeNode("data") != null)
{
options.Data = node.GetAttribute("data");
}
if (node.GetAttributeNode("action") != null)
{
options.Action = node.GetAttribute("action");
}
return options;
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <returns>Element with all property values set as attributes.</returns>
public string GetXml()
{
return this.GetXml(null);
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <param name="action">Optional (internal) event name.</param>
/// <returns>Element with all property values set as attributes.</returns>
internal string GetXml(string action)
{
var node = new XmlDocument().CreateElement("options");
node.SetAttribute("id", this.ID.ToString());
node.SetAttribute("badge", this.Badge.ToString());
node.SetAttribute("at", this.At.ToString());
if (this.Title != null)
{
node.SetAttribute("title", this.Title);
}
if (this.Text != null)
{
node.SetAttribute("text", this.Text);
}
if (this.Sound != null)
{
node.SetAttribute("sound", this.Sound);
}
if (this.Image != null)
{
node.SetAttribute("image", this.Image);
}
if (this.Every != null)
{
node.SetAttribute("every", this.Every);
}
if (this.Data != null)
{
node.SetAttribute("data", this.Data);
}
if (action != null)
{
node.SetAttribute("action", action);
}
return node.GetXml();
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment