Commit b13eb184 by PKnittel

Istalled latest version of local-notification

The latest Version provides more Feature
parent 03758444
...@@ -18,7 +18,7 @@ module.exports = [ ...@@ -18,7 +18,7 @@ module.exports = [
module.exports.metadata = module.exports.metadata =
// TOP OF METADATA // TOP OF METADATA
{ {
"de.appplant.cordova.plugin.local-notification": "0.7.6", "de.appplant.cordova.plugin.local-notification": "0.8.0dev",
"org.apache.cordova.device": "0.2.14-dev" "org.apache.cordova.device": "0.2.14-dev"
} }
// BOTTOM OF METADATA // BOTTOM OF METADATA
......
/* /*
* Licensed to the Apache Software Foundation (ASF) under one Copyright 2013-2014 appPlant UG
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information Licensed to the Apache Software Foundation (ASF) under one
* regarding copyright ownership. The ASF licenses this file or more contributor license agreements. See the NOTICE file
* to you under the Apache License, Version 2.0 (the distributed with this work for additional information
* "License"); you may not use this file except in compliance regarding copyright ownership. The ASF licenses this file
* with the License. You may obtain a copy of the License at to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* http://www.apache.org/licenses/LICENSE-2.0 with the License. You may obtain a copy of the License at
*
* Unless required by applicable law or agreed to in writing, http://www.apache.org/licenses/LICENSE-2.0
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY Unless required by applicable law or agreed to in writing,
* KIND, either express or implied. See the License for the software distributed under the License is distributed on an
* specific language governing permissions and limitations "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* under the License. KIND, either express or implied. See the License for the
*/ specific language governing permissions and limitations
under the License.
*/
* { * {
-webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */ -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
} }
......
<!DOCTYPE html> <!DOCTYPE html>
<!-- <!--
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
distributed with this work for additional information distributed with this work for additional information
...@@ -8,12 +10,12 @@ ...@@ -8,12 +10,12 @@
"License"); you may not use this file except in compliance "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the KIND, either express or implied. See the License for the
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
--> -->
......
...@@ -58,10 +58,14 @@ LocalNotification.prototype = { ...@@ -58,10 +58,14 @@ LocalNotification.prototype = {
/** /**
* @private * @private
* Merge settings with default values *
* Merges custom properties with the default values.
* *
* @param {Object} options * @param {Object} options
* Set of custom values
*
* @retrun {Object} * @retrun {Object}
* The merged property list
*/ */
mergeWithDefaults: function (options) { mergeWithDefaults: function (options) {
var defaults = this.getDefaults(); var defaults = this.getDefaults();
...@@ -77,6 +81,11 @@ LocalNotification.prototype = { ...@@ -77,6 +81,11 @@ LocalNotification.prototype = {
/** /**
* @private * @private
*
* Merges the platform specific properties into the default properties.
*
* @return {Object}
* The default properties for the platform
*/ */
applyPlatformSpecificOptions: function () { applyPlatformSpecificOptions: function () {
var defaults = this._defaults; var defaults = this._defaults;
...@@ -86,6 +95,7 @@ LocalNotification.prototype = { ...@@ -86,6 +95,7 @@ LocalNotification.prototype = {
defaults.icon = 'icon'; defaults.icon = 'icon';
defaults.smallIcon = null; defaults.smallIcon = null;
defaults.ongoing = false; defaults.ongoing = false;
defaults.led = 'FFFFFF'; /*RRGGBB*/
defaults.sound = 'TYPE_NOTIFICATION'; break; defaults.sound = 'TYPE_NOTIFICATION'; break;
case 'iOS': case 'iOS':
defaults.sound = ''; break; defaults.sound = ''; break;
...@@ -93,6 +103,30 @@ LocalNotification.prototype = { ...@@ -93,6 +103,30 @@ LocalNotification.prototype = {
defaults.smallImage = null; defaults.smallImage = null;
defaults.image = null; defaults.image = null;
defaults.wideImage = null; defaults.wideImage = null;
}
return defaults;
},
/**
* @private
*
* Creates a callback, which will be executed within a specific scope.
*
* @param {Function} callbackFn
* The callback function
* @param {Object} scope
* The scope for the function
*
* @return {Function}
* The new callback function
*/
createCallbackFn: function (callbackFn, scope) {
if (typeof callbackFn != 'function')
return;
return function () {
callbackFn.apply(scope || this, arguments);
}; };
}, },
...@@ -100,11 +134,18 @@ LocalNotification.prototype = { ...@@ -100,11 +134,18 @@ LocalNotification.prototype = {
* Add a new entry to the registry * Add a new entry to the registry
* *
* @param {Object} options * @param {Object} options
* @return {Number} The notification's ID * 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
*
* @return {Number}
* The notification's ID
*/ */
add: function (options) { add: function (options, callback, scope) {
var options = this.mergeWithDefaults(options), var options = this.mergeWithDefaults(options),
callbackFn = null; callbackFn = this.createCallbackFn(callback, scope);
if (options.id) { if (options.id) {
options.id = options.id.toString(); options.id = options.id.toString();
...@@ -114,11 +155,19 @@ LocalNotification.prototype = { ...@@ -114,11 +155,19 @@ LocalNotification.prototype = {
options.date = new Date(); options.date = new Date();
} }
if (options.title) {
options.title = options.title.toString();
}
if (options.message) {
options.message = options.message.toString();
}
if (typeof options.date == 'object') { if (typeof options.date == 'object') {
options.date = Math.round(options.date.getTime()/1000); options.date = Math.round(options.date.getTime()/1000);
} }
if (['WinCE', 'Win32NT'].indexOf(device.platform)) { if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
callbackFn = function (cmd) { callbackFn = function (cmd) {
eval(cmd); eval(cmd);
}; };
...@@ -130,100 +179,143 @@ LocalNotification.prototype = { ...@@ -130,100 +179,143 @@ LocalNotification.prototype = {
}, },
/** /**
* Cancels the specified notification * Cancels the specified notification.
* *
* @param {String} id of the notification * @param {String} id
* The ID of the notification
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*/ */
cancel: function (id) { cancel: function (id, callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'cancel', [id.toString()]); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancel', [id]);
}, },
/** /**
* Removes all previously registered notifications * Removes all previously registered notifications.
*
* @param {Function} callback
* A function to be called after all notifications have been canceled
* @param {Object} scope
* The scope for the callback function
*/ */
cancelAll: function () { cancelAll: function (callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'cancelAll', []); var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancelAll', []);
}, },
/** /**
* @async
*
* Retrieves a list with all currently pending notifications. * Retrieves a list with all currently pending notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
getScheduledIds: function (callback) { getScheduledIds: function (callback, scope) {
cordova.exec(callback, null, 'LocalNotification', 'getScheduledIds', []); var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'getScheduledIds', []);
}, },
/** /**
* @async
*
* Checks wether a notification with an ID is scheduled. * Checks wether a notification with an ID is scheduled.
* *
* @param {String} id * @param {String} id
* The ID of the notification
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
isScheduled: function (id, callback) { isScheduled: function (id, callback, scope) {
cordova.exec(callback, null, 'LocalNotification', 'isScheduled', [id.toString()]); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isScheduled', [id]);
}, },
/** /**
* Informs if the app has the permission to show badges. * Retrieves a list with all triggered notifications.
* *
* @param {Function} callback * @param {Function} callback
* The function to be exec as the callback * A callback function to be called with the list
* @param {Object?} scope * @param {Object} scope
* The callback function's scope * The scope for the callback function
*/ */
hasPermission: function (callback, scope) { getTriggeredIds: function (callback, scope) {
var fn = function (badge) { var callbackFn = this.createCallbackFn(callback, scope);
callback.call(scope || this, badge);
};
cordova.exec(fn, null, 'LocalNotification', 'hasPermission', []); cordova.exec(callbackFn, null, 'LocalNotification', 'getTriggeredIds', []);
}, },
/** /**
* Ask for permission to show badges if not already granted. * Checks wether a notification with an ID was triggered.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
promptForPermission: function () { isTriggered: function (id, callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'promptForPermission', []); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isTriggered', [id]);
}, },
/** /**
* Occurs when a notification was added. * Occurs when a notification was added.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
onadd: function (id, state, json) {}, onadd: function (id, state, json) {},
/** /**
* Occurs when the notification is triggered. * Occurs when the notification is triggered.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
ontrigger: function (id, state, json) {}, ontrigger: function (id, state, json) {},
/** /**
* Fires after the notification was clicked. * Fires after the notification was clicked.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
onclick: function (id, state, json) {}, onclick: function (id, state, json) {},
/** /**
* Fires if the notification was canceled. * Fires if the notification was canceled.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
oncancel: function (id, state, json) {} oncancel: function (id, state, json) {}
}; };
...@@ -231,24 +323,32 @@ LocalNotification.prototype = { ...@@ -231,24 +323,32 @@ LocalNotification.prototype = {
var plugin = new LocalNotification(), var plugin = new LocalNotification(),
channel = require('cordova/channel'); channel = require('cordova/channel');
// Called after all 'deviceready' listener are called
channel.deviceready.subscribe( function () { channel.deviceready.subscribe( function () {
// Device is ready now, the listeners are registered and all queued events
// can be executed now.
cordova.exec(null, null, 'LocalNotification', 'deviceready', []); cordova.exec(null, null, 'LocalNotification', 'deviceready', []);
}); });
channel.onCordovaReady.subscribe( function () { channel.onCordovaReady.subscribe( function () {
// The cordova device plugin is ready now
channel.onCordovaInfoReady.subscribe( function () { channel.onCordovaInfoReady.subscribe( function () {
if (device.platform == 'Android') { if (device.platform == 'Android') {
channel.onPause.subscribe( function () { channel.onPause.subscribe( function () {
// Necessary to set the state to `background`
cordova.exec(null, null, 'LocalNotification', 'pause', []); cordova.exec(null, null, 'LocalNotification', 'pause', []);
}); });
channel.onResume.subscribe( function () { channel.onResume.subscribe( function () {
// Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); cordova.exec(null, null, 'LocalNotification', 'resume', []);
}); });
// Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); cordova.exec(null, null, 'LocalNotification', 'resume', []);
} }
// Merges the platform specific properties into the default properties
plugin.applyPlatformSpecificOptions(); plugin.applyPlatformSpecificOptions();
}); });
}); });
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -41,6 +42,7 @@ import android.content.Context; ...@@ -41,6 +42,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.os.Build;
/** /**
* This plugin utilizes the Android AlarmManager in combination with StatusBar * This plugin utilizes the Android AlarmManager in combination with StatusBar
...@@ -67,7 +69,7 @@ public class LocalNotification extends CordovaPlugin { ...@@ -67,7 +69,7 @@ public class LocalNotification extends CordovaPlugin {
} }
@Override @Override
public boolean execute (String action, final JSONArray args, CallbackContext callbackContext) throws JSONException { public boolean execute (String action, final JSONArray args, final CallbackContext command) throws JSONException {
if (action.equalsIgnoreCase("add")) { if (action.equalsIgnoreCase("add")) {
cordova.getThreadPool().execute( new Runnable() { cordova.getThreadPool().execute( new Runnable() {
public void run() { public void run() {
...@@ -76,10 +78,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -76,10 +78,9 @@ public class LocalNotification extends CordovaPlugin {
persist(options.getId(), args); persist(options.getId(), args);
add(options, true); add(options, true);
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("cancel")) { if (action.equalsIgnoreCase("cancel")) {
...@@ -89,10 +90,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -89,10 +90,9 @@ public class LocalNotification extends CordovaPlugin {
cancel(id); cancel(id);
unpersist(id); unpersist(id);
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("cancelAll")) { if (action.equalsIgnoreCase("cancelAll")) {
...@@ -100,33 +100,29 @@ public class LocalNotification extends CordovaPlugin { ...@@ -100,33 +100,29 @@ public class LocalNotification extends CordovaPlugin {
public void run() { public void run() {
cancelAll(); cancelAll();
unpersistAll(); unpersistAll();
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("isScheduled")) { if (action.equalsIgnoreCase("isScheduled")) {
String id = args.optString(0); String id = args.optString(0);
isScheduled(id, callbackContext); isScheduled(id, command);
return true;
} }
if (action.equalsIgnoreCase("getScheduledIds")) { if (action.equalsIgnoreCase("getScheduledIds")) {
getScheduledIds(callbackContext); getScheduledIds(command);
return true;
} }
if (action.equalsIgnoreCase("hasPermission")) { if (action.equalsIgnoreCase("isTriggered")) {
hasPermission(callbackContext); String id = args.optString(0);
return true;
isTriggered(id, command);
} }
if (action.equalsIgnoreCase("promptForPermission")) { if (action.equalsIgnoreCase("getTriggeredIds")) {
return true; getTriggeredIds(command);
} }
if (action.equalsIgnoreCase("deviceready")) { if (action.equalsIgnoreCase("deviceready")) {
...@@ -135,24 +131,17 @@ public class LocalNotification extends CordovaPlugin { ...@@ -135,24 +131,17 @@ public class LocalNotification extends CordovaPlugin {
deviceready(); deviceready();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("pause")) { if (action.equalsIgnoreCase("pause")) {
isInBackground = true; isInBackground = true;
return true;
} }
if (action.equalsIgnoreCase("resume")) { if (action.equalsIgnoreCase("resume")) {
isInBackground = false; isInBackground = false;
return true;
} }
// Returning false results in a "MethodNotFound" error. return true;
return false;
} }
/** /**
...@@ -210,7 +199,7 @@ public class LocalNotification extends CordovaPlugin { ...@@ -210,7 +199,7 @@ public class LocalNotification extends CordovaPlugin {
Intent intent = new Intent(context, Receiver.class) Intent intent = new Intent(context, Receiver.class)
.setAction("" + notificationId); .setAction("" + notificationId);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager am = getAlarmManager(); AlarmManager am = getAlarmManager();
NotificationManager nc = getNotificationManager(); NotificationManager nc = getNotificationManager();
...@@ -245,19 +234,19 @@ public class LocalNotification extends CordovaPlugin { ...@@ -245,19 +234,19 @@ public class LocalNotification extends CordovaPlugin {
} }
/** /**
* Checks wether a notification with an ID is scheduled. * Checks if a notification with an ID is scheduled.
* *
* @param id * @param id
* The notification ID to be check. * The notification ID to be check.
* @param callbackContext * @param callbackContext
*/ */
public static void isScheduled (String id, CallbackContext callbackContext) { public static void isScheduled (String id, CallbackContext command) {
SharedPreferences settings = getSharedPreferences(); SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll(); Map<String, ?> alarms = settings.getAll();
boolean isScheduled = alarms.containsKey(id); boolean isScheduled = alarms.containsKey(id);
PluginResult result = new PluginResult(PluginResult.Status.OK, isScheduled); PluginResult result = new PluginResult(PluginResult.Status.OK, isScheduled);
callbackContext.sendPluginResult(result); command.sendPluginResult(result);
} }
/** /**
...@@ -265,32 +254,65 @@ public class LocalNotification extends CordovaPlugin { ...@@ -265,32 +254,65 @@ public class LocalNotification extends CordovaPlugin {
* *
* @param callbackContext * @param callbackContext
*/ */
public static void getScheduledIds (CallbackContext callbackContext) { public static void getScheduledIds (CallbackContext command) {
SharedPreferences settings = getSharedPreferences(); SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll(); Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet(); Set<String> alarmIds = alarms.keySet();
JSONArray pendingIds = new JSONArray(alarmIds); JSONArray scheduledIds = new JSONArray(alarmIds);
callbackContext.success(pendingIds); command.success(scheduledIds);
} }
/** /**
* Informs if the app has the permission to show notifications. * Checks if a notification with an ID was triggered.
* *
* @param callback * @param id
* The function to be exec as the callback * The notification ID to be check.
* @param callbackContext
*/ */
private void hasPermission (final CallbackContext callback) { public static void isTriggered (String id, CallbackContext command) {
cordova.getThreadPool().execute(new Runnable() { SharedPreferences settings = getSharedPreferences();
@Override Map<String, ?> alarms = settings.getAll();
public void run() { boolean isScheduled = alarms.containsKey(id);
PluginResult result; boolean isTriggered = isScheduled;
if (isScheduled) {
JSONObject arguments = (JSONObject) alarms.get(id);
Options options = new Options(context).parse(arguments);
Date fireDate = new Date(options.getDate());
result = new PluginResult(PluginResult.Status.OK, true); isTriggered = new Date().after(fireDate);
}
callback.sendPluginResult(result); PluginResult result = new PluginResult(PluginResult.Status.OK, isTriggered);
command.sendPluginResult(result);
}
/**
* Retrieves a list with all currently triggered notifications.
*
* @param callbackContext
*/
public static void getTriggeredIds (CallbackContext command) {
SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
JSONArray scheduledIds = new JSONArray();
Date now = new Date();
for (String id : alarmIds) {
JSONObject arguments = (JSONObject) alarms.get(id);
Options options = new Options(context).parse(arguments);
Date fireDate = new Date(options.getDate());
boolean isTriggered = now.after(fireDate);
if (isTriggered == true) {
scheduledIds.put(id);
} }
}); }
command.success(scheduledIds);
} }
/** /**
...@@ -308,7 +330,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -308,7 +330,11 @@ public class LocalNotification extends CordovaPlugin {
if (alarmId != null) { if (alarmId != null) {
editor.putString(alarmId, args.toString()); editor.putString(alarmId, args.toString());
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
} }
...@@ -323,7 +349,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -323,7 +349,11 @@ public class LocalNotification extends CordovaPlugin {
if (alarmId != null) { if (alarmId != null) {
editor.remove(alarmId); editor.remove(alarmId);
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
} }
...@@ -334,7 +364,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -334,7 +364,11 @@ public class LocalNotification extends CordovaPlugin {
Editor editor = getSharedPreferences().edit(); Editor editor = getSharedPreferences().edit();
editor.clear(); editor.clear();
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
/** /**
...@@ -397,4 +431,4 @@ public class LocalNotification extends CordovaPlugin { ...@@ -397,4 +431,4 @@ public class LocalNotification extends CordovaPlugin {
protected static NotificationManager getNotificationManager () { protected static NotificationManager getNotificationManager () {
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
} }
} }
\ No newline at end of file
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
...@@ -30,8 +34,14 @@ import org.json.JSONObject; ...@@ -30,8 +34,14 @@ import org.json.JSONObject;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.content.Context; import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
/** /**
* Class that helps to store the options that can be specified per alarm. * Class that helps to store the options that can be specified per alarm.
...@@ -153,21 +163,21 @@ public class Options { ...@@ -153,21 +163,21 @@ public class Options {
/** /**
* Returns the icon's ID * Returns the icon's ID
*/ */
public int getIcon () { public Bitmap getIcon () {
int icon = 0; String icon = options.optString("icon", "icon");
String iconName = options.optString("icon", "icon"); Bitmap bmp = null;
icon = getIconValue(packageName, iconName); if (icon.startsWith("http")) {
bmp = getIconFromURL(icon);
if (icon == 0) { } else if (icon.startsWith("file://")) {
icon = getIconValue("android", iconName); bmp = getIconFromURI(icon);
} }
if (icon == 0) { if (bmp == null) {
icon = android.R.drawable.ic_menu_info_details; bmp = getIconFromRes(icon);
} }
return options.optInt("icon", icon); return bmp;
} }
/** /**
...@@ -184,7 +194,7 @@ public class Options { ...@@ -184,7 +194,7 @@ public class Options {
} }
if (resId == 0) { if (resId == 0) {
resId = getIcon(); resId = getIconValue(packageName, "icon");
} }
return options.optInt("smallIcon", resId); return options.optInt("smallIcon", resId);
...@@ -233,6 +243,19 @@ public class Options { ...@@ -233,6 +243,19 @@ public class Options {
} }
/** /**
* @return
* The notification color for LED
*/
public int getColor () {
String hexColor = options.optString("led", "000000");
int aRGB = Integer.parseInt(hexColor,16);
aRGB += 0xFF000000;
return aRGB;
}
/**
* Returns numerical icon Value * Returns numerical icon Value
* *
* @param {String} className * @param {String} className
...@@ -249,4 +272,91 @@ public class Options { ...@@ -249,4 +272,91 @@ public class Options {
return icon; return icon;
} }
/**
* Converts an resource to Bitmap.
*
* @param icon
* The resource name
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromRes (String icon) {
Resources res = LocalNotification.context.getResources();
int iconId = 0;
iconId = getIconValue(packageName, icon);
if (iconId == 0) {
iconId = getIconValue("android", icon);
}
if (iconId == 0) {
iconId = android.R.drawable.ic_menu_info_details;
}
Bitmap bmp = BitmapFactory.decodeResource(res, iconId);
return bmp;
}
/**
* Converts an Image URL to Bitmap.
*
* @param src
* The external image URL
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromURL (String src) {
Bitmap bmp = null;
ThreadPolicy origMode = StrictMode.getThreadPolicy();
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
bmp = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}
StrictMode.setThreadPolicy(origMode);
return bmp;
}
/**
* Converts an Image URI to Bitmap.
*
* @param src
* The internal image URI
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromURI (String src) {
AssetManager assets = LocalNotification.context.getAssets();
Bitmap bmp = null;
try {
String path = src.replace("file:/", "www");
InputStream input = assets.open(path);
bmp = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
}
return bmp;
}
} }
...@@ -28,15 +28,13 @@ import org.json.JSONException; ...@@ -28,15 +28,13 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Notification; import android.support.v4.app.NotificationCompat;
import android.app.Notification.Builder; import android.support.v4.app.NotificationCompat.*;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
...@@ -117,28 +115,28 @@ public class Receiver extends BroadcastReceiver { ...@@ -117,28 +115,28 @@ public class Receiver extends BroadcastReceiver {
* Creates the notification. * Creates the notification.
*/ */
@SuppressLint("NewApi") @SuppressLint("NewApi")
private Builder buildNotification () { private Builder buildNotification () {
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), options.getIcon()); Uri sound = options.getSound();
Uri sound = options.getSound();
Builder notification = new Notification.Builder(context) Builder notification = new NotificationCompat.Builder(context)
.setDefaults(0) // Do not inherit any defaults .setDefaults(0) // Do not inherit any defaults
.setContentTitle(options.getTitle()) .setContentTitle(options.getTitle())
.setContentText(options.getMessage()) .setContentText(options.getMessage())
.setNumber(options.getBadge()) .setNumber(options.getBadge())
.setTicker(options.getMessage()) .setTicker(options.getMessage())
.setSmallIcon(options.getSmallIcon()) .setSmallIcon(options.getSmallIcon())
.setLargeIcon(icon) .setLargeIcon(options.getIcon())
.setAutoCancel(options.getAutoCancel()) .setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing()); .setOngoing(options.getOngoing())
.setLights(options.getColor(), 500, 500);
if (sound != null) { if (sound != null) {
notification.setSound(sound); notification.setSound(sound);
} }
if (Build.VERSION.SDK_INT > 16) { if (Build.VERSION.SDK_INT > 16) {
notification.setStyle(new Notification.BigTextStyle() notification.setStyle(new NotificationCompat.BigTextStyle()
.bigText(options.getMessage())); .bigText(options.getMessage()));
} }
setClickEvent(notification); setClickEvent(notification);
...@@ -165,7 +163,6 @@ public class Receiver extends BroadcastReceiver { ...@@ -165,7 +163,6 @@ public class Receiver extends BroadcastReceiver {
* Shows the notification * Shows the notification
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void showNotification (Builder notification) { private void showNotification (Builder notification) {
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int id = 0; int id = 0;
......
{"source":{"type":"registry","id":"de.appplant.cordova.plugin.local-notification"}} {"source":{"type":"git","url":"https://github.com/katzer/cordova-plugin-local-notifications.git","subdir":"."}}
\ No newline at end of file \ No newline at end of file
## ChangeLog ## ChangeLog
#### Version 0.8.0 (not yet released)
#### Version 0.7.6 (03.10.2014) - [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**)
- [bugfix:] `hasPermission` and `promptForPermission` let the app crash on iOS7 and older. - [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds`
- [bugfix:] Convert the id value to a String before comparison. - [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [bugfix:] Prevent possible crash when calling `cancelAll`. - [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [enhancement:] Do not inherit any notification defaults. - [feature:] New Android specific `led:` flag.
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
#### Version 0.7.5 (29.09.2014)
- [enhancement:] __iOS8 Support__
- [feature:] New method `hasPermission` to ask if the user has granted to display local notifications.
- [feature:] New method `promptForPermission` to promt the user to grant permission to display local notifications.
#### Version 0.7.4 (22.03.2014) #### Version 0.7.4 (22.03.2014)
- [bugfix:] Platform specific properties were ignored. - [bugfix:] Platform specific properties were ignored.
......
...@@ -19,10 +19,10 @@ The purpose of the plugin is to create an platform independent javascript interf ...@@ -19,10 +19,10 @@ The purpose of the plugin is to create an platform independent javascript interf
## Supported Platforms ## Supported Platforms
- **iOS** *(including iOS8)*<br> - **iOS**<br>
See [Local and Push Notification Programming Guide][ios_notification_guide] for detailed informations and screenshots. See [Local and Push Notification Programming Guide][ios_notification_guide] for detailed informations and screenshots.
- **Android** *(SDK >=11)*<br> - **Android** *(SDK >=7)*<br>
See [Notification Guide][android_notification_guide] for detailed informations and screenshots. See [Notification Guide][android_notification_guide] for detailed informations and screenshots.
- **WP8**<br> - **WP8**<br>
...@@ -35,19 +35,19 @@ See [Local notifications for Windows Phone][wp8_notification_guide] for detailed ...@@ -35,19 +35,19 @@ See [Local notifications for Windows Phone][wp8_notification_guide] for detailed
- [org.apache.cordova.device][apache_device_plugin] *(since v0.6.0)* - [org.apache.cordova.device][apache_device_plugin] *(since v0.6.0)*
# Installation ## Installation
The plugin can either be installed into the local development environment or cloud based through [PhoneGap Build][PGB]. The plugin can either be installed into the local development environment or cloud based through [PhoneGap Build][PGB].
### Adding the Plugin to your project ### Adding the Plugin to your project
Through the [Command-line Interface][CLI]: Through the [Command-line Interface][CLI]:
```bash ```bash
# ~~ from master ~~ # ~~ from master ~~
cordova plugin add https://github.com/katzer/cordova-plugin-local-notifications.git cordova plugin add https://github.com/katzer/cordova-plugin-local-notifications.git && cordova prepare
``` ```
or to use the last stable version: or to use the last stable version:
```bash ```bash
# ~~ stable version ~~ # ~~ stable version ~~
cordova plugin add de.appplant.cordova.plugin.local-notification@0.7.6 cordova plugin add de.appplant.cordova.plugin.local-notification && cordova prepare
``` ```
### Removing the Plugin from your project ### Removing the Plugin from your project
...@@ -63,31 +63,41 @@ Add the following xml to your config.xml to always use the latest version of thi ...@@ -63,31 +63,41 @@ Add the following xml to your config.xml to always use the latest version of thi
``` ```
or to use an specific version: or to use an specific version:
```xml ```xml
<gap:plugin name="de.appplant.cordova.plugin.local-notification" version="0.7.6" /> <gap:plugin name="de.appplant.cordova.plugin.local-notification" version="0.7.2" />
``` ```
More informations can be found [here][PGB_plugin]. More informations can be found [here][PGB_plugin].
## ChangeLog ## ChangeLog
#### Version 0.8.0 (not yet released)
#### Version 0.7.6 (03.10.2014) - [enhancement:] Android 2.x (SDK >= 7) support (Thanks to **khizarsonu**)
- [bugfix:] `hasPermission` and `promptForPermission` let the app crash on iOS7 and older. - [enhancement:] Scope parameter for `isScheduled` and `getScheduledIds`
- [bugfix:] Convert the id value to a String before comparison. - [enhancement:] Callbacks for `add`, `cancel` & `cancelAll`
- [bugfix:] Prevent possible crash when calling `cancelAll`. - [enhancement:] `image:` accepts remote URLs and local URIs (Android)
- [enhancement:] Do not inherit any notification defaults. - [feature:] New Android specific `led:` flag
- [feature:] Add `isTriggered` & `getTriggeredIds` methods.
#### Version 0.7.5 (29.09.2014)
- [enhancement:] __iOS8 Support__
- [feature:] New method `hasPermission` to ask if the user has granted to display local notifications.
- [feature:] New method `promptForPermission` to promt the user to grant permission to display local notifications.
#### Further informations #### Further informations
- See [CHANGELOG.md][changelog] to get the full changelog for the plugin. - See [CHANGELOG.md][changelog] to get the full changelog for the plugin.
- See the [v0.8.x TODO List][todo_list] for upcomming changes and other things.
## Using the plugin ## Using the plugin
The plugin creates the object ```window.plugin.notification.local``` with the following methods: The plugin creates the object ```window.plugin.notification.local``` with the following methods:
1. [notification.local.add][add]
2. [notification.local.cancel][cancel]
3. [notification.local.cancelAll][cancelall]
4. [notification.local.isScheduled][isscheduled]
5. [notification.local.getScheduledIds][getscheduledids]
6. [notification.local.isTriggered][istriggered]
7. [notification.local.getDefaults][getdefaults]
8. [notification.local.setDefaults][setDefaults]
9. [notification.local.onadd][onadd]
10. [notification.local.ontrigger][ontrigger]
11. [notification.local.onclick][onclick]
12. [notification.local.oncancel][oncancel]
### Plugin initialization ### Plugin initialization
The plugin and its methods are not available before the *deviceready* event has been fired. The plugin and its methods are not available before the *deviceready* event has been fired.
...@@ -97,30 +107,6 @@ document.addEventListener('deviceready', function () { ...@@ -97,30 +107,6 @@ document.addEventListener('deviceready', function () {
}, false); }, false);
``` ```
### Determine if the app does have the permission to show local notifications
If the permission has been granted through the user can be retrieved through the `notification.local.hasPermission` interface.<br/>
The method takes a callback function as its argument which will be called with a boolean value. Optional the scope of the callback function ca be defined through a second argument.
#### Further informations
- The method is supported on each platform, however its only relevant for iOS8 and above.
```javascript
window.plugin.notification.local.hasPermission(function (granted) {
// console.log('Permission has been granted: ' + granted);
});
```
### Prompt the user to grant permission for local notifications
The user can be prompted to grant the required permission through the `notification.local.promptForPermission` interface.
#### Further informations
- The method is supported on each platform, however its only relevant for iOS8 and above.
- The user will only get a prompt dialog for the first time. Later its only possible to change the setting via the notification center.
```javascript
window.plugin.notification.local.promptForPermission();
```
### Schedule local notifications ### Schedule local notifications
Local notifications can be scheduled through the `notification.local.add` interface.<br> Local notifications can be scheduled through the `notification.local.add` interface.<br>
The method takes a hash as an argument to specify the notification's properties and returns the ID for the notification.<br> The method takes a hash as an argument to specify the notification's properties and returns the ID for the notification.<br>
...@@ -131,7 +117,6 @@ All properties are optional. If no date object is given, the notification pops-u ...@@ -131,7 +117,6 @@ All properties are optional. If no date object is given, the notification pops-u
If the ID has an invalid format, it will be ignored, but canceling the notification will fail. If the ID has an invalid format, it will be ignored, but canceling the notification will fail.
#### Further informations #### Further informations
- The notification can only be scheduled if the user has previously granted the [required permission][prompt_permission].
- See the [onadd][onadd] event of how a listener can be registered to be notified when a local notification has been scheduled. - See the [onadd][onadd] event of how a listener can be registered to be notified when a local notification has been scheduled.
- See the [ontrigger][ontrigger] event of how a listener can be registered to be notified when a local notification has been triggered. - See the [ontrigger][ontrigger] event of how a listener can be registered to be notified when a local notification has been triggered.
- See the [onclick][onclick] event of how a listener can be registered to be notified when the user has been clicked on a local notification. - See the [onclick][onclick] event of how a listener can be registered to be notified when the user has been clicked on a local notification.
...@@ -151,7 +136,7 @@ window.plugin.notification.local.add({ ...@@ -151,7 +136,7 @@ window.plugin.notification.local.add({
json: String, // Data to be passed through the notification json: String, // Data to be passed through the notification
autoCancel: Boolean, // Setting this flag and the notification is automatically canceled when the user clicks it autoCancel: Boolean, // Setting this flag and the notification is automatically canceled when the user clicks it
ongoing: Boolean, // Prevent clearing of notification (Android only) ongoing: Boolean, // Prevent clearing of notification (Android only)
}); }, callback, scope);
``` ```
### Cancel scheduled local notifications ### Cancel scheduled local notifications
...@@ -163,7 +148,9 @@ Note that only local notifications with an ID can be canceled. ...@@ -163,7 +148,9 @@ Note that only local notifications with an ID can be canceled.
- See [getScheduledIds][getscheduledids] of how to retrieve a list of IDs of all scheduled local notifications. - See [getScheduledIds][getscheduledids] of how to retrieve a list of IDs of all scheduled local notifications.
```javascript ```javascript
window.plugin.notification.local.cancel(ID); window.plugin.notification.local.cancel(ID, function () {
// The notification has been canceled
}, scope);
``` ```
### Cancel all scheduled local notifications ### Cancel all scheduled local notifications
...@@ -174,12 +161,14 @@ The method cancels all local notifications even if they have no ID. ...@@ -174,12 +161,14 @@ The method cancels all local notifications even if they have no ID.
- See the [oncancel][oncancel] event of how a listener can be registered to be notified when a local notification has been canceled. - See the [oncancel][oncancel] event of how a listener can be registered to be notified when a local notification has been canceled.
```javascript ```javascript
window.plugin.notification.local.cancelAll(); window.plugin.notification.local.cancelAll(function () {
// All notifications have been canceled
}, scope);
``` ```
### Check wether a notification with an ID is scheduled ### Check wether a notification with an ID is scheduled
To check if a notification with an ID is scheduled, the `notification.local.isScheduled` interface can be used.<br> To check if a notification with an ID is scheduled, the `notification.local.isScheduled` interface can be used.<br>
The method takes the ID of the local notification as an argument and a callback function to be called with the result. The method takes the ID of the local notification as an argument and a callback function to be called with the result. Optional the scope of the callback can be assigned too.
#### Further informations #### Further informations
- See [getScheduledIds][getscheduledids] of how to retrieve a list of IDs of all scheduled local notifications. - See [getScheduledIds][getscheduledids] of how to retrieve a list of IDs of all scheduled local notifications.
...@@ -187,17 +176,40 @@ The method takes the ID of the local notification as an argument and a callback ...@@ -187,17 +176,40 @@ The method takes the ID of the local notification as an argument and a callback
```javascript ```javascript
window.plugin.notification.local.isScheduled(id, function (isScheduled) { window.plugin.notification.local.isScheduled(id, function (isScheduled) {
// console.log('Notification with ID ' + id + ' is scheduled: ' + isScheduled); // console.log('Notification with ID ' + id + ' is scheduled: ' + isScheduled);
}); }, scope);
``` ```
### Retrieve the IDs from all currently scheduled local notifications ### Retrieve the IDs from all currently scheduled local notifications
To retrieve the IDs from all currently scheduled local notifications, the `notification.local.isScheduled` interface can be used.<br> To retrieve the IDs from all currently scheduled local notifications, the `notification.local.getScheduledIds` interface can be used.<br>
The method takes a callback function to be called with the result as an array of IDs. The method takes a callback function to be called with the result as an array of IDs. Optional the scope of the callback can be assigned too.
```javascript ```javascript
window.plugin.notification.local.getScheduledIds( function (scheduledIds) { window.plugin.notification.local.getScheduledIds(function (scheduledIds) {
// alert('Scheduled IDs: ' + scheduledIds.join(' ,')); // alert('Scheduled IDs: ' + scheduledIds.join(' ,'));
}); }, scope);
```
### Check wether a notification with an ID was triggered
To check if a notification with an ID was triggered, the `notification.local.isTriggered` interface can be used.<br>
The method takes the ID of the local notification as an argument and a callback function to be called with the result. Optional the scope of the callback can be assigned too.
#### Further informations
- See [getTriggeredIds][gettriggeredIds] of how to retrieve a list of IDs of all scheduled local notifications.
```javascript
window.plugin.notification.local.isTriggered(id, function (isTriggered) {
// console.log('Notification with ID ' + id + ' is triggered: ' + isTriggered);
}, scope);
```
### Retrieve the IDs from all currently triggered local notifications
To retrieve the IDs from all currently triggered local notifications, the `notification.local.getTriggeredIds` interface can be used.<br>
The method takes a callback function to be called with the result as an array of IDs. Optional the scope of the callback can be assigned too.
```javascript
window.plugin.notification.local.getTriggeredIds(function (triggeredIds) {
// alert('Triggered IDs: ' + triggeredIds.join(' ,'));
}, scope);
``` ```
### Get the default values of the local notification properties ### Get the default values of the local notification properties
...@@ -310,8 +322,6 @@ window.plugin.notification.local.add({ ...@@ -310,8 +322,6 @@ window.plugin.notification.local.add({
}); });
``` ```
__Note:__ The notification can only be scheduled if the user has granted the [required permission][prompt_permission].
### Scheduling an immediately triggered local notification ### Scheduling an immediately triggered local notification
The example below shows how to schedule a local notification which will be triggered immediatly. The example below shows how to schedule a local notification which will be triggered immediatly.
...@@ -354,18 +364,33 @@ window.plugin.notification.local.setDefaults({ autoCancel: true }); ...@@ -354,18 +364,33 @@ window.plugin.notification.local.setDefaults({ autoCancel: true });
### Small and large icons on Android ### Small and large icons on Android
By default all notifications will display the app icon. But an specific icon can be defined through the `icon` and `smallIcon` properties. By default all notifications will display the app icon. But an specific icon can be defined through the `icon` and `smallIcon` properties.
#### Resource icons
The following example shows how to display the `<package.name>.R.drawable.ic_launcher`icon as the notifications icon.
```javascript ```javascript
/**
* Displays the <package.name>.R.drawable.ic_launcher icon
*/
window.plugin.notification.local.add({ icon: 'ic_launcher' }); window.plugin.notification.local.add({ icon: 'ic_launcher' });
```
/** See below how to use the `android.R.drawable.ic_dialog_email` icon as the notifications small icon.
* Displays the android.R.drawable.ic_dialog_email icon
*/ ```javascript
window.plugin.notification.local.add({ smallIcon: 'ic_dialog_email' }); window.plugin.notification.local.add({ smallIcon: 'ic_dialog_email' });
``` ```
#### Local icons
The `icon` property also accepts local file URIs. The URI points to a relative path within the www folder.
```javascript
window.plugin.notification.local.add({ icon: 'file://img/logo.png' }); //=> /assets/www/img/logo.png
```
#### Remote icons
The `icon` property also accepts remote URLs. If the device cannot download the image, it will fallback to the app icon.
```javascript
window.plugin.notification.local.add({ icon: 'https://cordova.apache.org/images/cordova_bot.png' });
```
### Notification sound on Android ### Notification sound on Android
The sound must be a absolute or relative Uri pointing to the sound file. The default sound is `RingtoneManager.TYPE_NOTIFICATION`. The sound must be a absolute or relative Uri pointing to the sound file. The default sound is `RingtoneManager.TYPE_NOTIFICATION`.
...@@ -433,6 +458,13 @@ To specify a custom interval, the `repeat` property can be assigned with an numb ...@@ -433,6 +458,13 @@ To specify a custom interval, the `repeat` property can be assigned with an numb
window.plugin.notification.local.add({ repeat: 15 }); window.plugin.notification.local.add({ repeat: 15 });
``` ```
### Change the LED color on Android devices
The LED color can be specified through the `led` property. By default the color value is white (FFFFFF). Its possible to change that value by setting another hex code.
```javascript
window.plugin.notification.local.add({ led: 'A0FF05' });
```
## Quirks ## Quirks
...@@ -479,7 +511,7 @@ The launch mode for the main activity has to be set to `singleInstance` ...@@ -479,7 +511,7 @@ The launch mode for the main activity has to be set to `singleInstance`
## License ## License
This software is released under the [Apache 2.0 License](http://opensource.org/licenses/Apache-2.0). This software is released under the [Apache 2.0 License][apache2_license].
© 2013-2014 appPlant UG, Inc. All rights reserved © 2013-2014 appPlant UG, Inc. All rights reserved
...@@ -491,10 +523,9 @@ This software is released under the [Apache 2.0 License](http://opensource.org/l ...@@ -491,10 +523,9 @@ This software is released under the [Apache 2.0 License](http://opensource.org/l
[apache_device_plugin]: https://github.com/apache/cordova-plugin-device [apache_device_plugin]: https://github.com/apache/cordova-plugin-device
[CLI]: http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface [CLI]: http://cordova.apache.org/docs/en/3.0.0/guide_cli_index.md.html#The%20Command-line%20Interface
[PGB]: http://docs.build.phonegap.com/en_US/3.3.0/index.html [PGB]: http://docs.build.phonegap.com/en_US/3.3.0/index.html
[PGB_plugin]: https://build.phonegap.com/plugins/1196 [PGB_plugin]: https://build.phonegap.com/plugins/413
[changelog]: CHANGELOG.md [changelog]: CHANGELOG.md
[has_permission]: #determine-if-the-app-does-have-the-permission-to-show-local-notifications [todo_list]: ../../issues/164
[prompt_permission]: #prompt-the-user-to-grant-permission-for-local-notifications
[onadd]: #get-notified-when-a-local-notification-has-been-scheduled [onadd]: #get-notified-when-a-local-notification-has-been-scheduled
[onclick]: #get-notified-when-the-user-has-been-clicked-on-a-local-notification [onclick]: #get-notified-when-the-user-has-been-clicked-on-a-local-notification
[oncancel]: #get-notified-when-a-local-notification-has-been-canceled [oncancel]: #get-notified-when-a-local-notification-has-been-canceled
...@@ -506,6 +537,9 @@ This software is released under the [Apache 2.0 License](http://opensource.org/l ...@@ -506,6 +537,9 @@ This software is released under the [Apache 2.0 License](http://opensource.org/l
[getdefaults]: #get-the-default-values-of-the-local-notification-properties [getdefaults]: #get-the-default-values-of-the-local-notification-properties
[setdefaults]: #set-the-default-values-of-the-local-notification-properties [setdefaults]: #set-the-default-values-of-the-local-notification-properties
[getscheduledids]: #retrieve-the-ids-from-all-currently-scheduled-local-notifications [getscheduledids]: #retrieve-the-ids-from-all-currently-scheduled-local-notifications
[gettriggeredids]: #retrieve-the-ids-from-all-currently-triggered-local-notifications
[isscheduled]: #check-wether-a-notification-with-an-id-is-scheduled [isscheduled]: #check-wether-a-notification-with-an-id-is-scheduled
[istriggered]: #check-wether-a-notification-with-an-id-was-triggered
[examples]: #examples [examples]: #examples
[setdefaults-example]: #change-the-default-value-of-local-notification-properties [setdefaults-example]: #change-the-default-value-of-local-notification-properties
[apache2_license]: http://opensource.org/licenses/Apache-2.0
{
"version": "0.7.6",
"name": "de.appplant.cordova.plugin.local-notification",
"cordova_name": "LocalNotification",
"description": "A bunch of local-notification plugins for Cordova 3.x.x",
"license": "Apache 2.0",
"repo": "https://github.com/katzer/cordova-plugin-local-notifications/tree/0.7",
"keywords": [
"notification",
" local notification",
" alarm",
" scheduler",
" tile",
" live tiles",
" ios",
" android",
" windows phone 8",
" wp8",
" iOS8"
],
"platforms": [
"ios",
"android",
"wp8"
],
"engines": [
{
"name": "cordova",
"version": ">=3.0.0"
}
]
}
\ No newline at end of file
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
id="de.appplant.cordova.plugin.local-notification" id="de.appplant.cordova.plugin.local-notification"
version="0.7.6"> version="0.8.0dev">
<name>LocalNotification</name> <name>LocalNotification</name>
<description>A bunch of local-notification plugins for Cordova 3.x.x</description> <description>The purpose of the plugin is to create an platform independent javascript interface for Cordova based mobile applications to access the specific Notification API on each platform.</description>
<repo>https://github.com/katzer/cordova-plugin-local-notifications/tree/0.7</repo> <repo>https://github.com/katzer/cordova-plugin-local-notifications.git</repo>
<keywords>notification, local notification, alarm, scheduler, tile, live tiles, ios, android, windows phone 8, wp8, iOS8</keywords> <keywords>notification, local notification, alarm, scheduler, tile, live tiles, ios, android, windows phone 8, wp8</keywords>
<license>Apache 2.0</license> <license>Apache 2.0</license>
<author>Sebastián Katzer</author> <author>Sebastián Katzer</author>
...@@ -77,6 +77,8 @@ ...@@ -77,6 +77,8 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</config-file> </config-file>
<lib-file src="libs/android/android-support-v4.jar" />
<source-file src="src/android/LocalNotification.java" target-dir="src/de/appplant/cordova/plugin/localnotification" /> <source-file src="src/android/LocalNotification.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/Receiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" /> <source-file src="src/android/Receiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file src="src/android/Options.java" target-dir="src/de/appplant/cordova/plugin/localnotification" /> <source-file src="src/android/Options.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -41,6 +42,7 @@ import android.content.Context; ...@@ -41,6 +42,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.os.Build;
/** /**
* This plugin utilizes the Android AlarmManager in combination with StatusBar * This plugin utilizes the Android AlarmManager in combination with StatusBar
...@@ -67,7 +69,7 @@ public class LocalNotification extends CordovaPlugin { ...@@ -67,7 +69,7 @@ public class LocalNotification extends CordovaPlugin {
} }
@Override @Override
public boolean execute (String action, final JSONArray args, CallbackContext callbackContext) throws JSONException { public boolean execute (String action, final JSONArray args, final CallbackContext command) throws JSONException {
if (action.equalsIgnoreCase("add")) { if (action.equalsIgnoreCase("add")) {
cordova.getThreadPool().execute( new Runnable() { cordova.getThreadPool().execute( new Runnable() {
public void run() { public void run() {
...@@ -76,10 +78,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -76,10 +78,9 @@ public class LocalNotification extends CordovaPlugin {
persist(options.getId(), args); persist(options.getId(), args);
add(options, true); add(options, true);
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("cancel")) { if (action.equalsIgnoreCase("cancel")) {
...@@ -89,10 +90,9 @@ public class LocalNotification extends CordovaPlugin { ...@@ -89,10 +90,9 @@ public class LocalNotification extends CordovaPlugin {
cancel(id); cancel(id);
unpersist(id); unpersist(id);
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("cancelAll")) { if (action.equalsIgnoreCase("cancelAll")) {
...@@ -100,33 +100,29 @@ public class LocalNotification extends CordovaPlugin { ...@@ -100,33 +100,29 @@ public class LocalNotification extends CordovaPlugin {
public void run() { public void run() {
cancelAll(); cancelAll();
unpersistAll(); unpersistAll();
command.success();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("isScheduled")) { if (action.equalsIgnoreCase("isScheduled")) {
String id = args.optString(0); String id = args.optString(0);
isScheduled(id, callbackContext); isScheduled(id, command);
return true;
} }
if (action.equalsIgnoreCase("getScheduledIds")) { if (action.equalsIgnoreCase("getScheduledIds")) {
getScheduledIds(callbackContext); getScheduledIds(command);
return true;
} }
if (action.equalsIgnoreCase("hasPermission")) { if (action.equalsIgnoreCase("isTriggered")) {
hasPermission(callbackContext); String id = args.optString(0);
return true;
isTriggered(id, command);
} }
if (action.equalsIgnoreCase("promptForPermission")) { if (action.equalsIgnoreCase("getTriggeredIds")) {
return true; getTriggeredIds(command);
} }
if (action.equalsIgnoreCase("deviceready")) { if (action.equalsIgnoreCase("deviceready")) {
...@@ -135,24 +131,17 @@ public class LocalNotification extends CordovaPlugin { ...@@ -135,24 +131,17 @@ public class LocalNotification extends CordovaPlugin {
deviceready(); deviceready();
} }
}); });
return true;
} }
if (action.equalsIgnoreCase("pause")) { if (action.equalsIgnoreCase("pause")) {
isInBackground = true; isInBackground = true;
return true;
} }
if (action.equalsIgnoreCase("resume")) { if (action.equalsIgnoreCase("resume")) {
isInBackground = false; isInBackground = false;
return true;
} }
// Returning false results in a "MethodNotFound" error. return true;
return false;
} }
/** /**
...@@ -210,7 +199,7 @@ public class LocalNotification extends CordovaPlugin { ...@@ -210,7 +199,7 @@ public class LocalNotification extends CordovaPlugin {
Intent intent = new Intent(context, Receiver.class) Intent intent = new Intent(context, Receiver.class)
.setAction("" + notificationId); .setAction("" + notificationId);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager am = getAlarmManager(); AlarmManager am = getAlarmManager();
NotificationManager nc = getNotificationManager(); NotificationManager nc = getNotificationManager();
...@@ -245,19 +234,19 @@ public class LocalNotification extends CordovaPlugin { ...@@ -245,19 +234,19 @@ public class LocalNotification extends CordovaPlugin {
} }
/** /**
* Checks wether a notification with an ID is scheduled. * Checks if a notification with an ID is scheduled.
* *
* @param id * @param id
* The notification ID to be check. * The notification ID to be check.
* @param callbackContext * @param callbackContext
*/ */
public static void isScheduled (String id, CallbackContext callbackContext) { public static void isScheduled (String id, CallbackContext command) {
SharedPreferences settings = getSharedPreferences(); SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll(); Map<String, ?> alarms = settings.getAll();
boolean isScheduled = alarms.containsKey(id); boolean isScheduled = alarms.containsKey(id);
PluginResult result = new PluginResult(PluginResult.Status.OK, isScheduled); PluginResult result = new PluginResult(PluginResult.Status.OK, isScheduled);
callbackContext.sendPluginResult(result); command.sendPluginResult(result);
} }
/** /**
...@@ -265,32 +254,65 @@ public class LocalNotification extends CordovaPlugin { ...@@ -265,32 +254,65 @@ public class LocalNotification extends CordovaPlugin {
* *
* @param callbackContext * @param callbackContext
*/ */
public static void getScheduledIds (CallbackContext callbackContext) { public static void getScheduledIds (CallbackContext command) {
SharedPreferences settings = getSharedPreferences(); SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll(); Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet(); Set<String> alarmIds = alarms.keySet();
JSONArray pendingIds = new JSONArray(alarmIds); JSONArray scheduledIds = new JSONArray(alarmIds);
callbackContext.success(pendingIds); command.success(scheduledIds);
} }
/** /**
* Informs if the app has the permission to show notifications. * Checks if a notification with an ID was triggered.
* *
* @param callback * @param id
* The function to be exec as the callback * The notification ID to be check.
* @param callbackContext
*/ */
private void hasPermission (final CallbackContext callback) { public static void isTriggered (String id, CallbackContext command) {
cordova.getThreadPool().execute(new Runnable() { SharedPreferences settings = getSharedPreferences();
@Override Map<String, ?> alarms = settings.getAll();
public void run() { boolean isScheduled = alarms.containsKey(id);
PluginResult result; boolean isTriggered = isScheduled;
if (isScheduled) {
JSONObject arguments = (JSONObject) alarms.get(id);
Options options = new Options(context).parse(arguments);
Date fireDate = new Date(options.getDate());
result = new PluginResult(PluginResult.Status.OK, true); isTriggered = new Date().after(fireDate);
}
callback.sendPluginResult(result); PluginResult result = new PluginResult(PluginResult.Status.OK, isTriggered);
command.sendPluginResult(result);
}
/**
* Retrieves a list with all currently triggered notifications.
*
* @param callbackContext
*/
public static void getTriggeredIds (CallbackContext command) {
SharedPreferences settings = getSharedPreferences();
Map<String, ?> alarms = settings.getAll();
Set<String> alarmIds = alarms.keySet();
JSONArray scheduledIds = new JSONArray();
Date now = new Date();
for (String id : alarmIds) {
JSONObject arguments = (JSONObject) alarms.get(id);
Options options = new Options(context).parse(arguments);
Date fireDate = new Date(options.getDate());
boolean isTriggered = now.after(fireDate);
if (isTriggered == true) {
scheduledIds.put(id);
} }
}); }
command.success(scheduledIds);
} }
/** /**
...@@ -308,7 +330,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -308,7 +330,11 @@ public class LocalNotification extends CordovaPlugin {
if (alarmId != null) { if (alarmId != null) {
editor.putString(alarmId, args.toString()); editor.putString(alarmId, args.toString());
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
} }
...@@ -323,7 +349,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -323,7 +349,11 @@ public class LocalNotification extends CordovaPlugin {
if (alarmId != null) { if (alarmId != null) {
editor.remove(alarmId); editor.remove(alarmId);
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
} }
...@@ -334,7 +364,11 @@ public class LocalNotification extends CordovaPlugin { ...@@ -334,7 +364,11 @@ public class LocalNotification extends CordovaPlugin {
Editor editor = getSharedPreferences().edit(); Editor editor = getSharedPreferences().edit();
editor.clear(); editor.clear();
editor.apply(); if (Build.VERSION.SDK_INT<9) {
editor.commit();
} else {
editor.apply();
}
} }
/** /**
...@@ -397,4 +431,4 @@ public class LocalNotification extends CordovaPlugin { ...@@ -397,4 +431,4 @@ public class LocalNotification extends CordovaPlugin {
protected static NotificationManager getNotificationManager () { protected static NotificationManager getNotificationManager () {
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
} }
} }
\ No newline at end of file
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
package de.appplant.cordova.plugin.localnotification; package de.appplant.cordova.plugin.localnotification;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
...@@ -30,8 +34,14 @@ import org.json.JSONObject; ...@@ -30,8 +34,14 @@ import org.json.JSONObject;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.content.Context; import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
/** /**
* Class that helps to store the options that can be specified per alarm. * Class that helps to store the options that can be specified per alarm.
...@@ -153,21 +163,21 @@ public class Options { ...@@ -153,21 +163,21 @@ public class Options {
/** /**
* Returns the icon's ID * Returns the icon's ID
*/ */
public int getIcon () { public Bitmap getIcon () {
int icon = 0; String icon = options.optString("icon", "icon");
String iconName = options.optString("icon", "icon"); Bitmap bmp = null;
icon = getIconValue(packageName, iconName); if (icon.startsWith("http")) {
bmp = getIconFromURL(icon);
if (icon == 0) { } else if (icon.startsWith("file://")) {
icon = getIconValue("android", iconName); bmp = getIconFromURI(icon);
} }
if (icon == 0) { if (bmp == null) {
icon = android.R.drawable.ic_menu_info_details; bmp = getIconFromRes(icon);
} }
return options.optInt("icon", icon); return bmp;
} }
/** /**
...@@ -184,7 +194,7 @@ public class Options { ...@@ -184,7 +194,7 @@ public class Options {
} }
if (resId == 0) { if (resId == 0) {
resId = getIcon(); resId = getIconValue(packageName, "icon");
} }
return options.optInt("smallIcon", resId); return options.optInt("smallIcon", resId);
...@@ -233,6 +243,19 @@ public class Options { ...@@ -233,6 +243,19 @@ public class Options {
} }
/** /**
* @return
* The notification color for LED
*/
public int getColor () {
String hexColor = options.optString("led", "000000");
int aRGB = Integer.parseInt(hexColor,16);
aRGB += 0xFF000000;
return aRGB;
}
/**
* Returns numerical icon Value * Returns numerical icon Value
* *
* @param {String} className * @param {String} className
...@@ -249,4 +272,91 @@ public class Options { ...@@ -249,4 +272,91 @@ public class Options {
return icon; return icon;
} }
/**
* Converts an resource to Bitmap.
*
* @param icon
* The resource name
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromRes (String icon) {
Resources res = LocalNotification.context.getResources();
int iconId = 0;
iconId = getIconValue(packageName, icon);
if (iconId == 0) {
iconId = getIconValue("android", icon);
}
if (iconId == 0) {
iconId = android.R.drawable.ic_menu_info_details;
}
Bitmap bmp = BitmapFactory.decodeResource(res, iconId);
return bmp;
}
/**
* Converts an Image URL to Bitmap.
*
* @param src
* The external image URL
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromURL (String src) {
Bitmap bmp = null;
ThreadPolicy origMode = StrictMode.getThreadPolicy();
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
bmp = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}
StrictMode.setThreadPolicy(origMode);
return bmp;
}
/**
* Converts an Image URI to Bitmap.
*
* @param src
* The internal image URI
* @return
* The corresponding bitmap
*/
private Bitmap getIconFromURI (String src) {
AssetManager assets = LocalNotification.context.getAssets();
Bitmap bmp = null;
try {
String path = src.replace("file:/", "www");
InputStream input = assets.open(path);
bmp = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
}
return bmp;
}
} }
...@@ -28,15 +28,13 @@ import org.json.JSONException; ...@@ -28,15 +28,13 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Notification; import android.support.v4.app.NotificationCompat;
import android.app.Notification.Builder; import android.support.v4.app.NotificationCompat.*;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
...@@ -117,28 +115,28 @@ public class Receiver extends BroadcastReceiver { ...@@ -117,28 +115,28 @@ public class Receiver extends BroadcastReceiver {
* Creates the notification. * Creates the notification.
*/ */
@SuppressLint("NewApi") @SuppressLint("NewApi")
private Builder buildNotification () { private Builder buildNotification () {
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), options.getIcon()); Uri sound = options.getSound();
Uri sound = options.getSound();
Builder notification = new Notification.Builder(context) Builder notification = new NotificationCompat.Builder(context)
.setDefaults(0) // Do not inherit any defaults .setDefaults(0) // Do not inherit any defaults
.setContentTitle(options.getTitle()) .setContentTitle(options.getTitle())
.setContentText(options.getMessage()) .setContentText(options.getMessage())
.setNumber(options.getBadge()) .setNumber(options.getBadge())
.setTicker(options.getMessage()) .setTicker(options.getMessage())
.setSmallIcon(options.getSmallIcon()) .setSmallIcon(options.getSmallIcon())
.setLargeIcon(icon) .setLargeIcon(options.getIcon())
.setAutoCancel(options.getAutoCancel()) .setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing()); .setOngoing(options.getOngoing())
.setLights(options.getColor(), 500, 500);
if (sound != null) { if (sound != null) {
notification.setSound(sound); notification.setSound(sound);
} }
if (Build.VERSION.SDK_INT > 16) { if (Build.VERSION.SDK_INT > 16) {
notification.setStyle(new Notification.BigTextStyle() notification.setStyle(new NotificationCompat.BigTextStyle()
.bigText(options.getMessage())); .bigText(options.getMessage()));
} }
setClickEvent(notification); setClickEvent(notification);
...@@ -165,7 +163,6 @@ public class Receiver extends BroadcastReceiver { ...@@ -165,7 +163,6 @@ public class Receiver extends BroadcastReceiver {
* Shows the notification * Shows the notification
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void showNotification (Builder notification) { private void showNotification (Builder notification) {
NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int id = 0; int id = 0;
......
...@@ -36,9 +36,5 @@ ...@@ -36,9 +36,5 @@
- (void) isScheduled:(CDVInvokedUrlCommand*)command; - (void) isScheduled:(CDVInvokedUrlCommand*)command;
// Retrieves a list of ids from all currently pending notifications // Retrieves a list of ids from all currently pending notifications
- (void) getScheduledIds:(CDVInvokedUrlCommand*)command; - (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
// Informs if the app has the permission to show notifications
- (void) hasPermission:(CDVInvokedUrlCommand *)command;
// Ask for permission to show notifications
- (void) promptForPermission:(CDVInvokedUrlCommand *)command;
@end @end
...@@ -20,44 +20,6 @@ ...@@ -20,44 +20,6 @@
*/ */
#import "APPLocalNotification.h" #import "APPLocalNotification.h"
#import <Cordova/CDVAvailability.h>
@interface APPLocalNotification (Private)
// Schedules a new local notification and fies the coresponding event
- (void) scheduleNotificationWithProperties:(NSMutableDictionary*)properties;
// Cancels the given local notification and fires the cancel event
- (void) cancelNotification:(UILocalNotification*)notification fireEvent:(BOOL)fireEvent;
// Cancels all local notification with are older then
- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds;
// Retrurns a key-value dictionary for repeat intervals
- (NSMutableDictionary*) repeatDict;
// Returns the userDict for a local notification
- (NSDictionary*) userDict:(NSMutableDictionary*)options;
// Creates an notification object based on the given properties
- (UILocalNotification*) notificationWithProperties:(NSMutableDictionary*)options;
// Calls the cancel or trigger event after a local notification was received
- (void) didReceiveLocalNotification:(NSNotification*)localNotification;
// Calls the cancel or trigger event after a local notification was received
- (void) didFinishLaunchingWithOptions:(NSNotification*)notification;
// Registers obervers for the following events after plugin was initialized.
- (void) pluginInitialize;
// Clears all single repeating notifications which are older then 5 days
- (void) onAppTerminate;
// Checks weather the given string is empty or not
- (BOOL) stringIsNullOrEmpty:(NSString*)str;
// Checks wether a notification with an ID is scheduled or not
- (BOOL) isNotificationScheduledWithId:(NSString*)id;
// Retrieves the local notification by its ID
- (UILocalNotification*) notificationWithId:(NSString*)id;
// Retrieves the application state
- (NSString*) applicationState;
// Retrieves all scheduled notifications
- (NSArray*) scheduledNotifications;
// Fires the given event
- (void) fireEvent:(NSString*)event id:(NSString*)id json:(NSString*)json;
@end
@interface APPLocalNotification () @interface APPLocalNotification ()
...@@ -76,6 +38,9 @@ ...@@ -76,6 +38,9 @@
@synthesize deviceready, eventQueue, applicationState, scheduledNotifications; @synthesize deviceready, eventQueue, applicationState, scheduledNotifications;
#pragma mark -
#pragma mark Plugin interface methods
/** /**
* Executes all queued events. * Executes all queued events.
*/ */
...@@ -102,14 +67,11 @@ ...@@ -102,14 +67,11 @@
NSArray* arguments = [command arguments]; NSArray* arguments = [command arguments];
NSMutableDictionary* properties = [arguments objectAtIndex:0]; NSMutableDictionary* properties = [arguments objectAtIndex:0];
UILocalNotification* notification;
NSString* id = [properties objectForKey:@"id"]; NSString* id = [properties objectForKey:@"id"];
if ([self isNotificationScheduledWithId:id]) { if ([self isNotificationScheduledWithId:id]) {
notification = [self notificationWithId:id]; UILocalNotification* notification = [self notificationWithId:id];
}
if (notification) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{ dispatch_get_main_queue(), ^{
[self cancelNotification:notification fireEvent:NO]; [self cancelNotification:notification fireEvent:NO];
...@@ -117,6 +79,7 @@ ...@@ -117,6 +79,7 @@
} }
[self scheduleNotificationWithProperties:properties]; [self scheduleNotificationWithProperties:properties];
[self execCallback:command];
}]; }];
} }
...@@ -137,6 +100,8 @@ ...@@ -137,6 +100,8 @@
if (notification) { if (notification) {
[self cancelNotification:notification fireEvent:YES]; [self cancelNotification:notification fireEvent:YES];
} }
[self execCallback:command];
}]; }];
} }
...@@ -157,6 +122,8 @@ ...@@ -157,6 +122,8 @@
[[UIApplication sharedApplication] [[UIApplication sharedApplication]
setApplicationIconBadgeNumber:0]; setApplicationIconBadgeNumber:0];
[self execCallback:command];
}]; }];
} }
...@@ -214,20 +181,23 @@ ...@@ -214,20 +181,23 @@
} }
/** /**
* Informs if the app has the permission to show * Checks wether a notification with an ID was triggered.
* badges and local notifications.
* *
* @param {NSString} id
* The ID of the notification
* @param callback * @param callback
* The function to be exec as the callback * The callback function to be called with the result
*/ */
- (void) hasPermission:(CDVInvokedUrlCommand *)command - (void) isTriggered:(CDVInvokedUrlCommand*)command
{ {
[self.commandDelegate runInBackground:^{ [self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSString* id = [arguments objectAtIndex:0];
bool isTriggered = [self isNotificationTriggeredWithId:id];
CDVPluginResult* result; CDVPluginResult* result;
BOOL hasPermission = [self hasPermissionToSheduleNotifications];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:hasPermission]; messageAsBool:isTriggered];
[self.commandDelegate sendPluginResult:result [self.commandDelegate sendPluginResult:result
callbackId:command.callbackId]; callbackId:command.callbackId];
...@@ -235,49 +205,41 @@ ...@@ -235,49 +205,41 @@
} }
/** /**
* Ask for permission to show badges. * Retrieves a list of ids from all currently triggered notifications.
* *
* @param callback * @param callback
* The function to be exec as the callback * The callback function to be called with the result
*/ */
- (void) promptForPermission:(CDVInvokedUrlCommand *)command - (void) getTriggeredIds:(CDVInvokedUrlCommand*)command
{ {
if (IsAtLeastiOSVersion(@"8.0")) { [self.commandDelegate runInBackground:^{
UIUserNotificationType types; NSArray* notifications = self.scheduledNotifications;
UIUserNotificationSettings *settings;
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound;
settings = [UIUserNotificationSettings settingsForTypes:types NSMutableArray* scheduledIds = [[NSMutableArray alloc] init];
categories:nil]; CDVPluginResult* result;
[self.commandDelegate runInBackground:^{ for (UILocalNotification* notification in notifications)
[[UIApplication sharedApplication] {
registerUserNotificationSettings:settings]; if (![self isNotificationTriggered:notification]) {
}]; continue;
} }
}
/** NSString* id = [notification.userInfo objectForKey:@"id"];
* If the app has the permission to show badges.
*/
- (BOOL) hasPermissionToSheduleNotifications
{
if (IsAtLeastiOSVersion(@"8.0")) {
UIUserNotificationType types;
UIUserNotificationSettings *settings;
settings = [[UIApplication sharedApplication] [scheduledIds addObject:id];
currentUserNotificationSettings]; }
types = UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound; result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:scheduledIds];
return (settings.types & types); [self.commandDelegate sendPluginResult:result
} else { callbackId:command.callbackId];
return YES; }];
}
} }
#pragma mark -
#pragma mark Plugin core methods
/** /**
* Schedules a new local notification and fies the coresponding event. * Schedules a new local notification and fies the coresponding event.
* *
...@@ -313,8 +275,12 @@ ...@@ -313,8 +275,12 @@
NSString* id = [userInfo objectForKey:@"id"]; NSString* id = [userInfo objectForKey:@"id"];
NSString* json = [userInfo objectForKey:@"json"]; NSString* json = [userInfo objectForKey:@"json"];
[[UIApplication sharedApplication] if (notification==nil) {
cancelLocalNotification:notification]; NSLog(@"cancelNotification: Notification equals nil");
}else{
[[UIApplication sharedApplication]
cancelLocalNotification:notification];
}
if (fireEvent) { if (fireEvent) {
[self fireEvent:@"cancel" id:id json:json]; [self fireEvent:@"cancel" id:id json:json];
...@@ -340,7 +306,7 @@ ...@@ -340,7 +306,7 @@
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate: NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:
fireDate]; fireDate];
if (notification.repeatInterval == NSEraCalendarUnit if (notification.repeatInterval == NSCalendarUnitEra
&& fireDateDistance > seconds) { && fireDateDistance > seconds) {
[self cancelNotification:notification fireEvent:YES]; [self cancelNotification:notification fireEvent:YES];
} }
...@@ -348,70 +314,6 @@ ...@@ -348,70 +314,6 @@
} }
/** /**
* Retrurns a key-value dictionary for repeat intervals.
*
* @return {NSMutableDictionary}
*/
- (NSMutableDictionary*) repeatDict
{
NSMutableDictionary* repeatDict = [[NSMutableDictionary alloc] init];
#ifdef NSCalendarUnitHour
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitSecond] forKey:@"secondly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMinute] forKey:@"minutely"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitHour] forKey:@"hourly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitDay] forKey:@"daily"];
[repeatDict setObject:
[NSNumber numberWithInt:NSWeekCalendarUnit] forKey:@"weekly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMonth] forKey:@"monthly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitYear] forKey:@"yearly"];
#else
[repeatDict setObject:
[NSNumber numberWithInt:NSSecondCalendarUnit] forKey:@"secondly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSMinuteCalendarUnit] forKey:@"minutely"];
[repeatDict setObject:
[NSNumber numberWithInt:NSHourCalendarUnit] forKey:@"hourly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSDayCalendarUnit] forKey:@"daily"];
[repeatDict setObject:
[NSNumber numberWithInt:NSWeekCalendarUnit] forKey:@"weekly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSMonthCalendarUnit] forKey:@"monthly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSYearCalendarUnit] forKey:@"yearly"];
#endif
[repeatDict setObject:
[NSNumber numberWithInt:NSEraCalendarUnit] forKey:@""];
return repeatDict;
}
/**
* Returns the userDict for a local notification.
*
* @param {NSMutableDictionary} options
* The properties for the local notification
* @return {NSDictionary}
*/
- (NSDictionary*) userDict:(NSMutableDictionary*)options
{
NSString* id = [options objectForKey:@"id"];
NSString* ac = [options objectForKey:@"autoCancel"];
NSString* js = [options objectForKey:@"json"];
return [NSDictionary dictionaryWithObjectsAndKeys:
id, @"id", ac, @"autoCancel", js, @"json", nil];
}
/**
* Creates an notification object based on the given properties. * Creates an notification object based on the given properties.
* *
* @param {NSMutableDictionary} properties * @param {NSMutableDictionary} properties
...@@ -459,6 +361,9 @@ ...@@ -459,6 +361,9 @@
return notification; return notification;
} }
#pragma mark -
#pragma mark Plugin delegate and life cycle methods
/** /**
* Calls the cancel or trigger event after a local notification was received. * Calls the cancel or trigger event after a local notification was received.
* Cancels the local notification if autoCancel was set to true. * Cancels the local notification if autoCancel was set to true.
...@@ -477,6 +382,10 @@ ...@@ -477,6 +382,10 @@
NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:fireDate]; NSTimeInterval fireDateDistance = [now timeIntervalSinceDate:fireDate];
NSString* event = (fireDateDistance < 1) ? @"trigger" : @"click"; NSString* event = (fireDateDistance < 1) ? @"trigger" : @"click";
if ([[self applicationState] isEqualToString:@"foreground"]) {
event = @"trigger";
}
if (autoCancel && [event isEqualToString:@"click"]) { if (autoCancel && [event isEqualToString:@"click"]) {
[self cancelNotification:notification fireEvent:YES]; [self cancelNotification:notification fireEvent:YES];
} }
...@@ -533,6 +442,55 @@ ...@@ -533,6 +442,55 @@
[self cancelAllNotificationsWhichAreOlderThen:432000]; [self cancelAllNotificationsWhichAreOlderThen:432000];
} }
#pragma mark -
#pragma mark Plugin helper methods
/**
* Retrurns a key-value dictionary for repeat intervals.
*
* @return {NSMutableDictionary}
*/
- (NSMutableDictionary*) repeatDict
{
NSMutableDictionary* repeatDict = [[NSMutableDictionary alloc] init];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitSecond] forKey:@"secondly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMinute] forKey:@"minutely"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitHour] forKey:@"hourly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitDay] forKey:@"daily"];
[repeatDict setObject:
[NSNumber numberWithInt:NSWeekCalendarUnit] forKey:@"weekly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitMonth] forKey:@"monthly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitYear] forKey:@"yearly"];
[repeatDict setObject:
[NSNumber numberWithInt:NSCalendarUnitEra] forKey:@""];
return repeatDict;
}
/**
* Returns the userDict for a local notification.
*
* @param {NSMutableDictionary} options
* The properties for the local notification
* @return {NSDictionary}
*/
- (NSDictionary*) userDict:(NSMutableDictionary*)options
{
NSString* id = [options objectForKey:@"id"];
NSString* ac = [options objectForKey:@"autoCancel"];
NSString* js = [options objectForKey:@"json"];
return [NSDictionary dictionaryWithObjectsAndKeys:
id, @"id", ac, @"autoCancel", js, @"json", nil];
}
/** /**
* Checks weather the given string is empty or not. * Checks weather the given string is empty or not.
* *
...@@ -567,6 +525,41 @@ ...@@ -567,6 +525,41 @@
} }
/** /**
* Checks wether a notification with an ID was triggered or not.
*
* @param id
* The ID of the notification
* @return BOOL
*/
- (BOOL) isNotificationTriggeredWithId:(NSString*)id
{
UILocalNotification* notification = [self notificationWithId:id];
if (notification == NULL) {
return NO;
}
return [self isNotificationTriggered:notification];
}
/**
* Checks wether a notification was triggered or not.
*
* @param notification
* The notification
* @return BOOL
*/
- (BOOL) isNotificationTriggered:(UILocalNotification*)notification
{
NSDate* now = [NSDate date];
NSDate* fireDate = notification.fireDate;
bool isLaterThanOrEqualTo = !([now compare:fireDate] == NSOrderedAscending);
return isLaterThanOrEqualTo;
}
/**
* Retrieves the local notification by its ID. * Retrieves the local notification by its ID.
* *
* @param {NSString} id * @param {NSString} id
...@@ -579,9 +572,12 @@ ...@@ -579,9 +572,12 @@
for (UILocalNotification* notification in notifications) for (UILocalNotification* notification in notifications)
{ {
NSString* notId = [[notification.userInfo objectForKey:@"id"] NSString* notId = NULL;
stringValue]; if ([[notification.userInfo objectForKey:@"id"] isKindOfClass:[NSString class]] ) {
notId = [notification.userInfo objectForKey:@"id"];
} else {
notId = [[notification.userInfo objectForKey:@"id"] stringValue];
}
if ([notId isEqualToString:id]) { if ([notId isEqualToString:id]) {
return notification; return notification;
} }
...@@ -630,6 +626,21 @@ ...@@ -630,6 +626,21 @@
return notificationsWithoutNIL; return notificationsWithoutNIL;
} }
#pragma mark -
#pragma mark Plugin callback methods
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command
{
CDVPluginResult *result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}
/** /**
* Fires the given event. * Fires the given event.
* *
......
...@@ -84,6 +84,7 @@ namespace Cordova.Extension.Commands ...@@ -84,6 +84,7 @@ namespace Cordova.Extension.Commands
cancelAll(jsonArgs); cancelAll(jsonArgs);
FireEvent("cancel", notificationID, ""); FireEvent("cancel", notificationID, "");
DispatchCommandResult();
} }
/// <summary> /// <summary>
...@@ -132,22 +133,18 @@ namespace Cordova.Extension.Commands ...@@ -132,22 +133,18 @@ namespace Cordova.Extension.Commands
DispatchCommandResult(); DispatchCommandResult();
} }
/// <summery> /// <summary>
/// Informs if the app has the permission to show notifications. /// Checks wether a notification with an ID was triggered
/// </summery> /// </summary>
public void hasPermission(string args) public void isTriggered (string jsonArgs)
{ {
PluginResult result; DispatchCommandResult();
result = new PluginResult(PluginResult.Status.OK, true);
DispatchCommandResult(result);
} }
/// <summery> /// <summary>
/// Ask for permission to show notifications. /// Retrieves a list with all currently triggered notifications
/// </summery> /// </summary>
public void promptForPermission(string args) public void getTriggeredIds (string jsonArgs)
{ {
DispatchCommandResult(); DispatchCommandResult();
} }
......
...@@ -58,10 +58,14 @@ LocalNotification.prototype = { ...@@ -58,10 +58,14 @@ LocalNotification.prototype = {
/** /**
* @private * @private
* Merge settings with default values *
* Merges custom properties with the default values.
* *
* @param {Object} options * @param {Object} options
* Set of custom values
*
* @retrun {Object} * @retrun {Object}
* The merged property list
*/ */
mergeWithDefaults: function (options) { mergeWithDefaults: function (options) {
var defaults = this.getDefaults(); var defaults = this.getDefaults();
...@@ -77,6 +81,11 @@ LocalNotification.prototype = { ...@@ -77,6 +81,11 @@ LocalNotification.prototype = {
/** /**
* @private * @private
*
* Merges the platform specific properties into the default properties.
*
* @return {Object}
* The default properties for the platform
*/ */
applyPlatformSpecificOptions: function () { applyPlatformSpecificOptions: function () {
var defaults = this._defaults; var defaults = this._defaults;
...@@ -86,6 +95,7 @@ LocalNotification.prototype = { ...@@ -86,6 +95,7 @@ LocalNotification.prototype = {
defaults.icon = 'icon'; defaults.icon = 'icon';
defaults.smallIcon = null; defaults.smallIcon = null;
defaults.ongoing = false; defaults.ongoing = false;
defaults.led = 'FFFFFF'; /*RRGGBB*/
defaults.sound = 'TYPE_NOTIFICATION'; break; defaults.sound = 'TYPE_NOTIFICATION'; break;
case 'iOS': case 'iOS':
defaults.sound = ''; break; defaults.sound = ''; break;
...@@ -93,6 +103,30 @@ LocalNotification.prototype = { ...@@ -93,6 +103,30 @@ LocalNotification.prototype = {
defaults.smallImage = null; defaults.smallImage = null;
defaults.image = null; defaults.image = null;
defaults.wideImage = null; defaults.wideImage = null;
}
return defaults;
},
/**
* @private
*
* Creates a callback, which will be executed within a specific scope.
*
* @param {Function} callbackFn
* The callback function
* @param {Object} scope
* The scope for the function
*
* @return {Function}
* The new callback function
*/
createCallbackFn: function (callbackFn, scope) {
if (typeof callbackFn != 'function')
return;
return function () {
callbackFn.apply(scope || this, arguments);
}; };
}, },
...@@ -100,11 +134,18 @@ LocalNotification.prototype = { ...@@ -100,11 +134,18 @@ LocalNotification.prototype = {
* Add a new entry to the registry * Add a new entry to the registry
* *
* @param {Object} options * @param {Object} options
* @return {Number} The notification's ID * 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
*
* @return {Number}
* The notification's ID
*/ */
add: function (options) { add: function (options, callback, scope) {
var options = this.mergeWithDefaults(options), var options = this.mergeWithDefaults(options),
callbackFn = null; callbackFn = this.createCallbackFn(callback, scope);
if (options.id) { if (options.id) {
options.id = options.id.toString(); options.id = options.id.toString();
...@@ -114,11 +155,19 @@ LocalNotification.prototype = { ...@@ -114,11 +155,19 @@ LocalNotification.prototype = {
options.date = new Date(); options.date = new Date();
} }
if (options.title) {
options.title = options.title.toString();
}
if (options.message) {
options.message = options.message.toString();
}
if (typeof options.date == 'object') { if (typeof options.date == 'object') {
options.date = Math.round(options.date.getTime()/1000); options.date = Math.round(options.date.getTime()/1000);
} }
if (['WinCE', 'Win32NT'].indexOf(device.platform)) { if (['WinCE', 'Win32NT'].indexOf(device.platform) > -1) {
callbackFn = function (cmd) { callbackFn = function (cmd) {
eval(cmd); eval(cmd);
}; };
...@@ -130,100 +179,143 @@ LocalNotification.prototype = { ...@@ -130,100 +179,143 @@ LocalNotification.prototype = {
}, },
/** /**
* Cancels the specified notification * Cancels the specified notification.
* *
* @param {String} id of the notification * @param {String} id
* The ID of the notification
* @param {Function} callback
* A function to be called after the notification has been canceled
* @param {Object} scope
* The scope for the callback function
*/ */
cancel: function (id) { cancel: function (id, callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'cancel', [id.toString()]); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancel', [id]);
}, },
/** /**
* Removes all previously registered notifications * Removes all previously registered notifications.
*
* @param {Function} callback
* A function to be called after all notifications have been canceled
* @param {Object} scope
* The scope for the callback function
*/ */
cancelAll: function () { cancelAll: function (callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'cancelAll', []); var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'cancelAll', []);
}, },
/** /**
* @async
*
* Retrieves a list with all currently pending notifications. * Retrieves a list with all currently pending notifications.
* *
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
getScheduledIds: function (callback) { getScheduledIds: function (callback, scope) {
cordova.exec(callback, null, 'LocalNotification', 'getScheduledIds', []); var callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'getScheduledIds', []);
}, },
/** /**
* @async
*
* Checks wether a notification with an ID is scheduled. * Checks wether a notification with an ID is scheduled.
* *
* @param {String} id * @param {String} id
* The ID of the notification
* @param {Function} callback * @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
isScheduled: function (id, callback) { isScheduled: function (id, callback, scope) {
cordova.exec(callback, null, 'LocalNotification', 'isScheduled', [id.toString()]); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isScheduled', [id]);
}, },
/** /**
* Informs if the app has the permission to show badges. * Retrieves a list with all triggered notifications.
* *
* @param {Function} callback * @param {Function} callback
* The function to be exec as the callback * A callback function to be called with the list
* @param {Object?} scope * @param {Object} scope
* The callback function's scope * The scope for the callback function
*/ */
hasPermission: function (callback, scope) { getTriggeredIds: function (callback, scope) {
var fn = function (badge) { var callbackFn = this.createCallbackFn(callback, scope);
callback.call(scope || this, badge);
};
cordova.exec(fn, null, 'LocalNotification', 'hasPermission', []); cordova.exec(callbackFn, null, 'LocalNotification', 'getTriggeredIds', []);
}, },
/** /**
* Ask for permission to show badges if not already granted. * Checks wether a notification with an ID was triggered.
*
* @param {String} id
* The ID of the notification
* @param {Function} callback
* A callback function to be called with the list
* @param {Object} scope
* The scope for the callback function
*/ */
promptForPermission: function () { isTriggered: function (id, callback, scope) {
cordova.exec(null, null, 'LocalNotification', 'promptForPermission', []); var id = id.toString(),
callbackFn = this.createCallbackFn(callback, scope);
cordova.exec(callbackFn, null, 'LocalNotification', 'isTriggered', [id]);
}, },
/** /**
* Occurs when a notification was added. * Occurs when a notification was added.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
onadd: function (id, state, json) {}, onadd: function (id, state, json) {},
/** /**
* Occurs when the notification is triggered. * Occurs when the notification is triggered.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
ontrigger: function (id, state, json) {}, ontrigger: function (id, state, json) {},
/** /**
* Fires after the notification was clicked. * Fires after the notification was clicked.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
onclick: function (id, state, json) {}, onclick: function (id, state, json) {},
/** /**
* Fires if the notification was canceled. * Fires if the notification was canceled.
* *
* @param {String} id The ID of the notification * @param {String} id
* @param {String} state Either "foreground" or "background" * The ID of the notification
* @param {String} json A custom (JSON) string * @param {String} state
* Either "foreground" or "background"
* @param {String} json
* A custom (JSON) string
*/ */
oncancel: function (id, state, json) {} oncancel: function (id, state, json) {}
}; };
...@@ -231,24 +323,32 @@ LocalNotification.prototype = { ...@@ -231,24 +323,32 @@ LocalNotification.prototype = {
var plugin = new LocalNotification(), var plugin = new LocalNotification(),
channel = require('cordova/channel'); channel = require('cordova/channel');
// Called after all 'deviceready' listener are called
channel.deviceready.subscribe( function () { channel.deviceready.subscribe( function () {
// Device is ready now, the listeners are registered and all queued events
// can be executed now.
cordova.exec(null, null, 'LocalNotification', 'deviceready', []); cordova.exec(null, null, 'LocalNotification', 'deviceready', []);
}); });
channel.onCordovaReady.subscribe( function () { channel.onCordovaReady.subscribe( function () {
// The cordova device plugin is ready now
channel.onCordovaInfoReady.subscribe( function () { channel.onCordovaInfoReady.subscribe( function () {
if (device.platform == 'Android') { if (device.platform == 'Android') {
channel.onPause.subscribe( function () { channel.onPause.subscribe( function () {
// Necessary to set the state to `background`
cordova.exec(null, null, 'LocalNotification', 'pause', []); cordova.exec(null, null, 'LocalNotification', 'pause', []);
}); });
channel.onResume.subscribe( function () { channel.onResume.subscribe( function () {
// Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); cordova.exec(null, null, 'LocalNotification', 'resume', []);
}); });
// Necessary to set the state to `foreground`
cordova.exec(null, null, 'LocalNotification', 'resume', []); cordova.exec(null, null, 'LocalNotification', 'resume', []);
} }
// Merges the platform specific properties into the default properties
plugin.applyPlatformSpecificOptions(); plugin.applyPlatformSpecificOptions();
}); });
}); });
......
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