diff --git a/CHANGELOG.md b/CHANGELOG.md
index 611e02f8b..87716553a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,45 @@ ChangeLog
Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information.
+#### 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
diff --git a/README.md b/README.md
index 878632ba0..20f853df4 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,14 @@
+[![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")
-#### :bangbang: Please vote for these cordova-windows issues :bangbang:
-1. https://issues.apache.org/jira/browse/CB-8674 _(Missing launch arguments)_
-2. https://issues.apache.org/jira/browse/CB-8946 _(Missing ToastCapable flag)_
-
-Thanks a lot!
-
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.
They are scheduled by an application and delivered on the same device.
-
+
### How they appear to the user
Users see notifications in the following ways:
@@ -29,10 +24,11 @@ For example, applications that depend on servers for messages or data can poll t
## Supported Platforms
The current 0.8 branch supports the following platforms:
-- __iOS__ _(including iOS8)_
+- __iOS__ _(>= 8)_
- __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.
@@ -119,7 +115,7 @@ Thank you!
This software is released under the [Apache 2.0 License][apache2_license].
-© 2013-2015 appPlant UG, Inc. All rights reserved
+© 2013-2016 appPlant UG, Inc. All rights reserved
[cordova]: https://cordova.apache.org
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..f4d685d29
--- /dev/null
+++ b/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "de.appplant.cordova.plugin.local-notification",
+ "cordova_name": "Cordova LocalNotification Plugin",
+ "version": "0.8.4",
+ "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"
+ },
+ "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"
+}
diff --git a/plugin.xml b/plugin.xml
index 169260784..250391e0e 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -3,7 +3,7 @@
+ version="0.8.4">
LocalNotification
@@ -20,11 +20,14 @@
-
+
+
+
+
@@ -53,8 +56,6 @@
-
-
@@ -79,7 +80,7 @@
-
+
@@ -203,6 +204,10 @@
+
+
+
+
@@ -215,14 +220,6 @@
-
-
-
-
-
-
-
-
diff --git a/scripts/windows/broadcastActivateEvent.js b/scripts/windows/broadcastActivateEvent.js
deleted file mode 100755
index 40a90ca0a..000000000
--- a/scripts/windows/broadcastActivateEvent.js
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env node
-
-/*
- * Copyright (c) 2013-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@
- */
-
-
-// Includes a snippet into the cordova-core js file
-// to fire the activated event after device is ready
-
-
-var fs = require('fs'),
- rootdir = process.argv[2];
-
-if (!rootdir)
- return;
-
-/**
- * Replaces a string with another one in a file.
- *
- * @param {String} path
- * Absolute or relative file path from cordova root project.
- * @param {String} to_replace
- * The string to replace.
- * @param {String}
- * The string to replace with.
- */
-function replace (filename, to_replace, replace_with) {
- var data = fs.readFileSync(filename, 'utf8'),
- result;
-
- if (data.indexOf(replace_with) > -1)
- return;
-
- result = data.replace(to_replace, replace_with);
- fs.writeFileSync(filename, result, 'utf8');
-}
-
-// Fires the activated event again after device is ready
-var snippet =
- "var activatedHandler = function (args) {" +
- "channel.deviceready.subscribe(function () {" +
- "app.queueEvent(args);" +
- "});" +
- "};" +
- "app.addEventListener('activated', activatedHandler, false);" +
- "document.addEventListener('deviceready', function () {" +
- "app.removeEventListener('activated', activatedHandler);" +
- "}, false);\n" +
- " app.start();";
-
-// Path to cordova-core js files where the snippet needs to be included
-var files = [
- 'platforms/windows/www/cordova.js',
- 'platforms/windows/platform_www/cordova.js'
-];
-
-// Includes the snippet before app.start() is called
-for (var i = 0; i < files.length; i++) {
- replace(files[i], 'app.start();', snippet);
-}
diff --git a/scripts/windows/setToastCapable.js b/scripts/windows/setToastCapable.js
deleted file mode 100755
index 46b561024..000000000
--- a/scripts/windows/setToastCapable.js
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env node
-
-/*
- * Copyright (c) 2013-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@
- */
-
-
-// Hook sets ToastCapable on true to enable local-notifications
-
-
-var fs = require('fs'),
- rootdir = process.argv[2];
-
-if (!rootdir)
- return;
-
-/**
- * Replaces a string with another one in a file.
- *
- * @param {String} path
- * Absolute or relative file path from cordova root project.
- * @param {String} to_replace
- * The string to replace.
- * @param {String}
- * The string to replace with.
- */
-function replace (filename, to_replace, replace_with) {
- var data = fs.readFileSync(filename, 'utf8'),
- result;
-
- if (data.indexOf('ToastCapable') > -1)
- return;
-
- result = data.replace(new RegExp(to_replace, 'g'), replace_with);
-
- fs.writeFileSync(filename, result, 'utf8');
-}
-
-// Set ToastCapable for Windows Phone
-replace('platforms/windows/package.phone.appxmanifest', ' options =
+ getNotificationMgr().getOptionsBy(type, toList(ids));
- command.success(options);
+ if (options.isEmpty()) {
+ // Status.NO_RESULT led to no callback invocation :(
+ // Status.OK led to no NPE and crash
+ result = new PluginResult(PluginResult.Status.NO_RESULT);
+ } else {
+ result = new PluginResult(PluginResult.Status.OK, options.get(0));
+ }
+
+ command.sendPluginResult(result);
}
/**
diff --git a/src/android/RestoreReceiver.java b/src/android/RestoreReceiver.java
index 7de4e3282..675ea7cab 100644
--- a/src/android/RestoreReceiver.java
+++ b/src/android/RestoreReceiver.java
@@ -44,6 +44,8 @@ public class RestoreReceiver extends AbstractRestoreReceiver {
public void onRestore (Notification notification) {
if (notification.isScheduled()) {
notification.schedule();
+ } else {
+ notification.cancel();
}
}
diff --git a/src/android/notification/AbstractClickActivity.java b/src/android/notification/AbstractClickActivity.java
index a02a9981e..5b70e1480 100644
--- a/src/android/notification/AbstractClickActivity.java
+++ b/src/android/notification/AbstractClickActivity.java
@@ -67,6 +67,16 @@ public void onCreate (Bundle state) {
}
}
+ /**
+ * 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.
*
diff --git a/src/android/notification/AbstractTriggerReceiver.java b/src/android/notification/AbstractTriggerReceiver.java
index fc6759c52..459e6d83a 100644
--- a/src/android/notification/AbstractTriggerReceiver.java
+++ b/src/android/notification/AbstractTriggerReceiver.java
@@ -70,7 +70,7 @@ public void onReceive(Context context, Intent intent) {
Builder builder = new Builder(options);
Notification notification = buildNotification(builder);
- boolean updated = notification.isUpdate();
+ boolean updated = notification.isUpdate(false);
onTrigger(notification, updated);
}
diff --git a/src/android/notification/AssetUtil.java b/src/android/notification/AssetUtil.java
index 2da8a2c3b..66662e557 100644
--- a/src/android/notification/AssetUtil.java
+++ b/src/android/notification/AssetUtil.java
@@ -42,6 +42,7 @@
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.UUID;
/**
* Util class to map unified asset URIs to native URIs. URIs like file:///
@@ -61,15 +62,15 @@ class AssetUtil {
// resources and app directory.
private final Context context;
- /**
- * Constructor
- *
- * @param context
+ /**
+ * Constructor
+ *
+ * @param context
* Application context
- */
- private AssetUtil(Context context) {
- this.context = context;
- }
+ */
+ private AssetUtil(Context context) {
+ this.context = context;
+ }
/**
* Static method to retrieve class instance.
@@ -100,223 +101,199 @@ Uri parseSound (String path) {
return parse(path);
}
- /**
- * The URI for a path.
- *
- * @param path
+ /**
+ * The URI for a path.
+ *
+ * @param path
* The given path
- */
+ */
Uri parse (String path) {
- if (path.startsWith("res:")) {
- return getUriForResourcePath(path);
- } else if (path.startsWith("file:///")) {
- return getUriFromPath(path);
- } else if (path.startsWith("file://")) {
- return getUriFromAsset(path);
- } else if (path.startsWith("http")){
- return getUriFromRemote(path);
- }
-
- return Uri.EMPTY;
- }
-
- /**
- * URI for a file.
- *
- * @param path
- * Absolute path like file:///...
- *
- * @return
- * URI pointing to the given path
- */
- private Uri getUriFromPath(String path) {
- String absPath = path.replaceFirst("file://", "");
- File file = new File(absPath);
-
- if (!file.exists()) {
- Log.e("Asset", "File not found: " + file.getAbsolutePath());
- return Uri.EMPTY;
- }
-
- return Uri.fromFile(file);
- }
-
- /**
- * URI for an asset.
- *
- * @param path
- * Asset path like file://...
- *
- * @return
+ if (path.startsWith("res:")) {
+ return getUriForResourcePath(path);
+ } else if (path.startsWith("file:///")) {
+ return getUriFromPath(path);
+ } else if (path.startsWith("file://")) {
+ return getUriFromAsset(path);
+ } else if (path.startsWith("http")){
+ return getUriFromRemote(path);
+ }
+
+ return Uri.EMPTY;
+ }
+
+ /**
+ * URI for a file.
+ *
+ * @param path
+ * Absolute path like file:///...
+ *
+ * @return
* URI pointing to the given path
- */
- private Uri getUriFromAsset(String path) {
- File dir = context.getExternalCacheDir();
+ */
+ private Uri getUriFromPath(String path) {
+ String absPath = path.replaceFirst("file://", "");
+ File file = new File(absPath);
+
+ if (!file.exists()) {
+ Log.e("Asset", "File not found: " + file.getAbsolutePath());
+ return Uri.EMPTY;
+ }
- if (dir == null) {
- Log.e("Asset", "Missing external cache dir");
- return Uri.EMPTY;
- }
+ return Uri.fromFile(file);
+ }
+ /**
+ * URI for an asset.
+ *
+ * @param path
+ * Asset path like file://...
+ *
+ * @return
+ * URI pointing to the given path
+ */
+ private Uri getUriFromAsset(String path) {
String resPath = path.replaceFirst("file:/", "www");
String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
- String storage = dir.toString() + STORAGE_FOLDER;
- File file = new File(storage, fileName);
+ File file = getTmpFile(fileName);
- //noinspection ResultOfMethodCallIgnored
- new File(storage).mkdir();
+ if (file == null) {
+ Log.e("Asset", "Missing external cache dir");
+ return Uri.EMPTY;
+ }
- try {
- AssetManager assets = context.getAssets();
- FileOutputStream outStream = new FileOutputStream(file);
- InputStream inputStream = assets.open(resPath);
+ try {
+ AssetManager assets = context.getAssets();
+ FileOutputStream outStream = new FileOutputStream(file);
+ InputStream inputStream = assets.open(resPath);
- copyFile(inputStream, outStream);
+ copyFile(inputStream, outStream);
- outStream.flush();
- outStream.close();
+ outStream.flush();
+ outStream.close();
- return Uri.fromFile(file);
+ return Uri.fromFile(file);
- } catch (Exception e) {
- Log.e("Asset", "File not found: assets/" + resPath);
- e.printStackTrace();
- }
+ } catch (Exception e) {
+ Log.e("Asset", "File not found: assets/" + resPath);
+ e.printStackTrace();
+ }
- return Uri.EMPTY;
- }
+ return Uri.EMPTY;
+ }
- /**
- * The URI for a resource.
- *
- * @param path
- * The given relative path
- *
- * @return
+ /**
+ * The URI for a resource.
+ *
+ * @param path
+ * The given relative path
+ *
+ * @return
* URI pointing to the given path
- */
- private Uri getUriForResourcePath(String path) {
- File dir = context.getExternalCacheDir();
-
- if (dir == null) {
- Log.e("Asset", "Missing external cache dir");
- return Uri.EMPTY;
- }
-
+ */
+ private Uri getUriForResourcePath(String path) {
String resPath = path.replaceFirst("res://", "");
+ int resId = getResIdForDrawable(resPath);
+ File file = getTmpFile();
- int resId = getResIdForDrawable(resPath);
-
- if (resId == 0) {
- Log.e("Asset", "File not found: " + resPath);
- return Uri.EMPTY;
- }
-
- String resName = extractResourceName(resPath);
- String extName = extractResourceExtension(resPath);
- String storage = dir.toString() + STORAGE_FOLDER;
- File file = new File(storage, resName + extName);
+ if (resId == 0) {
+ Log.e("Asset", "File not found: " + resPath);
+ return Uri.EMPTY;
+ }
- //noinspection ResultOfMethodCallIgnored
- new File(storage).mkdir();
+ if (file == null) {
+ Log.e("Asset", "Missing external cache dir");
+ return Uri.EMPTY;
+ }
- try {
- Resources res = context.getResources();
- FileOutputStream outStream = new FileOutputStream(file);
- InputStream inputStream = res.openRawResource(resId);
- copyFile(inputStream, outStream);
+ try {
+ Resources res = context.getResources();
+ FileOutputStream outStream = new FileOutputStream(file);
+ InputStream inputStream = res.openRawResource(resId);
+ copyFile(inputStream, outStream);
- outStream.flush();
- outStream.close();
+ outStream.flush();
+ outStream.close();
- return Uri.fromFile(file);
+ return Uri.fromFile(file);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
return Uri.EMPTY;
- }
+ }
- /**
- * Uri from remote located content.
+ /**
+ * Uri from remote located content.
*
- * @param path
+ * @param path
* Remote address
*
- * @return
+ * @return
* Uri of the downloaded file
- */
- private Uri getUriFromRemote(String path) {
- File dir = context.getExternalCacheDir();
+ */
+ private Uri getUriFromRemote(String path) {
+ File file = getTmpFile();
- if (dir == null) {
+ if (file == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
- String resName = extractResourceName(path);
- String extName = extractResourceExtension(path);
- String storage = dir.toString() + STORAGE_FOLDER;
- File file = new File(storage, resName + extName);
-
- //noinspection ResultOfMethodCallIgnored
- new File(storage).mkdir();
-
try {
URL url = new URL(path);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- StrictMode.ThreadPolicy policy =
- new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.ThreadPolicy policy =
+ new StrictMode.ThreadPolicy.Builder().permitAll().build();
- StrictMode.setThreadPolicy(policy);
+ StrictMode.setThreadPolicy(policy);
connection.setRequestProperty("Connection", "close");
connection.setConnectTimeout(5000);
- connection.connect();
+ connection.connect();
- InputStream input = connection.getInputStream();
- FileOutputStream outStream = new FileOutputStream(file);
+ InputStream input = connection.getInputStream();
+ FileOutputStream outStream = new FileOutputStream(file);
- copyFile(input, outStream);
+ copyFile(input, outStream);
- outStream.flush();
- outStream.close();
+ outStream.flush();
+ outStream.close();
- return Uri.fromFile(file);
+ return Uri.fromFile(file);
- } catch (MalformedURLException e) {
- Log.e("Asset", "Incorrect URL");
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- Log.e("Asset", "Failed to create new File from HTTP Content");
- e.printStackTrace();
- } catch (IOException e) {
- Log.e("Asset", "No Input can be created from http Stream");
- e.printStackTrace();
- }
+ } catch (MalformedURLException e) {
+ Log.e("Asset", "Incorrect URL");
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ Log.e("Asset", "Failed to create new File from HTTP Content");
+ e.printStackTrace();
+ } catch (IOException e) {
+ Log.e("Asset", "No Input can be created from http Stream");
+ e.printStackTrace();
+ }
return Uri.EMPTY;
- }
-
- /**
- * Copy content from input stream into output stream.
- *
- * @param in
- * The input stream
- * @param out
- * The output stream
- */
- private void copyFile(InputStream in, OutputStream out) throws IOException {
- byte[] buffer = new byte[1024];
- int read;
-
- while ((read = in.read(buffer)) != -1) {
- out.write(buffer, 0, read);
- }
- }
+ }
+
+ /**
+ * Copy content from input stream into output stream.
+ *
+ * @param in
+ * The input stream
+ * @param out
+ * The output stream
+ */
+ private void copyFile(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+ int read;
+
+ while ((read = in.read(buffer)) != -1) {
+ out.write(buffer, 0, read);
+ }
+ }
/**
* Resource ID for drawable.
@@ -343,7 +320,7 @@ int getResIdForDrawable(String resPath) {
* Resource path as string
*/
int getResIdForDrawable(String clsName, String resPath) {
- String drawable = extractResourceName(resPath);
+ String drawable = getBaseName(resPath);
int resId = 0;
try {
@@ -372,7 +349,7 @@ Bitmap getIconFromDrawable (String drawable) {
}
if (iconId == 0) {
- iconId = android.R.drawable.ic_menu_info_details;
+ iconId = android.R.drawable.screen_background_dark_transparent;
}
return BitmapFactory.decodeResource(res, iconId);
@@ -396,7 +373,7 @@ Bitmap getIconFromUri (Uri uri) throws IOException {
* @param resPath
* Resource path as string
*/
- private String extractResourceName (String resPath) {
+ private String getBaseName (String resPath) {
String drawable = resPath;
if (drawable.contains("/")) {
@@ -411,19 +388,39 @@ private String extractResourceName (String resPath) {
}
/**
- * Extract extension of drawable resource from path.
+ * Returns a file located under the external cache dir of that app.
*
- * @param resPath
- * Resource path as string
+ * @return
+ * File with a random UUID name
*/
- private String extractResourceExtension (String resPath) {
- String extName = "png";
+ private File getTmpFile () {
+ // If random UUID is not be enough see
+ // https://github.com/LukePulverenti/cordova-plugin-local-notifications/blob/267170db14044cbeff6f4c3c62d9b766b7a1dd62/src/android/notification/AssetUtil.java#L255
+ return getTmpFile(UUID.randomUUID().toString());
+ }
- if (resPath.contains(".")) {
- extName = resPath.substring(resPath.lastIndexOf('.'));
+ /**
+ * Returns a file located under the external cache dir of that app.
+ *
+ * @param name
+ * The name of the file
+ * @return
+ * File with the provided name
+ */
+ private File getTmpFile (String name) {
+ File dir = context.getExternalCacheDir();
+
+ if (dir == null) {
+ Log.e("Asset", "Missing external cache dir");
+ return null;
}
- return extName;
+ String storage = dir.toString() + STORAGE_FOLDER;
+
+ //noinspection ResultOfMethodCallIgnored
+ new File(storage).mkdir();
+
+ return new File(storage, name);
}
/**
diff --git a/src/android/notification/Builder.java b/src/android/notification/Builder.java
index a0be8b939..ab8db3dce 100644
--- a/src/android/notification/Builder.java
+++ b/src/android/notification/Builder.java
@@ -115,30 +115,36 @@ public Builder setClickActivity(Class> activity) {
* Creates the notification with all its options passed through JS.
*/
public Notification build() {
- Uri sound = options.getSoundUri();
- NotificationCompat.BigTextStyle style;
+ Uri sound = options.getSoundUri();
+ int smallIcon = options.getSmallIcon();
+ int ledColor = options.getLedColor();
NotificationCompat.Builder builder;
- style = new NotificationCompat.BigTextStyle()
- .bigText(options.getText());
-
builder = new NotificationCompat.Builder(context)
.setDefaults(0)
.setContentTitle(options.getTitle())
.setContentText(options.getText())
.setNumber(options.getBadgeNumber())
.setTicker(options.getText())
- .setSmallIcon(options.getSmallIcon())
- .setLargeIcon(options.getIconBitmap())
.setAutoCancel(options.isAutoClear())
.setOngoing(options.isOngoing())
- .setStyle(style)
- .setLights(options.getLedColor(), 500, 500);
+ .setColor(options.getColor());
+
+ if (ledColor != 0) {
+ builder.setLights(ledColor, options.getLedOnTime(), options.getLedOffTime());
+ }
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);
@@ -157,14 +163,14 @@ private void applyDeleteReceiver(NotificationCompat.Builder builder) {
if (clearReceiver == null)
return;
- Intent deleteIntent = new Intent(context, clearReceiver)
+ Intent intent = new Intent(context, clearReceiver)
.setAction(options.getIdStr())
.putExtra(Options.EXTRA, options.toString());
- PendingIntent dpi = PendingIntent.getBroadcast(
- context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent deleteIntent = PendingIntent.getBroadcast(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- builder.setDeleteIntent(dpi);
+ builder.setDeleteIntent(deleteIntent);
}
/**
@@ -183,10 +189,10 @@ private void applyContentReceiver(NotificationCompat.Builder builder) {
.putExtra(Options.EXTRA, options.toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
- int requestCode = new Random().nextInt();
+ int reqCode = new Random().nextInt();
PendingIntent contentIntent = PendingIntent.getActivity(
- context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ context, reqCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
}
diff --git a/src/android/notification/ClickActivity.java b/src/android/notification/ClickActivity.java
index 01af5c457..dcc0390dc 100644
--- a/src/android/notification/ClickActivity.java
+++ b/src/android/notification/ClickActivity.java
@@ -40,6 +40,12 @@ public class ClickActivity extends AbstractClickActivity {
@Override
public void onClick(Notification notification) {
launchApp();
+
+ if (notification.isRepeating()) {
+ notification.clear();
+ } else {
+ notification.cancel();
+ }
}
/**
diff --git a/src/android/notification/Manager.java b/src/android/notification/Manager.java
index 03ea384f9..9af3c94f2 100644
--- a/src/android/notification/Manager.java
+++ b/src/android/notification/Manager.java
@@ -31,7 +31,6 @@
import org.json.JSONObject;
import java.util.ArrayList;
-import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -121,7 +120,7 @@ public Notification update (int id, JSONObject updates, Class> receiver) {
notification.getOptions().getDict(), updates);
try {
- options.putOpt("updatedAt", new Date().getTime());
+ options.put("updated", true);
} catch (JSONException ignore) {}
return schedule(options, receiver);
@@ -193,7 +192,11 @@ public List getIds() {
ArrayList ids = new ArrayList();
for (String key : keys) {
- ids.add(Integer.parseInt(key));
+ try {
+ ids.add(Integer.parseInt(key));
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
}
return ids;
diff --git a/src/android/notification/Notification.java b/src/android/notification/Notification.java
index 5dba9d54f..ad363788d 100644
--- a/src/android/notification/Notification.java
+++ b/src/android/notification/Notification.java
@@ -138,24 +138,25 @@ public boolean isTriggered () {
/**
* If the notification is an update.
+ *
+ * @param keepFlag
+ * Set to false to remove the flag from the option map
*/
- protected boolean isUpdate () {
-
- if (!options.getDict().has("updatedAt"))
- return false;
+ protected boolean isUpdate (boolean keepFlag) {
+ boolean updated = options.getDict().optBoolean("updated", false);
- long now = new Date().getTime();
-
- long updatedAt = options.getDict().optLong("updatedAt", now);
+ if (!keepFlag) {
+ options.getDict().remove("updated");
+ }
- return (now - updatedAt) < 1000;
+ return updated;
}
/**
* Notification type can be one of pending or scheduled.
*/
public Type getType () {
- return isTriggered() ? Type.TRIGGERED : Type.SCHEDULED;
+ return isScheduled() ? Type.SCHEDULED : Type.TRIGGERED;
}
/**
@@ -184,14 +185,14 @@ public void schedule() {
/**
* Clear the local notification without canceling repeating alarms.
- *
*/
public void clear () {
- if (!isRepeating() && wasInThePast()) {
+
+ if (!isRepeating() && wasInThePast())
unpersist();
- } else {
+
+ if (!isRepeating())
getNotMgr().cancel(getId());
- }
}
/**
@@ -239,13 +240,6 @@ private void showNotification () {
}
}
- /**
- * Show as modal dialog when in foreground.
- */
- private void showDialog () {
- // TODO
- }
-
/**
* Count of triggers since schedule.
*/
@@ -276,7 +270,7 @@ public String toString() {
}
json.remove("firstAt");
- json.remove("updatedAt");
+ json.remove("updated");
json.remove("soundUri");
json.remove("iconUri");
diff --git a/src/android/notification/Options.java b/src/android/notification/Options.java
index 198a52f41..e78035958 100644
--- a/src/android/notification/Options.java
+++ b/src/android/notification/Options.java
@@ -27,6 +27,7 @@
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;
@@ -109,6 +110,9 @@ private void parseInterval() {
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 {
@@ -125,10 +129,10 @@ private void parseInterval() {
*/
private void parseAssets() {
- if (options.has("iconUri"))
+ if (options.has("iconUri") && !options.optBoolean("updated"))
return;
- Uri iconUri = assets.parse(options.optString("icon", "icon"));
+ Uri iconUri = assets.parse(options.optString("icon", "res://icon"));
Uri soundUri = assets.parseSound(options.optString("sound", null));
try {
@@ -213,10 +217,7 @@ public Date getTriggerDate() {
* Trigger date in milliseconds.
*/
public long getTriggerTime() {
- return Math.max(
- System.currentTimeMillis(),
- options.optLong("at", 0) * 1000
- );
+ return options.optLong("at", 0) * 1000;
}
/**
@@ -238,12 +239,68 @@ public String getTitle() {
* The notification color for LED
*/
public int getLedColor() {
- String hex = options.optString("led", "000000");
- int aRGB = Integer.parseInt(hex,16);
+ String hex = options.optString("led", null);
+
+ if (hex == null) {
+ return 0;
+ }
- aRGB += 0xFF000000;
+ int aRGB = Integer.parseInt(hex, 16);
- return aRGB;
+ return aRGB + 0xFF000000;
+ }
+
+ /**
+ * @return
+ * The time that the LED should be on (in milliseconds).
+ */
+ public int getLedOnTime() {
+ String timeOn = options.optString("ledOnTime", null);
+
+ if (timeOn == null) {
+ return 1000;
+ }
+
+ try {
+ return Integer.parseInt(timeOn);
+ } catch (NumberFormatException e) {
+ return 1000;
+ }
+ }
+
+ /**
+ * @return
+ * The time that the LED should be off (in milliseconds).
+ */
+ public int getLedOffTime() {
+ String timeOff = options.optString("ledOffTime", null);
+
+ if (timeOff == null) {
+ return 1000;
+ }
+
+ try {
+ return Integer.parseInt(timeOff);
+ } catch (NumberFormatException e) {
+ return 1000;
+ }
+ }
+
+ /**
+ * @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;
}
/**
@@ -265,34 +322,47 @@ public Uri getSoundUri() {
* Icon bitmap for the local notification.
*/
public Bitmap getIconBitmap() {
- String icon = options.optString("icon", "icon");
Bitmap bmp;
- try{
+ try {
Uri uri = Uri.parse(options.optString("iconUri"));
bmp = assets.getIconFromUri(uri);
} catch (Exception e){
- bmp = assets.getIconFromDrawable(icon);
+ e.printStackTrace();
+ bmp = assets.getIconFromDrawable("icon");
}
return bmp;
}
/**
- * Small icon resource ID for the local notification.
+ * Icon resource ID for the local notification.
*/
- public int getSmallIcon () {
- String icon = options.optString("smallIcon", "");
+ public int getIcon () {
+ String icon = options.optString("icon", "");
int resId = assets.getResIdForDrawable(icon);
if (resId == 0) {
- resId = android.R.drawable.screen_background_dark;
+ 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.
*/
diff --git a/src/ios/APPLocalNotification.m b/src/ios/APPLocalNotification.m
index 43cf9f8cb..03a2d23e5 100644
--- a/src/ios/APPLocalNotification.m
+++ b/src/ios/APPLocalNotification.m
@@ -25,7 +25,6 @@
#import "APPLocalNotificationOptions.h"
#import "UIApplication+APPLocalNotification.h"
#import "UILocalNotification+APPLocalNotification.h"
-#import "AppDelegate+APPRegisterUserNotificationSettings.h"
@interface APPLocalNotification ()
@@ -393,7 +392,7 @@ - (void) getOption:(CDVInvokedUrlCommand*)command
}
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
- messageAsDictionary:notifications[0]];
+ messageAsDictionary:[notifications firstObject]];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
@@ -571,12 +570,11 @@ - (void) didReceiveLocalNotification:(NSNotification*)localNotification
{
UILocalNotification* notification = [localNotification object];
- if ([notification wasUpdated])
+ if ([notification userInfo] == NULL || [notification wasUpdated])
return;
NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
-
- NSString* event = (timeInterval <= 1 && deviceready) ? @"trigger" : @"click";
+ NSString* event = timeInterval < 0.2 && deviceready ? @"trigger" : @"click";
[self fireEvent:event notification:notification];
@@ -616,8 +614,7 @@ - (void) didFinishLaunchingWithOptions:(NSNotification*)notification
*/
- (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
{
- if (_command)
- {
+ if (_command) {
[self hasPermission:_command];
_command = NULL;
}
@@ -631,25 +628,7 @@ - (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settin
*/
- (void) pluginInitialize
{
- NSNotificationCenter* center = [NSNotificationCenter
- defaultCenter];
-
eventQueue = [[NSMutableArray alloc] init];
-
- [center addObserver:self
- selector:@selector(didReceiveLocalNotification:)
- name:CDVLocalNotification
- object:nil];
-
- [center addObserver:self
- selector:@selector(didFinishLaunchingWithOptions:)
- name:UIApplicationDidFinishLaunchingNotification
- object:nil];
-
- [center addObserver:self
- selector:@selector(didRegisterUserNotificationSettings:)
- name:UIApplicationRegisterUserNotificationSettings
- object:nil];
}
/**
diff --git a/src/ios/APPLocalNotificationOptions.h b/src/ios/APPLocalNotificationOptions.h
index 73c3ef758..627ba00f7 100644
--- a/src/ios/APPLocalNotificationOptions.h
+++ b/src/ios/APPLocalNotificationOptions.h
@@ -20,6 +20,9 @@
*
* @APPPLANT_LICENSE_HEADER_END@
*/
+
+#import
+#import
@interface APPLocalNotificationOptions : NSObject
diff --git a/src/ios/APPLocalNotificationOptions.m b/src/ios/APPLocalNotificationOptions.m
index ce931ce7e..6918919b4 100644
--- a/src/ios/APPLocalNotificationOptions.m
+++ b/src/ios/APPLocalNotificationOptions.m
@@ -46,7 +46,7 @@ @implementation APPLocalNotificationOptions
*/
- (id) initWithDict:(NSDictionary*)dictionary
{
- self = [super init];
+ self = [self init];
self.dict = dictionary;
@@ -173,6 +173,9 @@ - (NSCalendarUnit) repeatInterval
else if ([interval isEqualToString:@"month"]) {
return NSCalendarUnitMonth;
}
+ else if ([interval isEqualToString:@"quarter"]) {
+ return NSCalendarUnitQuarter;
+ }
else if ([interval isEqualToString:@"year"]) {
return NSCalendarUnitYear;
}
diff --git a/src/ios/UIApplication+APPLocalNotification.m b/src/ios/UIApplication+APPLocalNotification.m
index 60b6daac3..21fab3199 100644
--- a/src/ios/UIApplication+APPLocalNotification.m
+++ b/src/ios/UIApplication+APPLocalNotification.m
@@ -188,7 +188,9 @@ - (UILocalNotification*) localNotificationWithId:(NSNumber*)id
for (UILocalNotification* notification in notifications)
{
- if ([notification.options.id isEqualToNumber:id]) {
+ NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
+
+ if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
diff --git a/src/ios/UILocalNotification+APPLocalNotification.m b/src/ios/UILocalNotification+APPLocalNotification.m
index 80012f89f..383725389 100644
--- a/src/ios/UILocalNotification+APPLocalNotification.m
+++ b/src/ios/UILocalNotification+APPLocalNotification.m
@@ -41,7 +41,7 @@ @implementation UILocalNotification (APPLocalNotification)
*/
- (id) initWithOptions:(NSDictionary*)dict
{
- self = [super init];
+ self = [self init];
[self setUserInfo:dict];
[self __init];
@@ -168,9 +168,12 @@ - (NSString*) encodeToJSON
[obj removeObjectForKey:@"updatedAt"];
+ if (obj == NULL || obj.count == 0)
+ return json;
+
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
- error:Nil];
+ error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
diff --git a/src/windows/LocalNotificationCore.js b/src/windows/LocalNotificationCore.js
index f27193e17..beb18148a 100644
--- a/src/windows/LocalNotificationCore.js
+++ b/src/windows/LocalNotificationCore.js
@@ -103,9 +103,7 @@ proxy.core = {
toast.id = options.id;
toast.tag = 'Toast' + toast.id;
- Notifications.ToastNotificationManager
- .createToastNotifier()
- .addToSchedule(toast);
+ this.getToastNotifier().addToSchedule(toast);
},
/**
@@ -326,9 +324,12 @@ proxy.core = {
ids = [];
for (var i = 0; i < toasts.length; i++) {
- var toast = toasts[i];
+ var toast = toasts[i],
+ toastId = this.getToastId(toast);
- ids.push(this.getToastId(toast));
+ if (ids.indexOf(toastId) == -1) {
+ ids.push(toastId);
+ }
}
return ids;
diff --git a/src/windows/LocalNotificationUtil.js b/src/windows/LocalNotificationUtil.js
index 4081a0b84..5679254f6 100644
--- a/src/windows/LocalNotificationUtil.js
+++ b/src/windows/LocalNotificationUtil.js
@@ -412,8 +412,8 @@ channel.onCordovaReady.subscribe(function () {
});
// Handle onclick event
-WinJS.Application.addEventListener('activated', function (args) {
- var id = args.detail.arguments,
+document.addEventListener('activated', function (e) {
+ var id = e.args,
notification = exports.getAll([id])[0];
if (!notification)
diff --git a/www/local-notification-core.js b/www/local-notification-core.js
index 03faa834e..afcc24575 100644
--- a/www/local-notification-core.js
+++ b/www/local-notification-core.js
@@ -55,52 +55,74 @@ exports.setDefaults = function (newDefaults) {
/**
* Schedule a new local notification.
*
- * @param {Object} opts
+ * @param {Object} msgs
* The notification properties
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object?} scope
* The scope for the callback function
+ * @param {Object?} args
+ * skipPermission:true schedules the notifications immediatly without
+ * registering or checking for permission
*/
-exports.schedule = function (opts, callback, scope) {
- this.registerPermission(function(granted) {
+exports.schedule = function (msgs, callback, scope, args) {
+ var fn = function(granted) {
- if (!granted)
- return;
+ if (!granted) return;
- var notifications = Array.isArray(opts) ? opts : [opts];
+ var notifications = Array.isArray(msgs) ? msgs : [msgs];
for (var i = 0; i < notifications.length; i++) {
- var properties = notifications[i];
+ var notification = notifications[i];
- this.mergeWithDefaults(properties);
- this.convertProperties(properties);
+ this.mergeWithDefaults(notification);
+ this.convertProperties(notification);
}
this.exec('schedule', notifications, callback, scope);
- }, this);
+ };
+
+ if (args && args.skipPermission) {
+ fn.call(this, true);
+ } else {
+ this.registerPermission(fn, this);
+ }
};
/**
* Update existing notifications specified by IDs in options.
*
- * @param {Object} options
+ * @param {Object} notifications
* The notification properties to update
* @param {Function} callback
* A function to be called after the notification has been updated
* @param {Object?} scope
* The scope for the callback function
+ * @param {Object?} args
+ * skipPermission:true schedules the notifications immediatly without
+ * registering or checking for permission
*/
-exports.update = function (opts, callback, scope) {
- var notifications = Array.isArray(opts) ? opts : [opts];
+exports.update = function (msgs, callback, scope, args) {
+ var fn = function(granted) {
- for (var i = 0; i < notifications.length; i++) {
- var properties = notifications[i];
+ if (!granted) return;
- this.convertProperties(properties);
- }
+ var notifications = Array.isArray(msgs) ? msgs : [msgs];
+
+ for (var i = 0; i < notifications.length; i++) {
+ var notification = notifications[i];
+
+ this.convertProperties(notification);
+ }
- this.exec('update', notifications, callback, scope);
+ this.exec('update', notifications, callback, scope);
+ };
+
+ if (args && args.skipPermission) {
+ fn.call(this, true);
+ } else {
+ this.registerPermission(fn, this);
+ }
};
/**
@@ -414,6 +436,13 @@ exports.hasPermission = function (callback, scope) {
* The callback function's scope
*/
exports.registerPermission = function (callback, scope) {
+
+ if (this._registered) {
+ return this.hasPermission(callback, scope);
+ } else {
+ this._registered = true;
+ }
+
var fn = this.createCallbackFn(callback, scope);
if (device.platform != 'iOS') {
@@ -441,6 +470,9 @@ exports.registerPermission = function (callback, scope) {
*/
exports.on = function (event, callback, scope) {
+ if (typeof callback !== "function")
+ return;
+
if (!this._listener[event]) {
this._listener[event] = [];
}
diff --git a/www/local-notification-util.js b/www/local-notification-util.js
index 7e96b64c5..e87409a66 100644
--- a/www/local-notification-util.js
+++ b/www/local-notification-util.js
@@ -44,6 +44,9 @@ exports._defaults = {
// listener
exports._listener = {};
+// Registered permission flag
+exports._registered = false;
+
/********
* UTIL *
@@ -60,11 +63,14 @@ exports.applyPlatformSpecificOptions = function () {
switch (device.platform) {
case 'Android':
- defaults.icon = 'res://icon';
- defaults.smallIcon = 'res://ic_popup_reminder';
+ defaults.icon = 'res://ic_popup_reminder';
+ defaults.smallIcon = undefined;
defaults.ongoing = false;
defaults.autoClear = true;
- defaults.led = 'FFFFFF';
+ defaults.led = undefined;
+ defaults.ledOnTime = undefined;
+ defaults.ledOffTime = undefined;
+ defaults.color = undefined;
break;
}
@@ -168,6 +174,16 @@ exports.convertProperties = function (options) {
options.data = JSON.stringify(options.data);
}
+ if (options.every) {
+ if (device.platform == 'iOS' && typeof options.every != 'string') {
+ options.every = this.getDefaults().every;
+ var warning = 'Every option is not a string: ' + options.id;
+ warning += '. Expects one of: second, minute, hour, day, week, ';
+ warning += 'month, year on iOS.';
+ console.warn(warning);
+ }
+ }
+
return options;
};
diff --git a/www/local-notification.js b/www/local-notification.js
index 9e9bd2844..fc647a6e3 100644
--- a/www/local-notification.js
+++ b/www/local-notification.js
@@ -47,29 +47,35 @@ exports.setDefaults = function (defaults) {
/**
* Schedule a new local notification.
*
- * @param {Object} opts
+ * @param {Object} notifications
* The notification properties
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object?} scope
* The scope for the callback function
+ * @param {Object?} args
+ * skipPermission:true schedules the notifications immediatly without
+ * registering or checking for permission
*/
-exports.schedule = function (opts, callback, scope) {
- this.core.schedule(opts, callback, scope);
+exports.schedule = function (notifications, callback, scope, args) {
+ this.core.schedule(notifications, callback, scope, args);
};
/**
* Update existing notifications specified by IDs in options.
*
- * @param {Object} options
+ * @param {Object} notifications
* The notification properties to update
* @param {Function} callback
* A function to be called after the notification has been updated
* @param {Object?} scope
* The scope for the callback function
+ * @param {Object?} args
+ * skipPermission:true schedules the notifications immediatly without
+ * registering or checking for permission
*/
-exports.update = function (opts, callback, scope) {
- this.core.update(opts, callback, scope);
+exports.update = function (notifications, callback, scope, args) {
+ this.core.update(notifications, callback, scope, args);
};
/**
@@ -366,5 +372,5 @@ exports.on = function (event, callback, scope) {
* The function to be exec as callback
*/
exports.un = function (event, callback) {
- this.core.un(event, callback, scope);
+ this.core.un(event, callback);
};