Commit 92ae360d by Sebastián Katzer

Added new callback registration interface and new callback types

parent e077ee32
......@@ -48,6 +48,7 @@ More informations can be found [here](https://build.phonegap.com/plugins/356).
## Release Notes
#### Version 0.7.0 (not yet released)
- **Note:** The new way of callback registration will be not compatible with previous versions! See #62
- [feature:] Added new callback registration interface and new callback types.
#### Version 0.7.0beta1 (17.01.2014)
- [bugfix:] App throws an error on iOS if `message` is null.
......@@ -123,8 +124,6 @@ window.plugin.notification.local.add({
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
ongoing: Boolean, // Prevent clearing of notification (Android only)
foreground: String, // A javascript function to be called if the app is running
background: String, // A javascript function to be called if the app is in the background
});
```
**Note:** On Android the notification id needs to be a string which can be converted to a number. If the ID has an invalid format, it will be ignored, but canceling the notification will fail.
......@@ -141,6 +140,15 @@ The method cancels all notifications which were previously added by the applicat
window.plugin.notification.local.cancelAll();
```
### onadd() | ontrigger() | onclick() | oncancel()
There are 4 different callback types available. For each of them one listener can be specified. The listener has to be a function and takes the following arguments:
- event: The Name of the event
- id: The ID of the notification
- json: A custom (JSON) string
```javascript
window.plugin.notification.local.on_callback_ = function (id, state, json) {};
```
## Examples
#### Will fire every week on this day, 60 seconds from now
......@@ -149,22 +157,12 @@ var now = new Date().getTime(),
_60_seconds_from_now = new Date(now + 60*1000);
window.plugin.notification.local.add({
id: 1, // is converted to a string
title: 'Reminder',
message: 'Dont forget to buy some flowers.',
repeat: 'weekly',
date: _60_seconds_from_now,
foreground: 'foreground',
background: 'background'
id: 1, // is converted to a string
title: 'Reminder',
message: 'Dont forget to buy some flowers.',
repeat: 'weekly',
date: _60_seconds_from_now
});
function foreground (id) {
console.log('I WAS RUNNING ID='+id)
}
function background (id) {
console.log('I WAS IN THE BACKGROUND ID='+id)
}
```
#### Pop's up immediately
......@@ -177,16 +175,20 @@ window.plugin.notification.local.add({ message: 'Great app!' });
window.plugin.notification.local.add({ sound: null });
```
#### Callback registration
```javascript
window.plugin.notification.local.onadd = function (id, state, json) {};
```
#### Pass data through the notification
```javascript
window.plugin.notification.local.add({
id: 1,
message: 'I love BlackBerry!',
json: { test: 123 },
foreground: 'foreground'
json: { test: 123 }
});
function foreground (id, json) {
window.plugin.notification.local.onclick = function (id, state, json) {
console.log(id, JSON.parse(json).test);
}
```
......
......@@ -3,7 +3,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="de.appplant.cordova.plugin.local-notification"
version="0.7.0beta1">
version="0.7.0dev">
<name>LocalNotification</name>
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -33,6 +33,7 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
......@@ -51,10 +52,10 @@ public class LocalNotification extends CordovaPlugin {
protected final static String PLUGIN_NAME = "LocalNotification";
protected static CordovaWebView webView = null;
private static CordovaWebView webView = null;
protected static Context context = null;
protected static ArrayList<String> callbackQueue = new ArrayList<String>();
private static ArrayList<String> callbackQueue = new ArrayList<String>();
@Override
public void initialize (CordovaInterface cordova, CordovaWebView webView) {
......@@ -119,6 +120,8 @@ public class LocalNotification extends CordovaPlugin {
AlarmManager am = getAlarmManager();
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
fireEvent("add", options.getId(), options.getJSON());
am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
}
......@@ -136,7 +139,6 @@ public class LocalNotification extends CordovaPlugin {
* Now we can search for such an intent using the 'getService' method
* and cancel it.
*/
Intent intent = new Intent(context, Receiver.class)
.setAction("" + notificationId);
......@@ -149,6 +151,8 @@ public class LocalNotification extends CordovaPlugin {
try {
nc.cancel(Integer.parseInt(notificationId));
} catch (Exception e) {}
fireEvent("cancel", notificationId, "");
}
/**
......@@ -210,13 +214,34 @@ public class LocalNotification extends CordovaPlugin {
* Clear all alarms from the Android shared Preferences.
*/
public static void unpersistAll () {
Editor editor = LocalNotification.getSharedPreferences().edit();
Editor editor = getSharedPreferences().edit();
editor.clear();
editor.commit();
}
/**
* Fires the given event.
*
* @param {String} event The Name of the event
* @param {String} id The ID of the notification
* @param {String} json A custom (JSON) string
*/
public static void fireEvent (String event, String id, String json) {
String state = isInBackground() ? "background" : "foreground";
String params = "\"" + id + "\",\"" + state + "\",\\'" + JSONObject.quote(json) + "\\'.replace(/(^\"|\"$)/g, \\'\\')";
String js = "setTimeout('plugin.notification.local.on" + event + "(" + params + ")',0)";
// after reboot, LocalNotification.webView is always be null
// call background callback later
if (webView == null) {
callbackQueue.add(js);
} else {
webView.sendJavascript(js);
}
}
/**
* Set the application context if not already set.
*/
protected static void setContext (Context context) {
......@@ -247,6 +272,13 @@ public class LocalNotification extends CordovaPlugin {
}
/**
* Gibt an, ob die App im Hintergrund läuft.
*/
private static boolean isInBackground () {
return !context.getPackageName().equalsIgnoreCase(((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).topActivity.getPackageName());
}
/**
* Calls all pending callbacks after the webview was created.
*/
private void execPendingCallbacks () {
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -187,20 +187,6 @@ public class Options {
}
/**
* Gibt den Pfad zur Callback-Funktion der Notification an.
*/
public String getForeground () {
return options.optString("foreground", null);
}
/**
* Gibt den Pfad zur Callback-Funktion der Notification an.
*/
public String getBackground () {
return options.optString("background", null);
}
/**
* Gibt das Intervall an, in dem die Notification aufpoppen soll (daily, weekly, monthly, yearly)
*/
public long getInterval () {
......@@ -228,10 +214,6 @@ public class Options {
return options.optBoolean("autoCancel", false);
}
public Boolean getOngoing() {
return options.optBoolean("ongoing", false);
}
/**
* Gibt die zusätzlichen Daten als String an.
*/
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -28,7 +28,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
......@@ -40,7 +39,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
......@@ -74,6 +72,8 @@ public class Receiver extends BroadcastReceiver {
// The context may got lost if the app was not running before
LocalNotification.setContext(context);
fireTriggerEvent();
if (options.getInterval() == 0) {
LocalNotification.unpersist(options.getId());
} else if (isFirstAlarmInFuture()) {
......@@ -84,10 +84,6 @@ public class Receiver extends BroadcastReceiver {
Builder notification = buildNotification();
if (!isInBackground(context)) {
invokeForegroundCallback();
}
showNotification(notification);
}
......@@ -130,8 +126,7 @@ public class Receiver extends BroadcastReceiver {
.setSmallIcon(options.getSmallIcon())
.setLargeIcon(icon)
.setSound(options.getSound())
.setAutoCancel(options.getAutoCancel())
.setOngoing(options.getOngoing());
.setAutoCancel(options.getAutoCancel());
setClickEvent(notification);
......@@ -176,25 +171,9 @@ public class Receiver extends BroadcastReceiver {
}
/**
* Gibt an, ob die App im Hintergrund läuft.
*/
private boolean isInBackground (Context context) {
return !context.getPackageName().equalsIgnoreCase(((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).topActivity.getPackageName());
}
/**
* Ruft die `foreground` Callback Funktion auf.
* Fires ontrigger event.
*/
private void invokeForegroundCallback () {
String function = options.getForeground();
// after reboot, LocalNotification.webView is always null
// may be call foreground callback later
if (!TextUtils.isEmpty(function) && LocalNotification.webView != null) {
String params = "\"" + options.getId() + "\",\\'" + JSONObject.quote(options.getJSON()) + "\\'.replace(/(^\"|\"$)/g, \\'\\')";
String js = "setTimeout('" + function + "(" + params + ")',0)";
LocalNotification.webView.sendJavascript(js);
}
private void fireTriggerEvent () {
LocalNotification.fireEvent("trigger", options.getId(), options.getJSON());
}
}
}
\ No newline at end of file
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -28,7 +28,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
public class ReceiverActivity extends Activity {
......@@ -45,7 +44,7 @@ public class ReceiverActivity extends Activity {
Options options = new Options(getApplicationContext()).parse(args);
launchMainIntent();
invokeBackgroundCallback(options);
fireClickEvent(options);
} catch (JSONException e) {}
}
......@@ -63,23 +62,9 @@ public class ReceiverActivity extends Activity {
}
/**
* Ruft die `background` Callback Funktion auf.
* Fires the onclick event.
*/
private void invokeBackgroundCallback (Options options) {
String function = options.getBackground();
if (TextUtils.isEmpty(function))
return;
String params = "\"" + options.getId() + "\",\\'" + JSONObject.quote(options.getJSON()) + "\\'.replace(/(^\"|\"$)/g, \\'\\')";
final String js = "setTimeout('" + function + "(" + params + ")',0)";
// after reboot, LocalNotification.webView is always null
// call background callback later
if (LocalNotification.webView == null) {
LocalNotification.callbackQueue.add(js);
} else {
LocalNotification.webView.sendJavascript(js);
}
private void fireClickEvent (Options options) {
LocalNotification.fireEvent("click", options.getId(), options.getJSON());
}
}
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -54,11 +54,14 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
NSArray* arguments = [command arguments];
NSMutableDictionary* options = [arguments objectAtIndex:0];
UILocalNotification* notification = [self notificationWithProperties:options];
NSString* notificationId = [notification.userInfo objectForKey:@"id"];
NSString* id = [notification.userInfo objectForKey:@"id"];
NSString* json = [notification.userInfo objectForKey:@"json"];
[self cancelNotificationWithId:notificationId];
[self cancelNotificationWithId:id];
[self archiveNotification:notification];
[self fireEvent:@"add" id:id json:json];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}];
}
......@@ -71,10 +74,13 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
- (void) cancel:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* arguments = [command arguments];
NSString* notificationId = [arguments objectAtIndex:0];
NSArray* arguments = [command arguments];
NSString* id = [arguments objectAtIndex:0];
[self cancelNotificationWithId:notificationId];
UILocalNotification* notification = [self cancelNotificationWithId:id];
NSString* json = [notification.userInfo objectForKey:@"json"];
[self fireEvent:@"cancel" id:id json:json];
}];
}
......@@ -105,7 +111,7 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
*
* @param {NSString} id Die ID der Notification
*/
- (void) cancelNotificationWithId:(NSString*)id
- (UILocalNotification*) cancelNotificationWithId:(NSString*)id
{
if (![self strIsNullOrEmpty:id])
{
......@@ -118,8 +124,12 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
[[UIApplication sharedApplication] cancelLocalNotification:notification];
return notification;
}
}
return NULL;
}
/**
......@@ -163,17 +173,11 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
- (NSDictionary*) userDict:(NSMutableDictionary*)options
{
NSString* id = [options objectForKey:@"id"];
NSString* bg = [options objectForKey:@"background"];
NSString* fg = [options objectForKey:@"foreground"];
NSString* ac = [options objectForKey:@"autoCancel"];
NSString* js = [options objectForKey:@"json"];
return [NSDictionary dictionaryWithObjectsAndKeys:
id, @"id",
bg, @"background",
fg, @"foreground",
ac, @"autoCancel",
js, @"json", nil];
id, @"id", ac, @"autoCancel", js, @"json", nil];
}
/**
......@@ -231,12 +235,11 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
{
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
bool isActive = state == UIApplicationStateActive;
NSString* event = isActive ? @"trigger" : @"click";
UILocalNotification* notification = [localNotification object];
NSString* id = [notification.userInfo objectForKey:@"id"];
NSString* json = [notification.userInfo objectForKey:@"json"];
NSString* callbackType = isActive ? @"foreground" : @"background";
NSString* callbackFn = [notification.userInfo objectForKey:callbackType];
BOOL autoCancel = [[notification.userInfo objectForKey:@"autoCancel"] boolValue];
if (autoCancel && !isActive)
......@@ -244,13 +247,7 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
[self cancelNotificationWithId:id];
}
if (![self strIsNullOrEmpty:callbackFn])
{
NSString* params = [NSString stringWithFormat:@"\"%@\",\\'%@\\'", id, json];
NSString* js = [NSString stringWithFormat:@"setTimeout('%@(%@)',0)", callbackFn, params];
[self.commandDelegate evalJs:js];
}
[self fireEvent:event id:id json:json];
}
/**
......@@ -269,4 +266,23 @@ NSString *const kAPP_LOCALNOTIFICATION = @"APP_LOCALNOTIFICATION";
return (str == (NSString*)[NSNull null] || [str isEqualToString:@""]) ? YES : NO;
}
/**
* Fires the given event.
*
* @param {String} event The Name of the event
* @param {String} id The ID of the notification
* @param {String} json A custom (JSON) string
*/
- (void) fireEvent:(NSString*) event id:(NSString*) id json:(NSString*) json
{
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
bool isActive = state == UIApplicationStateActive;
NSString* stateName = isActive ? @"foreground" : @"background";
NSString* params = [NSString stringWithFormat:@"\"%@\",\"%@\",\\'%@\\'", id, stateName, json];
NSString* js = [NSString stringWithFormat:@"setTimeout('plugin.notification.local.on%@(%@)',0)", event, params];
[self.commandDelegate evalJs:js];
}
@end
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -87,18 +87,6 @@ namespace De.APPPlant.Cordova.Plugin.LocalNotification
public string ID { get; set; }
/// <summary>
/// A javascript function to be called if the app is in the background
/// </summary>
[DataMember(IsRequired = false, Name = "background")]
public string Background { get; set; }
/// <summary>
/// A javascript function to be called if the app is running
/// </summary>
[DataMember(IsRequired = false, Name = "foreground")]
public string Foreground { get; set; }
/// <summary>
/// Setting this flag will make it so the notification is automatically canceled when the user clicks it
/// </summary>
[DataMember(IsRequired = false, Name = "autoCancel")]
......
/*
Copyright 2013 appPlant UG
Copyright 2013-2014 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
......@@ -40,9 +40,7 @@ LocalNotification.prototype = {
badge: 0,
id: '0',
json: '',
repeat: '',
background: '',
foreground: ''
repeat: ''
};
switch (device.platform) {
......@@ -58,10 +56,6 @@ LocalNotification.prototype = {
defaults.wideImage = null;
};
var callbackFn = function (cmd) {
eval(cmd);
};
for (var key in defaults) {
if (options[key] !== undefined) {
defaults[key] = options[key];
......@@ -76,7 +70,7 @@ LocalNotification.prototype = {
defaults.date = Math.round(defaults.date.getTime()/1000);
}
cordova.exec(callbackFn, null, 'LocalNotification', 'add', [defaults]);
cordova.exec(null, null, 'LocalNotification', 'add', [defaults]);
return defaults.id;
},
......@@ -95,7 +89,43 @@ LocalNotification.prototype = {
*/
cancelAll: function () {
cordova.exec(null, null, 'LocalNotification', 'cancelAll', []);
}
},
/**
* Occurs when a notification was added.
*
* @param {String} id The ID of the notification
* @param {String} state Either "foreground" or "background"
* @param {String} json A custom (JSON) string
*/
onadd: function (id, state, json) {},
/**
* Occurs when the notification is triggered.
*
* @param {String} id The ID of the notification
* @param {String} state Either "foreground" or "background"
* @param {String} json A custom (JSON) string
*/
ontrigger: function (id, state, json) {},
/**
* Fires after the notification was clicked.
*
* @param {String} id The ID of the notification
* @param {String} state Either "foreground" or "background"
* @param {String} json A custom (JSON) string
*/
onclick: function (id, state, json) {},
/**
* Fires if the notification was canceled.
*
* @param {String} id The ID of the notification
* @param {String} state Either "foreground" or "background"
* @param {String} json A custom (JSON) string
*/
oncancel: function (id, state, json) {}
};
var plugin = new LocalNotification();
......
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