Explorar o código

Added getFunctions to request notifications arguments
Changed add-,cancel-, and clear function
Revised class-structure

PKnittel %!s(int64=11) %!d(string=hai) anos
pai
achega
e364b93b7c

+ 11 - 6
plugin.xml

@@ -98,12 +98,17 @@
 
         <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/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/Restore.java"           target-dir="src/de/appplant/cordova/plugin/localnotification" />
-        <source-file src="src/android/ReceiverActivity.java"  target-dir="src/de/appplant/cordova/plugin/localnotification" />
-		<source-file src="src/android/DeleteIntentReceiver.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/Restore.java"           		target-dir="src/de/appplant/cordova/plugin/localnotification" />
+        <source-file src="src/android/ReceiverActivity.java"  		target-dir="src/de/appplant/cordova/plugin/localnotification" />
+		<source-file src="src/android/DeleteIntentReceiver.java"  	target-dir="src/de/appplant/cordova/plugin/localnotification" />
+		
+		<source-file src="src/android/notification/Options.java"           	target-dir="src/de/appplant/cordova/plugin/notification" />
+		<source-file src="src/android/notification/Asset.java"           	target-dir="src/de/appplant/cordova/plugin/notification" />
+		<source-file src="src/android/notification/Manager.java"           	target-dir="src/de/appplant/cordova/plugin/notification" />
+		<source-file src="src/android/notification/NotificationBuilder.java" target-dir="src/de/appplant/cordova/plugin/notification" />
+		<source-file src="src/android/notification/NotificationWrapper.java" target-dir="src/de/appplant/cordova/plugin/notification" />
     </platform>
 
     <!-- wp8 -->

+ 10 - 12
src/android/DeleteIntentReceiver.java

@@ -23,6 +23,7 @@ package de.appplant.cordova.plugin.localnotification;
 
 import java.util.Date;
 
+import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
@@ -31,10 +32,15 @@ import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 
+import de.appplant.cordova.plugin.notification.Options;
+
 public class DeleteIntentReceiver extends BroadcastReceiver {
 
     public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
 	
+    /**
+     * Is called when a Notification is cleared manualy by the User
+     */
 	@Override
 	public void onReceive(Context context, Intent intent) {
         Options options = null;
@@ -53,7 +59,8 @@ public class DeleteIntentReceiver extends BroadcastReceiver {
         
         Date now = new Date();
 		if ((options.getInterval()!=0)){
-			LocalNotification.persist(options.getId(), setInitDate(args));
+			options.setInitDate();
+			LocalNotification.persist(options.getId(), options.getJSONObject());
 		}
 		else if((new Date(options.getDate()).before(now))){
 			LocalNotification.unpersist(options.getId());
@@ -62,21 +69,12 @@ public class DeleteIntentReceiver extends BroadcastReceiver {
 		fireClearEvent(options);
 	}
 	
-	private JSONObject setInitDate(JSONObject arguments){
-    	long initialDate = arguments.optLong("date", 0) * 1000;
-    	try {
-    		arguments.put("initialDate", initialDate);
-		} catch (JSONException e) {
-			e.printStackTrace();
-		}
-    	return arguments;
-    }
-	
     /**
      * Fires onclear event.
      */
     private void fireClearEvent (Options options) {
-        LocalNotification.fireEvent("clear", options.getId(), options.getJSON());
+    	JSONArray data = new JSONArray().put(options.getJSONObject());
+        LocalNotification.fireEvent("clear", options.getId(), options.getJSON(),data);
     }
 
 }

+ 153 - 421
src/android/LocalNotification.java

@@ -22,14 +22,12 @@
 package de.appplant.cordova.plugin.localnotification;
 
 import java.util.ArrayList;
-import java.util.Date;
-import java.util.Map;
-import java.util.Set;
 
 import org.apache.cordova.CallbackContext;
 import org.apache.cordova.CordovaInterface;
 import org.apache.cordova.CordovaPlugin;
 import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.LOG;
 import org.apache.cordova.PluginResult;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -38,13 +36,13 @@ import org.json.JSONObject;
 import android.app.Activity;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.Context;
-import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.os.Build;
-import android.widget.Toast;
+import android.annotation.TargetApi;
+
+import de.appplant.cordova.plugin.notification.*;
 
 /**
  * This plugin utilizes the Android AlarmManager in combination with StatusBar
@@ -55,14 +53,17 @@ import android.widget.Toast;
 public class LocalNotification extends CordovaPlugin {
 
     protected final static String PLUGIN_NAME = "LocalNotification";
-
+    static protected final String STORAGE_FOLDER = "/localnotification";
     private   static CordovaWebView webView = null;
     private   static Boolean deviceready = false;
     protected static Context context = null;
     protected static Boolean isInBackground = true;
     private   static ArrayList<String> eventQueue = new ArrayList<String>();
     static Activity activity;
-
+    Asset asset;
+    Manager manager;
+    NotificationWrapper nWrapper;
+    
     @Override
     public void initialize (CordovaInterface cordova, CordovaWebView webView) {
         super.initialize(cordova, webView);
@@ -70,30 +71,28 @@ public class LocalNotification extends CordovaPlugin {
         LocalNotification.webView = super.webView;
         LocalNotification.context = super.cordova.getActivity().getApplicationContext();
         LocalNotification.activity = super.cordova.getActivity();
+        this.asset = new Asset(activity,STORAGE_FOLDER);
+        this.manager = new Manager(context, PLUGIN_NAME);
+        this.nWrapper = new NotificationWrapper(context,Receiver.class,PLUGIN_NAME,Receiver.OPTIONS);
     }
-
     @Override
     public boolean execute (String action, final JSONArray args, final CallbackContext command) throws JSONException {
+    	
         if (action.equalsIgnoreCase("add")) {
             cordova.getThreadPool().execute( new Runnable() {
-                public void run() {               	
-                    JSONObject arguments = setInitDate(args.optJSONObject(0));
-                    Options options      = new Options(context).parse(arguments);
-                    add(options, true);
-                    command.success();
-                }
-            });
-        }
-        
-        if (action.equalsIgnoreCase("addMultiple")) {
-            cordova.getThreadPool().execute( new Runnable() {
-                public void run() {    
+                public void run() { 
                 	JSONArray notifications = args.optJSONArray(0);
-                	for (int i =0; i<notifications.length();i++){
-                		JSONObject arguments = setInitDate(notifications.optJSONObject(i));
+                	JSONObject arguments;
+                	for(int i=0;i<notifications.length();i++){
+                		arguments = notifications.optJSONObject(i);
+                    	LOG.d("LocalNotification", arguments.toString());
+                		arguments = asset.parseURIs(arguments);
                 		Options options      = new Options(context).parse(arguments);
-                		add(options, true);
-                	}
+                		options.setInitDate();
+                    	nWrapper.schedule(options);
+                    	JSONArray data = new JSONArray().put(options.getJSONObject());
+                   		fireEvent("add", options.getId(), options.getJSON(), data);
+                	}                    
                     command.success();
                 }
             });
@@ -102,75 +101,84 @@ public class LocalNotification extends CordovaPlugin {
         if (action.equalsIgnoreCase("update")) {
         	cordova.getThreadPool().execute( new Runnable() {
                 public void run() {
-                	JSONObject updates = args.optJSONObject(0);
+                	JSONArray updates = args.optJSONArray(0);
+                	JSONObject updateContent;
+                	for(int i=0;i<updates.length();i++){
+                		updateContent = args.optJSONObject(i);
                 	
-                	update(updates);
+                		nWrapper.update(updateContent);
+                	}
                 	command.success();
                 }
             });
         }
         
-        if (action.equalsIgnoreCase("clear")) {
-        	cordova.getThreadPool().execute( new Runnable() {
-                public void run() {
-                	String id = args.optString(0);
-
-                    clear(id);
-                    command.success();
-                }
-            });
-        }
-        
-        if (action.equalsIgnoreCase("clearMultiple")) {
-        	cordova.getThreadPool().execute( new Runnable() {
+        if (action.equalsIgnoreCase("cancel")) {
+            cordova.getThreadPool().execute( new Runnable() {
                 public void run() {
                 	JSONArray ids = args.optJSONArray(0);
-                	for (int i =0; i<ids.length();i++){
-                        clear(ids.optString(i));
+                	String id;
+                	for(int i=0;i<ids.length();i++){
+                		id = args.optString(i);
+                		nWrapper.cancel(id);
+                    	JSONArray managerId = new JSONArray().put(id);
+                    	JSONArray data = new JSONArray().put(manager.getAll(managerId));
+                        fireEvent("cancel", id, "",data);
                 	}
                     command.success();
-                }
-            });
-        }
-        
-        if (action.equalsIgnoreCase("clearAll")) {
-        	cordova.getThreadPool().execute( new Runnable() {
-                public void run() {
-                	clearAll();
-                    command.success();
+                    
                 }
             });
         }
 
-        if (action.equalsIgnoreCase("cancel")) {
+        if (action.equalsIgnoreCase("cancelAll")) {
             cordova.getThreadPool().execute( new Runnable() {
                 public void run() {
-                    String id = args.optString(0);
-
-                    cancel(id);
-                    unpersist(id);
+                	JSONArray options = manager.getAll();
+                    nWrapper.cancelAll();
+                	String id;
+                	JSONObject arguments;
+                    for(int i=0;i<options.length();i++){
+                    	arguments= (JSONObject) options.opt(i);
+                      	JSONArray data = new JSONArray().put(arguments);
+                      	id = arguments.optString("id");
+                      	fireEvent("cancel", id, "",data);
+                    }
                     command.success();
                 }
             });
         }
         
-        if (action.equalsIgnoreCase("cancelMultiple")) {
+        if (action.equalsIgnoreCase("clear")) {
         	cordova.getThreadPool().execute( new Runnable() {
                 public void run() {
                 	JSONArray ids = args.optJSONArray(0);
-                	for (int i =0; i<ids.length();i++){
-                        cancel(ids.optString(i));
+                	String id;
+                	for(int i=0;i<ids.length();i++){
+                		id = args.optString(i);
+                		nWrapper.clear(id);
+                    	JSONArray managerId = new JSONArray().put(id);
+                    	JSONArray data = new JSONArray().put(manager.getAll(managerId));
+                        fireEvent("clear", id, "",data);
                 	}
                     command.success();
                 }
             });
         }
-
-        if (action.equalsIgnoreCase("cancelAll")) {
-            cordova.getThreadPool().execute( new Runnable() {
+        
+        if (action.equalsIgnoreCase("clearAll")) {
+        	cordova.getThreadPool().execute( new Runnable() {
                 public void run() {
-                    cancelAll();
-                    unpersistAll();
+                	JSONArray options = manager.getAll();
+                	nWrapper.clearAll();
+                	String id;
+                	JSONObject arguments;
+                    for(int i=0;i<options.length();i++){
+                    	arguments= (JSONObject) options.opt(i);
+                      	JSONArray data = new JSONArray().put(arguments);
+                      	id = arguments.optString("id");
+                      	fireEvent("clear", id, "",data);
+                    }
                     command.success();
                 }
             });
@@ -178,22 +186,74 @@ public class LocalNotification extends CordovaPlugin {
 
         if (action.equalsIgnoreCase("isScheduled")) {
             String id = args.optString(0);
-
-            isScheduled(id, command);
-        }
-
-        if (action.equalsIgnoreCase("getScheduledIds")) {
-            getScheduledIds(command);
+        	boolean isScheduled = manager.isScheduled(id);        
+            PluginResult result        = new PluginResult(PluginResult.Status.OK, (isScheduled));
+            command.sendPluginResult(result);
         }
-
+        
         if (action.equalsIgnoreCase("isTriggered")) {
             String id = args.optString(0);
+            boolean isTriggered        = manager.isTriggered(id);
+            PluginResult result = new PluginResult(PluginResult.Status.OK, isTriggered);
+            command.sendPluginResult(result);
+        }
+        
+        if (action.equalsIgnoreCase("exist")) {
+            String id = args.optString(0);
+            boolean exist        = manager.exist(id);
+            PluginResult result = new PluginResult(PluginResult.Status.OK, exist);
+            command.sendPluginResult(result);
+        }
 
-            isTriggered(id, command);
+        if (action.equalsIgnoreCase("getScheduledIds")) {
+        	JSONArray scheduledIds     = manager.getScheduledIds();
+            command.success(scheduledIds);
         }
 
         if (action.equalsIgnoreCase("getTriggeredIds")) {
-            getTriggeredIds(command);
+            JSONArray triggeredIds     = manager.getTriggeredIds();
+            command.success(triggeredIds);
+        }
+        
+        if (action.equalsIgnoreCase("getAllIds")) {
+            JSONArray allIds     = manager.getAllIds();
+            command.success(allIds);
+        }
+        
+        if (action.equalsIgnoreCase("getAll")) {
+        	JSONArray ids;
+        	JSONArray all;
+        	try{
+        		ids = args.getJSONArray(0);
+        		all = manager.getAll(ids);
+        	} catch (JSONException jse){
+        		all = manager.getAll();
+        	}
+        	command.success(all);
+        }
+        
+        if (action.equalsIgnoreCase("getTriggered")) {
+        	JSONArray ids;
+        	JSONArray triggered;
+        	try{
+        		ids = args.getJSONArray(0);
+        		triggered = manager.getTriggered(ids);
+        	} catch (JSONException jse){
+        		triggered = manager.getTriggered();
+        	}
+        	command.success(triggered);
+        }
+        
+        if (action.equalsIgnoreCase("getScheduled")) {
+        	JSONArray ids;
+        	JSONArray scheduled;
+        	try{
+        		ids = args.getJSONArray(0);
+        		scheduled = manager.getScheduled(ids);
+        	} catch (JSONException jse){
+        		scheduled = manager.getScheduled();
+        	}
+        	command.success(scheduled);
         }
 
         if (action.equalsIgnoreCase("deviceready")) {
@@ -222,310 +282,12 @@ public class LocalNotification extends CordovaPlugin {
         deviceready = true;
 
         for (String js : eventQueue) {
-            webView.sendJavascript(js);
+            sendJavascript(js);
         }
 
         eventQueue.clear();
     }
 
-    /**
-     * Set an alarm.
-     *
-     * @param options
-     *            The options that can be specified per alarm.
-     * @param doFireEvent
-     *            If the onadd callback shall be called.
-     */
-    public static void add (Options options, boolean doFireEvent) {
-        long triggerTime = options.getDate();
-        
-        persist(options.getId(), options.getJSONObject());
-
-        //Intent is called when the Notification gets fired
-        Intent intent = new Intent(context, Receiver.class)
-            .setAction("" + options.getId())
-            .putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
-
-        AlarmManager am  = getAlarmManager();
-        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-
-        if (doFireEvent) {
-            fireEvent("add", options.getId(), options.getJSON());
-        }
-
-        am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
-    }
-
-    /** 
-     * Update an existing notification 
-     * 
-     * @param updates JSONObject with update-content
-     */
-    public static void update (JSONObject updates){
-    	String id = updates.optString("id", "0");
-    	
-    	// update shared preferences
-    	SharedPreferences settings = getSharedPreferences();
-    	Map<String, ?> alarms      = settings.getAll();
-    	JSONObject arguments;
-		try {
-			arguments = new JSONObject(alarms.get(id).toString());
-		} catch (JSONException e) {
-			e.printStackTrace();
-			return;
-		}
-		arguments = updateArguments(arguments, updates);
-		    	
-    	// cancel existing alarm
-        Intent intent = new Intent(context, Receiver.class)
-        	.setAction("" + id);
-        PendingIntent pi       = PendingIntent.getBroadcast(context, 0, intent, 0);
-        AlarmManager am        = getAlarmManager();
-        am.cancel(pi);
-        
-        //add new alarm
-        Options options      = new Options(context).parse(arguments);
-        add(options,false);        
-    }
-    
-    /**
-     * Clear a specific notification without canceling repeating alarms
-     * 
-     * @param notificationID
-     *            The original ID of the notification that was used when it was
-     *            registered using add()
-     */
-    public static void clear (String notificationId){
-    	SharedPreferences settings = getSharedPreferences();
-    	Map<String, ?> alarms      = settings.getAll();
-        NotificationManager nc = getNotificationManager();
-
-        try {
-            nc.cancel(Integer.parseInt(notificationId));
-        } catch (Exception e) {}
-        
-        JSONObject arguments;
-		try {
-			arguments = new JSONObject(alarms.get(notificationId).toString());
-			Options options      = new Options(context).parse(arguments);
-			Date now = new Date();
-			if ((options.getInterval()!=0)){
-				persist(notificationId, setInitDate(arguments));
-			}
-			else if((new Date(options.getDate()).before(now))){
-				unpersist(notificationId);
-			}
-		} catch (JSONException e) {
-			e.printStackTrace();
-			return;
-		}
-		
-        fireEvent("clear", notificationId, "");
-    }
-    
-    /**
-     * Clear all notifications without canceling repeating alarms
-     */
-    public static void clearAll (){
-        SharedPreferences settings = getSharedPreferences();
-        NotificationManager nc     = getNotificationManager();
-        Map<String, ?> alarms      = settings.getAll();
-        Set<String> alarmIds       = alarms.keySet();
-
-        for (String alarmId : alarmIds) {
-            clear(alarmId);
-        }
-
-        nc.cancelAll();
-    }
-
-    
-    
-    /**
-     * Cancel a specific notification that was previously registered.
-     *
-     * @param notificationId
-     *            The original ID of the notification that was used when it was
-     *            registered using add()
-     */
-    public static void cancel (String notificationId) {
-        /*
-         * Create an intent that looks similar, to the one that was registered
-         * using add. Making sure the notification id in the action is the same.
-         * Now we can search for such an intent using the 'getService' method
-         * and cancel it.
-         */
-        Intent intent = new Intent(context, Receiver.class)
-            .setAction("" + notificationId);
-
-        PendingIntent pi       = PendingIntent.getBroadcast(context, 0, intent, 0);
-        AlarmManager am        = getAlarmManager();
-        NotificationManager nc = getNotificationManager();
-
-        am.cancel(pi);
-
-        try {
-            nc.cancel(Integer.parseInt(notificationId));
-        } catch (Exception e) {}
-
-        fireEvent("cancel", notificationId, "");
-    }
-
-    /**
-     * Cancel all notifications that were created by this plugin.
-     *
-     * Android can only unregister a specific alarm. There is no such thing
-     * as cancelAll. Therefore we rely on the Shared Preferences which holds
-     * all our alarms to loop through these alarms and unregister them one
-     * by one.
-     */
-    public static void cancelAll() {
-        SharedPreferences settings = getSharedPreferences();
-        NotificationManager nc     = getNotificationManager();
-        Map<String, ?> alarms      = settings.getAll();
-        Set<String> alarmIds       = alarms.keySet();
-
-        for (String alarmId : alarmIds) {
-            cancel(alarmId);
-        }
-
-        nc.cancelAll();
-    }
-
-    /**
-     * Checks if a notification with an ID is scheduled.
-     *
-     * @param id
-     *          The notification ID to be check.
-     * @param callbackContext
-     */
-    public static void isScheduled (String id, CallbackContext command) {
-        SharedPreferences settings = getSharedPreferences();
-        Map<String, ?> alarms      = settings.getAll();
-        boolean isScheduled        = alarms.containsKey(id);
-        boolean isNotTriggered	   = false;
-        
-        if (isScheduled) {
-        	JSONObject arguments;
-			try {
-				arguments = new JSONObject(alarms.get(id).toString());
-	        	Options options      = new Options(context).parse(arguments);
-	        	Date fireDate        = new Date(options.getDate());
-	        	isNotTriggered = new Date().before(fireDate);
-			} catch (JSONException e) {
-				isNotTriggered = false;
-				e.printStackTrace();
-			}
-        	
-        }
-        
-        PluginResult result        = new PluginResult(PluginResult.Status.OK, (isScheduled && isNotTriggered));
-
-        command.sendPluginResult(result);
-    }
-
-    /**
-     * Retrieves a list with all currently pending notifications.
-     *
-     * @param callbackContext
-     */
-    public static void getScheduledIds (CallbackContext command) {
-        SharedPreferences settings = getSharedPreferences();
-        Map<String, ?> alarms      = settings.getAll();
-        Set<String> alarmIds       = alarms.keySet();
-        JSONArray scheduledIds     = new JSONArray();
-        
-        for (String id : alarmIds) {
-        	boolean isScheduled;
-        	JSONObject arguments;
- 			try {
- 				arguments = new JSONObject(alarms.get(id).toString());
- 	        	Options options      = new Options(context).parse(arguments);
- 	        	Date fireDate        = new Date(options.getDate());
- 	        	isScheduled = new Date().before(fireDate);
- 			} catch (JSONException e) {
- 				isScheduled = false;
- 				e.printStackTrace();
- 			}
- 			if (isScheduled){
- 				scheduledIds.put(id);
- 			}
-        }
-
-        
-        
-        command.success(scheduledIds);
-    }
-
-    /**
-     * Checks if a notification with an ID was triggered.
-     *
-     * @param id
-     *          The notification ID to be check.
-     * @param callbackContext
-     */
-    public static void isTriggered (String id, CallbackContext command) {
-        SharedPreferences settings = getSharedPreferences();
-        Map<String, ?> alarms      = settings.getAll();
-        boolean isScheduled        = alarms.containsKey(id);
-        boolean isTriggered        = isScheduled;
-
-        if (isScheduled) {
-        	JSONObject arguments;
-			try {
-				arguments = new JSONObject(alarms.get(id).toString());
-	        	Options options      = new Options(context).parse(arguments);
-	        	Date fireDate        = new Date(options.getInitialDate());
-	        	isTriggered = new Date().after(fireDate);
-			} catch (JSONException e) {
-				isTriggered = false;
-				e.printStackTrace();
-			}
-        	
-        }
-        	
-        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 triggeredIds     = new JSONArray();
-        Date now                   = new Date();
-
-        for (String id : alarmIds) {
-        	boolean isTriggered;
-        	JSONObject arguments;
-        	try{
-        		arguments = new JSONObject(alarms.get(id).toString());
-        		Options options      = new Options(context).parse(arguments);
-        		Date fireDate        = new Date(options.getInitialDate());
-        		isTriggered  = now.after(fireDate);
-            } catch(ClassCastException cce) {
-            	cce.printStackTrace();
-            	isTriggered = false;
-            }
-        	catch(JSONException jse) {
-        		jse.printStackTrace();
-            	isTriggered = false;
-            }
-
-            if (isTriggered == true) {
-                triggeredIds.put(id);
-            }
-        }
-
-        command.success(triggeredIds);
-    }
-
     /**
      * Persist the information of this alarm to the Android Shared Preferences.
      * This will allow the application to restore the alarm upon device reboot.
@@ -582,6 +344,7 @@ public class LocalNotification extends CordovaPlugin {
         }
     }
 
+    // 
     /**
      * Fires the given event.
      *
@@ -589,9 +352,11 @@ public class LocalNotification extends CordovaPlugin {
      * @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) {
+    public static void fireEvent (String event, String id, String json, JSONArray data) {
         String state  = getApplicationState();
+        //TODO dataArray handling
         String params = "\"" + id + "\",\"" + state + "\",\\'" + JSONObject.quote(json) + "\\'.replace(/(^\"|\"$)/g, \\'\\')";
+     //   params = params + "," + dataArray;
         String js     = "setTimeout('plugin.notification.local.on" + event + "(" + params + ")',0)";
 
         // webview may available, but callbacks needs to be executed
@@ -599,7 +364,7 @@ public class LocalNotification extends CordovaPlugin {
         if (deviceready == false) {
             eventQueue.add(js);
         } else {
-            webView.sendJavascript(js);
+            sendJavascript(js);
         }
     }
 
@@ -643,54 +408,21 @@ public class LocalNotification extends CordovaPlugin {
         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
     }
     
-    /**
-     * Function to set the value of "initialDate" in the JSONArray
-     * @param args The given JSONArray
-     * @return A new JSONArray with the parameter "initialDate" set.
-     */
-    private static JSONObject setInitDate(JSONObject arguments){
-    	long initialDate = arguments.optLong("date", 0) * 1000;
-    	try {
-    		arguments.put("initialDate", initialDate);
-		} catch (JSONException e) {
-			e.printStackTrace();
-		}
-    	return arguments;
-    }
-    
-    private static JSONObject updateArguments(JSONObject arguments,JSONObject updates){
-    	try	{
-    		if(!updates.isNull("message")){
-    			arguments.put("message", updates.get("message"));
-    		}
-    		if(!updates.isNull("title")){
-    			arguments.put("title", updates.get("title"));
-    		}
-    		if(!updates.isNull("badge")){
-    			arguments.put("badge", updates.get("badge"));
-    		}
-    		if(!updates.isNull("sound")){
-    			arguments.put("sound", updates.get("sound"));
-    		}
-    		if(!updates.isNull("icon")){
-    			arguments.put("icon", updates.get("icon"));
-    		}
-    	} catch (JSONException jse){
-    		jse.printStackTrace();
-    	}
-    	
-    	return arguments;
-    }
     
-    public static void showNotification(String title,String notification){
-       	int duration = Toast.LENGTH_LONG;
-       	if(title.equals("")){
-       		title = "Notification";
-       	}
-       	String text = title + " \n " + notification;
-       	
-    	Toast notificationToast = Toast.makeText(context, text, duration);
-    	notificationToast.show();
+   /**
+    * Use this instead of deprecated sendJavascript
+    */
+   @TargetApi(Build.VERSION_CODES.KITKAT)
+   private static void sendJavascript(final String js){
+	   webView.post(new Runnable(){
+		   public void run(){
+			   if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.KITKAT){
+				   webView.evaluateJavascript(js, null);
+			   } else {
+				   webView.loadUrl("javascript:" + js);
+			   }
+		   }
+	   });
    }
     
   

+ 14 - 92
src/android/Receiver.java

@@ -22,23 +22,18 @@
 package de.appplant.cordova.plugin.localnotification;
 
 import java.util.Calendar;
-import java.util.Random;
 
+import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import android.annotation.SuppressLint;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.app.NotificationCompat.*;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 
+import de.appplant.cordova.plugin.notification.*;
+
 /**
  * The alarm receiver is triggered when a scheduled alarm is fired. This class
  * reads the information in the intent and displays this information in the
@@ -49,11 +44,12 @@ public class Receiver extends BroadcastReceiver {
 
     public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
 
-    private Context context;
     private Options options;
 
     @Override
     public void onReceive (Context context, Intent intent) {
+    	NotificationWrapper nWrapper = new NotificationWrapper(context,
+    			Receiver.class,LocalNotification.PLUGIN_NAME,OPTIONS);
         Options options = null;
         Bundle bundle   = intent.getExtras();
         JSONObject args;
@@ -64,9 +60,10 @@ public class Receiver extends BroadcastReceiver {
         } catch (JSONException e) {
             return;
         }
-
-        this.context = context;
         this.options = options;
+        
+    	NotificationBuilder builder = new NotificationBuilder(options,context,OPTIONS,
+    			DeleteIntentReceiver.class,ReceiverActivity.class);
 
         // The context may got lost if the app was not running before
         LocalNotification.setContext(context);
@@ -77,18 +74,18 @@ public class Receiver extends BroadcastReceiver {
         } else if (isFirstAlarmInFuture()) {
             return;
         } else {
-            LocalNotification.add(options.moveDate(), false);
+            nWrapper.schedule(options.moveDate());
         }
         if (!LocalNotification.isInBackground && options.getForegroundMode()){
         	if (options.getInterval() == 0) {
         		LocalNotification.unpersist(options.getId());
         	}
-        	LocalNotification.showNotification(options.getTitle(), options.getMessage());
+        	builder.showNotificationToast();
         	fireTriggerEvent();
         } else {
-        	Builder notification = buildNotification();
+        	builder.buildNotification();
 
-        	showNotification(notification);
+        	builder.showNotification();
         }
     }
 
@@ -117,86 +114,11 @@ public class Receiver extends BroadcastReceiver {
         return false;
     }
 
-    /**
-     * Creates the notification.
-     */
-    @SuppressLint("NewApi")
-    private Builder buildNotification () {
-        Uri sound = options.getSound();
-        
-        //DeleteIntent is called when the user clears a notification manually
-        Intent deleteIntent = new Intent(context, DeleteIntentReceiver.class)
-        	.setAction("" + options.getId())
-        	.putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
-        PendingIntent dpi = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-        
-        Builder notification = new NotificationCompat.Builder(context)
-            .setDefaults(0) // Do not inherit any defaults
-            .setContentTitle(options.getTitle())
-            .setContentText(options.getMessage())
-            .setNumber(options.getBadge())
-            .setTicker(options.getMessage())
-            .setSmallIcon(options.getSmallIcon())
-            .setLargeIcon(options.getIcon())
-            .setAutoCancel(options.getAutoCancel())
-            .setOngoing(options.getOngoing())
-            .setLights(options.getColor(), 500, 500)
-            .setDeleteIntent(dpi);
-
-        if (sound != null) {
-            notification.setSound(sound);
-        }
-
-        if (Build.VERSION.SDK_INT > 16) {
-            notification.setStyle(new NotificationCompat.BigTextStyle()
-                .bigText(options.getMessage()));
-        }
-
-        setClickEvent(notification);
-
-        return notification;
-    }
-
-    /**
-     * Adds an onclick handler to the notification
-     */
-    private Builder setClickEvent (Builder notification) {
-        Intent intent = new Intent(context, ReceiverActivity.class)
-            .putExtra(OPTIONS, options.getJSONObject().toString())
-            .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
-
-        int requestCode = new Random().nextInt();
-
-        PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-
-        return notification.setContentIntent(contentIntent);
-    }
-
-    /**
-     * Shows the notification
-     */
-    @SuppressWarnings("deprecation")
-    private void showNotification (Builder notification) {
-        NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        int id                  = 0;
-
-        try {
-            id = Integer.parseInt(options.getId());
-        } catch (Exception e) {}
-
-        if (Build.VERSION.SDK_INT<16) {
-            // build notification for HoneyComb to ICS
-            mgr.notify(id, notification.getNotification());
-        } else if (Build.VERSION.SDK_INT>15) {
-            // Notification for Jellybean and above
-            mgr.notify(id, notification.build());
-        }
-    }
-
     /**
      * Fires ontrigger event.
      */
     private void fireTriggerEvent () {
-        LocalNotification.fireEvent("trigger", options.getId(), options.getJSON());
+    	JSONArray data = new JSONArray().put(options.getJSONObject());
+        LocalNotification.fireEvent("trigger", options.getId(), options.getJSON(),data);
     }
 }

+ 6 - 2
src/android/ReceiverActivity.java

@@ -23,12 +23,15 @@ package de.appplant.cordova.plugin.localnotification;
 
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.json.JSONArray;
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 
+import de.appplant.cordova.plugin.notification.*;
+
 public class ReceiverActivity extends Activity {
 
     /** Called when the activity is first created. */
@@ -65,10 +68,11 @@ public class ReceiverActivity extends Activity {
      * Fires the onclick event.
      */
     private void fireClickEvent (Options options) {
-        LocalNotification.fireEvent("click", options.getId(), options.getJSON());
+    	JSONArray data = new JSONArray().put(options.getJSONObject());
+        LocalNotification.fireEvent("click", options.getId(), options.getJSON(),data);
 
         if (options.getAutoCancel()) {
-            LocalNotification.fireEvent("cancel", options.getId(), options.getJSON());
+            LocalNotification.fireEvent("cancel", options.getId(), options.getJSON(),data);
         }
     }
 }

+ 7 - 2
src/android/Restore.java

@@ -31,6 +31,8 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 
+import de.appplant.cordova.plugin.notification.*;
+
 /**
  * This class is triggered upon reboot of the device. It needs to re-register
  * the alarms with the AlarmManager since these alarms are lost in case of
@@ -42,6 +44,9 @@ public class Restore extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
         // The application context needs to be set as first
         LocalNotification.setContext(context);
+        //Create NotificationWrapper
+    	NotificationWrapper nWrapper = new NotificationWrapper(context,
+    			Receiver.class,LocalNotification.PLUGIN_NAME,Receiver.OPTIONS);
 
         // Obtain alarm details form Shared Preferences
         SharedPreferences alarms = LocalNotification.getSharedPreferences();
@@ -59,8 +64,8 @@ public class Restore extends BroadcastReceiver {
                 /*
                  * If the trigger date was in the past, the notification will be displayed immediately.
                  */
-                LocalNotification.add(options, false);
-
+                nWrapper.schedule(options);
+                
             } catch (JSONException e) {}
         }
     }

+ 310 - 0
src/android/notification/Asset.java

@@ -0,0 +1,310 @@
+/*
+    Copyright 2013-2014 appPlant UG
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+package de.appplant.cordova.plugin.notification;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.StrictMode;
+import android.util.Log;
+
+
+public class Asset {
+	private Activity activity;
+	protected final String STORAGE_FOLDER;
+	
+	/**
+	 * Constructor of Asset Class. Takes Applications Activity and a foldername for temporary saving.
+	 *
+	 *@param activity Applications Activity
+	 *@param storageFolder foldername for temporary saving.
+	 */
+	public Asset(Activity activity,String storageFolder){
+		this.activity = activity;
+		this.STORAGE_FOLDER = storageFolder;
+	}
+	
+	/**
+	 * Parse given PathStrings to Uris
+	 * @param notification Notifications JSONObject
+	 * @return	new Notification JSONObject with additional iconUri and soundUri
+	 */
+    public JSONObject parseURIs(JSONObject notification){
+    	//sound
+        String sound = notification.optString("sound", null);	
+        Uri soundUri = null;
+        if (sound != null) {
+            try {
+                int soundId = (Integer) RingtoneManager.class.getDeclaredField(sound).get(Integer.class);
+
+                soundUri = RingtoneManager.getDefaultUri(soundId);
+            } catch (Exception e) {
+            	soundUri = getURIfromPath(sound);
+            }
+        }
+        if (soundUri!= null&&soundUri!=Uri.EMPTY){
+        	try{
+        		notification.put("soundUri", soundUri.toString());
+        	} catch (JSONException jse){
+        		jse.printStackTrace();
+        	}
+        }
+    	//image
+        String icon = notification.optString("icon", "icon");
+        Uri iconUri = null;
+        iconUri = getURIfromPath(icon);
+        if (iconUri != Uri.EMPTY&&iconUri != null){
+        	try{
+        		notification.put("iconUri", iconUri.toString());
+        	} catch (JSONException jse){
+        		jse.printStackTrace();
+        	}
+        }
+        return notification;
+    }
+	
+	/**
+	 * The URI for a path.
+	 * 
+	 * @param path The given path
+	 * 
+	 * @return The URI pointing to the given path
+	 */
+    public Uri getURIfromPath(String path){
+		if (path.startsWith("res:")) {
+			return getUriForResourcePath(path);
+		} else if (path.startsWith("file:///")) {
+			return getUriForAbsolutePath(path);
+		} else if (path.startsWith("file://")) {
+			return getUriForAssetPath(path);
+		} else if (path.startsWith("http")){
+			return getUriForHTTP(path);
+		}
+		return Uri.parse(path);
+	}
+    
+
+    
+	/**
+	 * The URI for a file.
+	 * 
+	 * @param path
+	 *            The given absolute path
+	 * 
+	 * @return The URI pointing to the given path
+	 */
+	private Uri getUriForAbsolutePath(String path) {
+		String absPath = path.replaceFirst("file://", "");
+		File file = new File(absPath);
+		if (!file.exists()) {
+			Log.e("Asset", "File not found: " + file.getAbsolutePath());
+			return Uri.EMPTY;
+		}
+		return Uri.fromFile(file);
+	}
+
+	/**
+	 * The URI for an asset.
+	 * 
+	 * @param path
+	 *            The given asset path
+	 * 
+	 * @return The URI pointing to the given path
+	 */
+	private Uri getUriForAssetPath(String path) {
+		String resPath = path.replaceFirst("file:/", "www");
+		String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
+		File dir = 		activity.getExternalCacheDir();
+		if (dir == null) {
+			Log.e("Asset", "Missing external cache dir");
+			return Uri.EMPTY;
+		}
+		String storage = dir.toString() + STORAGE_FOLDER;
+		File file = new File(storage, fileName);
+		new File(storage).mkdir();
+		try {
+			AssetManager assets = activity.getAssets();
+			FileOutputStream outStream = new FileOutputStream(file);
+			InputStream inputStream = assets.open(resPath);
+			copyFile(inputStream, outStream);
+			outStream.flush();
+			outStream.close();
+			return Uri.fromFile(file);
+		} catch (Exception e) {
+			Log.e("Asset", "File not found: assets/" + resPath);
+			e.printStackTrace();
+		}
+		return Uri.EMPTY;
+	}
+
+	/**
+	 * The URI for a resource.
+	 * 
+	 * @param path
+	 *            The given relative path
+	 * 
+	 * @return The URI pointing to the given path
+	 */
+	private Uri getUriForResourcePath(String path) {
+		String resPath = path.replaceFirst("res://", "");
+		String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
+		String resName = fileName.substring(0, fileName.lastIndexOf('.'));
+		String extension = resPath.substring(resPath.lastIndexOf('.'));
+		File dir = activity.getExternalCacheDir();
+		if (dir == null) {
+			Log.e("Asset", "Missing external cache dir");
+			return Uri.EMPTY;
+		}
+		String storage = dir.toString() + STORAGE_FOLDER;
+		int resId = getResId(resPath);
+		File file = new File(storage, resName + extension);
+		if (resId == 0) {
+			Log.e("Asset", "File not found: " + resPath);
+			return Uri.EMPTY;
+		}
+		new File(storage).mkdir();
+		try {
+			Resources res = activity.getResources();
+			FileOutputStream outStream = new FileOutputStream(file);
+			InputStream inputStream = res.openRawResource(resId);
+			copyFile(inputStream, outStream);
+			outStream.flush();
+			outStream.close();
+			return Uri.fromFile(file);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return Uri.EMPTY;
+	}
+	
+	/**
+	 *Get Uri for HTTP Content
+	 * @param path HTTP adress
+	 * @return Uri of the downloaded file
+	 */
+	private Uri getUriForHTTP(String path) {
+        try {
+			URL url = new URL(path);
+			String fileName = path.substring(path.lastIndexOf('/') + 1);
+			String resName = fileName.substring(0, fileName.lastIndexOf('.'));
+			String extension = path.substring(path.lastIndexOf('.'));
+			File dir = activity.getExternalCacheDir();
+			if (dir == null) {
+				Log.e("Asset", "Missing external cache dir");
+				return Uri.EMPTY;
+			}
+			String storage = dir.toString() + STORAGE_FOLDER;
+			File file = new File(storage, resName + extension);
+			new File(storage).mkdir();
+			
+			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();
+			FileOutputStream outStream = new FileOutputStream(file);		
+			copyFile(input, outStream);
+			outStream.flush();
+			outStream.close();
+			
+			return Uri.fromFile(file);
+		} catch (MalformedURLException e) {
+			Log.e("Asset", "Incorrect URL");			
+			e.printStackTrace();
+		} catch (FileNotFoundException e) {
+			Log.e("Asset", "Failed to create new File from HTTP Content");
+			e.printStackTrace();
+		} catch (IOException e) {
+			Log.e("Asset", "No Input can be created from http Stream");
+			e.printStackTrace();
+		}
+        return Uri.EMPTY;
+	}
+
+	/**
+	 * Writes an InputStream to an OutputStream
+	 * 
+	 * @param in
+	 *            The input stream
+	 * @param out
+	 *            The output stream
+	 */
+	private void copyFile(InputStream in, OutputStream out) throws IOException {
+		byte[] buffer = new byte[1024];
+		int read;
+		while ((read = in.read(buffer)) != -1) {
+			out.write(buffer, 0, read);
+		}
+	}
+
+	/**
+	 * @return The resource ID for the given resource.
+	 */
+	private int getResId(String resPath) {
+		Resources res = activity.getResources();
+		int resId;
+		String pkgName = getPackageName();
+		String dirName = "drawable";
+		String fileName = resPath;
+		if (resPath.contains("/")) {
+			dirName = resPath.substring(0, resPath.lastIndexOf('/'));
+			fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
+		}
+		String resName = fileName.substring(0, fileName.lastIndexOf('.'));
+		resId = res.getIdentifier(resName, dirName, pkgName);
+		if (resId == 0) {
+			resId = res.getIdentifier(resName, "drawable", pkgName);
+		}
+		return resId;
+	}
+	
+	/**
+	 * The name for the package.
+	 * 
+	 * @return The package name
+	 */
+	private String getPackageName() {
+		return activity.getPackageName();
+	}
+
+}

+ 440 - 0
src/android/notification/Manager.java

@@ -0,0 +1,440 @@
+package de.appplant.cordova.plugin.notification;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Build;
+
+public class Manager {	
+    //---------------Global Parameter------------------------------------------------------------
+	private Context context;
+	private final String PLUGIN_NAME;
+	
+    //---------------Constructor-----------------------------------------------------------------
+	/**
+	 * Constructor of NotificationWrapper-Class
+	 */
+	public Manager(Context context,String PluginName){
+		this.context = context;
+		this.PLUGIN_NAME = PluginName;
+	}
+	
+    //---------------Public Functions------------------------------------------------------------
+	/**
+     * Checks if a notification with an ID is scheduled.
+     *
+     * @param id
+     *          The notification ID to be check.
+     * @return true if the notification is scheduled
+     */
+    public boolean isScheduled (String id) {
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        boolean isScheduled        = alarms.containsKey(id);
+        boolean isNotTriggered	   = false;
+        
+        if (isScheduled) {
+        	JSONObject arguments;
+			try {
+				arguments = new JSONObject(alarms.get(id).toString());
+	        	Options options      = new Options(context).parse(arguments);
+	        	Date fireDate        = new Date(options.getDate());
+	        	isNotTriggered = new Date().before(fireDate);
+			} catch (JSONException e) {
+				isNotTriggered = false;
+				e.printStackTrace();
+			}
+        	
+        }
+        
+        return (isScheduled && isNotTriggered);
+    }
+    
+    /**
+     * Checks if a notification with an ID was triggered.
+     *
+     * @param id
+     *          The notification ID to be check.
+     * @return true if the notification is triggered
+     */
+    public boolean isTriggered (String id) {
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        boolean isScheduled        = alarms.containsKey(id);
+        boolean isTriggered        = isScheduled;
+
+        if (isScheduled) {
+        	JSONObject arguments;
+			try {
+				arguments = new JSONObject(alarms.get(id).toString());
+	        	Options options      = new Options(context).parse(arguments);
+	        	Date fireDate        = new Date(options.getInitialDate());
+	        	isTriggered = new Date().after(fireDate);
+			} catch (JSONException e) {
+				isTriggered = false;
+				e.printStackTrace();
+			}
+        	
+        }
+        return isTriggered;
+    }
+    /**
+     * Checks whether a notification with an ID exist.
+     *
+     * @param id
+     *          The notification ID to check.
+     * @return true if the notification exist
+     */
+    public boolean exist(String id){
+    	boolean exist;
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        exist = alarms.containsKey(id);
+    	return exist;
+    }
+
+    /**
+     * Retrieves a list with all currently pending notification Ids.
+     *
+     * @return JSONArray with all Id-Strings
+     */
+    public JSONArray getScheduledIds () {
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray scheduledIds     = new JSONArray();
+        
+        for (String id : alarmIds) {
+        	boolean isScheduled;
+        	JSONObject arguments;
+ 			try {
+ 				arguments = new JSONObject(alarms.get(id).toString());
+ 	        	Options options      = new Options(context).parse(arguments);
+ 	        	Date fireDate        = new Date(options.getDate());
+ 	        	isScheduled = new Date().before(fireDate);
+ 			} catch (JSONException e) {
+ 				isScheduled = false;
+ 				e.printStackTrace();
+ 			}
+ 			if (isScheduled){
+ 				scheduledIds.put(id);
+ 			}
+        }
+
+        
+        
+        return scheduledIds;
+    }
+
+
+
+    /**
+     * Retrieves a list with all currently triggered notification Ids.
+     *
+     * @return JSONArray with all Id-Strings
+     */
+    public JSONArray getTriggeredIds () {
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray triggeredIds     = new JSONArray();
+        Date now                   = new Date();
+
+        for (String id : alarmIds) {
+        	boolean isTriggered;
+        	JSONObject arguments;
+        	try{
+        		arguments = new JSONObject(alarms.get(id).toString());
+        		Options options      = new Options(context).parse(arguments);
+        		Date fireDate        = new Date(options.getInitialDate());
+        		isTriggered  = now.after(fireDate);
+            } catch(ClassCastException cce) {
+            	cce.printStackTrace();
+            	isTriggered = false;
+            } catch(JSONException jse) {
+        		jse.printStackTrace();
+            	isTriggered = false;
+            }
+
+            if (isTriggered == true) {
+                triggeredIds.put(id);
+            }
+        }
+
+        return triggeredIds;
+    }
+    
+    /**
+     * Retrieves a list with all currently triggered or scheduled notification-Ids.
+     * @return JSONArray with all Id-Strings
+     */
+    public JSONArray getAllIds (){
+        JSONArray allIds     = new JSONArray();
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        for (String id : alarmIds) {
+        	allIds.put(id);
+        }
+        return allIds;
+    }
+    
+    /**
+     * Retrieves a list with all currently pending notification JSONObject.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getAll(){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray all     = new JSONArray();
+
+        for (String id : alarmIds) {
+        	JSONObject arguments;
+        	try{
+        		arguments = new JSONObject(alarms.get(id).toString());
+        		all.put(arguments);
+        	} catch(JSONException jse) {
+        		jse.printStackTrace();
+            }
+        }
+        return all;
+    }
+    /**
+     * Retrieves a list with all currently scheduled notification-JSONObjects.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getScheduled(){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray scheduled     = new JSONArray();
+        
+        for (String id : alarmIds) {
+        	boolean isScheduled;
+        	JSONObject arguments = null;
+ 			try {
+ 				arguments = new JSONObject(alarms.get(id).toString());
+ 	        	Options options      = new Options(context).parse(arguments);
+ 	        	Date fireDate        = new Date(options.getDate());
+ 	        	isScheduled = new Date().before(fireDate);
+ 			} catch (JSONException e) {
+ 				isScheduled = false;
+ 				e.printStackTrace();
+ 			}
+ 			if (isScheduled){
+ 				scheduled.put(arguments);
+ 			}
+        }
+
+        
+        
+        return scheduled;
+    	
+    }
+    
+    /**
+     * Retrieves a list with all currently triggered notification-JSONObjects.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getTriggered(){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray triggered     = new JSONArray();
+        Date now                   = new Date();
+
+        for (String id : alarmIds) {
+        	boolean isTriggered;
+        	JSONObject arguments = null;
+        	try{
+        		arguments = new JSONObject(alarms.get(id).toString());
+        		Options options      = new Options(context).parse(arguments);
+        		Date fireDate        = new Date(options.getInitialDate());
+        		isTriggered  = now.after(fireDate);
+            } catch(ClassCastException cce) {
+            	cce.printStackTrace();
+            	isTriggered = false;
+            } catch(JSONException jse) {
+        		jse.printStackTrace();
+            	isTriggered = false;
+            }
+
+            if (isTriggered == true) {
+                triggered.put(arguments);
+            }
+        }
+
+        return triggered;
+    }
+    
+    
+    /**
+     * Retrieves a list with all currently pending notification JSONObject.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getAll(JSONArray ids){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray all     = new JSONArray();
+        for (String id : alarmIds) {
+        	for(int i=0;i<ids.length();i++){
+        		if(ids.optString(i).equals(id)){
+		        	JSONObject arguments;
+		        	try{
+		        		arguments = new JSONObject(alarms.get(id).toString());
+		        		all.put(arguments);
+		        	} catch(JSONException jse) {
+		        		jse.printStackTrace();
+		            }
+        		}
+        	}
+        }
+        return all;
+    }
+    /**
+     * Retrieves a list with all currently scheduled notification-JSONObjects.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getScheduled(JSONArray ids){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray scheduled     = new JSONArray();
+        boolean isScheduled;
+        
+        for (String id : alarmIds) {
+        	for(int i=0;i<ids.length();i++){
+        		if(ids.optString(i).equals(id)){
+		        	JSONObject arguments = null;
+		 			try {
+		 				arguments = new JSONObject(alarms.get(id).toString());
+		 	        	Options options      = new Options(context).parse(arguments);
+		 	        	Date fireDate        = new Date(options.getDate());
+		 	        	isScheduled = new Date().before(fireDate);
+		 			} catch (JSONException e) {
+		 				isScheduled = false;
+		 				e.printStackTrace();
+		 			}
+		 			if (isScheduled){
+		 				scheduled.put(arguments);
+		 			}
+        		}
+        	}
+        }
+
+        
+        
+        return scheduled;
+    	
+    }
+    
+    /**
+     * Retrieves a list with all currently triggered notification-JSONObjects.
+     *
+     * @return JSONArray with all notification-JSONObjects
+     */
+    public JSONArray getTriggered(JSONArray ids){
+        SharedPreferences settings = getSharedPreferences();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+        JSONArray triggered     = new JSONArray();
+        Date now                   = new Date();
+
+        for (String id : alarmIds) {
+        	for(int i=0;i<ids.length();i++){
+        		if(ids.optString(i).equals(id)){
+		        	boolean isTriggered;
+		        	JSONObject arguments = null;
+		        	try{
+		        		arguments = new JSONObject(alarms.get(id).toString());
+		        		Options options      = new Options(context).parse(arguments);
+		        		Date fireDate        = new Date(options.getInitialDate());
+		        		isTriggered  = now.after(fireDate);
+		            } catch(ClassCastException cce) {
+		            	cce.printStackTrace();
+		            	isTriggered = false;
+		            } catch(JSONException jse) {
+		        		jse.printStackTrace();
+		            	isTriggered = false;
+		            }
+		
+		            if (isTriggered == true) {
+		                triggered.put(arguments);
+		            }
+        		}
+        	}
+        }
+
+        return triggered;
+    }
+    
+    
+    
+    //---------------Manage Shared Preferences---------------------------------------------------
+    
+    /**
+     * The Local storage for the application.
+     */
+    private SharedPreferences getSharedPreferences () {
+        return context.getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
+    }
+    
+    /**
+     * Persist the information of this alarm to the Android Shared Preferences.
+     * This will allow the application to restore the alarm upon device reboot.
+     * Also this is used by the cancelAll method.
+     *
+     * @param alarmId
+     *            The Id of the notification that must be persisted.
+     * @param args
+     *            The assumption is that parse has been called already.
+     */
+    public void persist (String alarmId, JSONObject args) {
+        Editor editor = getSharedPreferences().edit();
+
+        if (alarmId != null) {
+            editor.putString(alarmId, args.toString());
+            if (Build.VERSION.SDK_INT<9) {
+                editor.commit();
+            } else {
+                editor.apply();
+            }
+        }
+    }
+    
+    /**
+     * Remove a specific alarm from the Android shared Preferences.
+     *
+     * @param alarmId
+     *            The Id of the notification that must be removed.
+     */
+    public void unpersist (String alarmId) {
+        Editor editor = getSharedPreferences().edit();
+
+        if (alarmId != null) {
+            editor.remove(alarmId);
+            if (Build.VERSION.SDK_INT<9) {
+                editor.commit();
+            } else {
+                editor.apply();
+            }
+        }
+    }
+
+
+}

+ 153 - 0
src/android/notification/NotificationBuilder.java

@@ -0,0 +1,153 @@
+/*
+    Copyright 2013-2014 appPlant UG
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+package de.appplant.cordova.plugin.notification;
+
+import java.util.Random;
+
+import android.annotation.SuppressLint;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationCompat.Builder;
+import android.widget.Toast;
+
+public class NotificationBuilder {
+	private Options options;
+	private Context context;
+	private Builder notification;
+	private final String OPTIONS;
+	private Class<?> deleteIntentReceiver;
+	private Class<?> receiverActivity;
+	
+	/**
+	 * Constructor of NotificationBuilder
+	 * @param options
+	 * @param context
+	 * @param OPTIONS
+	 * @param deleteIntentReceiver
+	 * @param receiverActivity
+	 */
+	public NotificationBuilder(Options options,Context context, String OPTIONS,	
+			Class<?> deleteIntentReceiver, Class<?> receiverActivity){
+		this.options = options;
+		this.context = context;
+		this.OPTIONS = OPTIONS;
+		this.deleteIntentReceiver = deleteIntentReceiver;
+		this.receiverActivity = receiverActivity;
+		}
+	
+    /**
+     * Creates the notification.
+     */
+    @SuppressLint("NewApi")
+    public void buildNotification () {
+        Uri sound = options.getSound();
+        
+        //DeleteIntent is called when the user clears a notification manually
+        Intent deleteIntent = new Intent(context, deleteIntentReceiver)
+        	.setAction("" + options.getId())
+        	.putExtra(OPTIONS, options.getJSONObject().toString());
+        PendingIntent dpi = PendingIntent.getBroadcast(context, 0, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+        
+        notification = new NotificationCompat.Builder(context)
+            .setDefaults(0) // Do not inherit any defaults
+            .setContentTitle(options.getTitle())
+            .setContentText(options.getMessage())
+            .setNumber(options.getBadge())
+            .setTicker(options.getMessage())
+            .setSmallIcon(options.getSmallIcon())
+            .setLargeIcon(options.getIcon())
+            .setAutoCancel(options.getAutoCancel())
+            .setOngoing(options.getOngoing())
+            .setLights(options.getColor(), 500, 500)
+            .setDeleteIntent(dpi);
+
+        if (sound != null) {
+            notification.setSound(sound);
+        }
+
+        if (Build.VERSION.SDK_INT > 16) {
+            notification.setStyle(new NotificationCompat.BigTextStyle()
+                .bigText(options.getMessage()));
+        }
+
+        setClickEvent(notification);
+    }
+
+    /**
+     * Adds an onclick handler to the notification
+     */
+    private Builder setClickEvent (Builder notification) {
+        Intent intent = new Intent(context, receiverActivity)
+            .putExtra(OPTIONS, options.getJSONObject().toString())
+            .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
+
+        int requestCode = new Random().nextInt();
+
+        PendingIntent contentIntent = PendingIntent.getActivity(context, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+        return notification.setContentIntent(contentIntent);
+    }
+
+    /**
+     * Shows the notification
+     */
+    @SuppressWarnings("deprecation")
+    public void showNotification () {
+        NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        int id                  = 0;
+
+        try {
+            id = Integer.parseInt(options.getId());
+        } catch (Exception e) {}
+
+        if (Build.VERSION.SDK_INT<16) {
+            // build notification for HoneyComb to ICS
+            mgr.notify(id, notification.getNotification());
+        } else if (Build.VERSION.SDK_INT>15) {
+            // Notification for Jellybean and above
+            mgr.notify(id, notification.build());
+        }
+    }
+    
+    /**
+     * Show a notification as a Toast when App is runing in foreground
+     * @param title Title of the notification
+     * @param notification Notification to show
+     */
+    public void showNotificationToast(){
+    	String title = options.getTitle();
+    	String message = options.getMessage();
+       	int duration = Toast.LENGTH_LONG;
+       	if(title.equals("")){
+       		title = "Notification";
+       	}
+       	String text = title + " \n " + message;
+       	
+    	Toast notificationToast = Toast.makeText(context, text, duration);
+    	notificationToast.show();
+   }
+	
+}

+ 324 - 0
src/android/notification/NotificationWrapper.java

@@ -0,0 +1,324 @@
+/*
+    Copyright 2013-2014 appPlant UG
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+package de.appplant.cordova.plugin.notification;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.AlarmManager;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Build;
+
+/**
+ * Wrapper class to schedule, cancel, clear, and update notifications.
+ *
+ */
+public class NotificationWrapper {
+    //---------------Global Parameter------------------------------------------------------------
+	private Context context;
+	private Class<?> receiver;
+	private final String PLUGIN_NAME;
+	private final String OPTIONS;
+	
+    //---------------Constructor-----------------------------------------------------------------
+	/**
+	 * Constructor of NotificationWrapper-Class
+	 */
+	public NotificationWrapper(Context context, Class<?> receiver,String PluginName, String OPTIONS){
+		this.context = context;
+		this.receiver = receiver;
+		this.PLUGIN_NAME = PluginName;
+		this.OPTIONS = OPTIONS;
+	}
+	
+	
+	//---------------public functions------------------------------------------------------------
+	/**
+	 * Schedule new notification
+	 */
+	public void schedule(Options options){
+        long triggerTime = options.getDate();
+
+        persist(options.getId(), options.getJSONObject());
+        
+        //Intent is called when the Notification gets fired
+        Intent intent = new Intent(context, receiver)
+            .setAction("" + options.getId())
+            .putExtra(OPTIONS, options.getJSONObject().toString());
+
+        AlarmManager am  = getAlarmManager();
+        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+        am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
+	}
+
+	/**
+	 * Cancel existing notification
+	 */
+	public void cancel(String notificationId){
+		/*
+         * Create an intent that looks similar, to the one that was registered
+         * using add. Making sure the notification id in the action is the same.
+         * Now we can search for such an intent using the 'getService' method
+         * and cancel it.
+         */
+        Intent intent = new Intent(context, receiver)
+            .setAction("" + notificationId);
+
+        PendingIntent pi       = PendingIntent.getBroadcast(context, 0, intent, 0);
+        AlarmManager am        = getAlarmManager();
+        NotificationManager nc = getNotificationManager();
+
+        am.cancel(pi);
+
+        try {
+            nc.cancel(Integer.parseInt(notificationId));
+        } catch (Exception e) {}
+        unpersist(notificationId);
+	}
+	
+    /**
+     * Cancel all notifications that were created by this plugin.
+     *
+     * Android can only unregister a specific alarm. There is no such thing
+     * as cancelAll. Therefore we rely on the Shared Preferences which holds
+     * all our alarms to loop through these alarms and unregister them one
+     * by one.
+     */
+    public void cancelAll() {
+        SharedPreferences settings = getSharedPreferences();
+        NotificationManager nc     = getNotificationManager();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+
+        for (String alarmId : alarmIds) {
+            cancel(alarmId);
+        }
+
+        nc.cancelAll();
+    }
+	
+    /** 
+     * Update an existing notification 
+     * 
+     * @param updates JSONObject with update-content
+     */
+	public void update(JSONObject updates){
+		String id = updates.optString("id", "0");
+    	
+    	// update shared preferences
+    	SharedPreferences settings = getSharedPreferences();
+    	Map<String, ?> alarms      = settings.getAll();
+    	JSONObject arguments;
+		try {
+			arguments = new JSONObject(alarms.get(id).toString());
+		} catch (JSONException e) {
+			e.printStackTrace();
+			return;
+		}
+		arguments = updateArguments(arguments, updates);
+		    	
+    	// cancel existing alarm
+        Intent intent = new Intent(context, receiver)
+        	.setAction("" + id);
+        PendingIntent pi       = PendingIntent.getBroadcast(context, 0, intent, 0);
+        AlarmManager am        = getAlarmManager();
+        am.cancel(pi);
+        
+        //add new alarm
+        Options options      = new Options(context).parse(arguments);
+        schedule(options);		
+	}
+	
+    /**
+     * Clear a specific notification without canceling repeating alarms
+     * 
+     * @param notificationID
+     *            The original ID of the notification that was used when it was
+     *            registered using add()
+     */
+    public void clear (String notificationId){
+    	SharedPreferences settings = getSharedPreferences();
+    	Map<String, ?> alarms      = settings.getAll();
+        NotificationManager nc = getNotificationManager();
+
+        try {
+            nc.cancel(Integer.parseInt(notificationId));
+        } catch (Exception e) {}
+        
+        JSONObject arguments;
+		try {
+			arguments = new JSONObject(alarms.get(notificationId).toString());
+			Options options      = new Options(context).parse(arguments);
+			Date now = new Date();
+			if ((options.getInterval()!=0)){
+				persist(notificationId, setInitDate(arguments));
+			}
+			else if((new Date(options.getDate()).before(now))){
+				unpersist(notificationId);
+			}
+		} catch (JSONException e) {
+			e.printStackTrace();
+			return;
+		}
+    }
+    
+    /**
+     * Clear all notifications without canceling repeating alarms
+     */
+    public void clearAll (){
+        SharedPreferences settings = getSharedPreferences();
+        NotificationManager nc     = getNotificationManager();
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+
+        for (String alarmId : alarmIds) {
+            clear(alarmId);
+        }
+
+        nc.cancelAll();
+    }
+	
+    //---------------Manage Shared Preferences---------------------------------------------------
+    
+    /**
+     * The Local storage for the application.
+     */
+    private SharedPreferences getSharedPreferences () {
+        return context.getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
+    }
+    
+    /**
+     * Persist the information of this alarm to the Android Shared Preferences.
+     * This will allow the application to restore the alarm upon device reboot.
+     * Also this is used by the cancelAll method.
+     *
+     * @param alarmId
+     *            The Id of the notification that must be persisted.
+     * @param args
+     *            The assumption is that parse has been called already.
+     */
+    public void persist (String alarmId, JSONObject args) {
+        Editor editor = getSharedPreferences().edit();
+
+        if (alarmId != null) {
+            editor.putString(alarmId, args.toString());
+            if (Build.VERSION.SDK_INT<9) {
+                editor.commit();
+            } else {
+                editor.apply();
+            }
+        }
+    }
+    
+    /**
+     * Remove a specific alarm from the Android shared Preferences.
+     *
+     * @param alarmId
+     *            The Id of the notification that must be removed.
+     */
+    public void unpersist (String alarmId) {
+        Editor editor = getSharedPreferences().edit();
+
+        if (alarmId != null) {
+            editor.remove(alarmId);
+            if (Build.VERSION.SDK_INT<9) {
+                editor.commit();
+            } else {
+                editor.apply();
+            }
+        }
+    }
+    
+    //---------------private functions-----------------------------------------------------------
+    
+    /**
+     * The alarm manager for the application.
+     */
+    private AlarmManager getAlarmManager () {
+        return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+    }
+    
+    /**
+     * The notification manager for the application.
+     */
+    private NotificationManager getNotificationManager () {
+        return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+    }
+    
+    /**
+     * Update the Arguments Input with content from updates-input
+     * 
+     * @param arguments The notifications optionArray
+     * @param updates	The content you like to change 
+     * 
+     * @return The updated value
+     */
+    private JSONObject updateArguments(JSONObject arguments,JSONObject updates){
+    	try	{
+    		if(!updates.isNull("message")){
+    			arguments.put("message", updates.get("message"));
+    		}
+    		if(!updates.isNull("title")){
+    			arguments.put("title", updates.get("title"));
+    		}
+    		if(!updates.isNull("badge")){
+    			arguments.put("badge", updates.get("badge"));
+    		}
+    		if(!updates.isNull("sound")){
+    			arguments.put("sound", updates.get("sound"));
+    		}
+    		if(!updates.isNull("icon")){
+    			arguments.put("icon", updates.get("icon"));
+    		}
+    	} catch (JSONException jse){
+    		jse.printStackTrace();
+    	}
+    	
+    	return arguments;
+    }
+    
+    /**
+     * Function to set the value of "initialDate" in the JSONArray
+     * @param args The given JSONArray
+     * @return A new JSONArray with the parameter "initialDate" set.
+     */
+    private JSONObject setInitDate(JSONObject arguments){
+    	long initialDate = arguments.optLong("date", 0) * 1000;
+    	try {
+    		arguments.put("initialDate", initialDate);
+		} catch (JSONException e) {
+			e.printStackTrace();
+		}
+    	return arguments;
+    }
+
+}

+ 45 - 231
src/android/Options.java → src/android/notification/Options.java

@@ -19,51 +19,40 @@
     under the License.
 */
 
-package de.appplant.cordova.plugin.localnotification;
+package de.appplant.cordova.plugin.notification;
 
-import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
 import java.util.Calendar;
 import java.util.Date;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import android.app.Activity;
 import android.app.AlarmManager;
 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.net.Uri;
-import android.os.StrictMode;
-import android.os.StrictMode.ThreadPolicy;
-import android.util.Log;
 
 /**
  * Class that helps to store the options that can be specified per alarm.
  */
 public class Options {
-	static protected final String STORAGE_FOLDER = "/localnotification";
     private JSONObject options = new JSONObject();
     private String packageName = null;
     private long interval      = 0;
+    private Context context;
 
-    Options (Activity activity) {
-        packageName = activity.getPackageName();
-    }
 
-    Options (Context context) {
-        packageName = context.getPackageName();
-    }
 
+    public Options(Context context){
+    	this.context= context;
+    	this.packageName = context.getPackageName();
+    }
+    
+    
     /**
      * Parses the given properties
      */
@@ -156,18 +145,13 @@ public class Options {
      * Returns the path of the notification's sound file
      */
     public Uri getSound () {
-        String sound = options.optString("sound", null);
-
-        if (sound != null) {
-            try {
-                int soundId = (Integer) RingtoneManager.class.getDeclaredField(sound).get(Integer.class);
-
-                return RingtoneManager.getDefaultUri(soundId);
-            } catch (Exception e) {
-            	return getURIfromPath(sound);
-            }
+        Uri soundUri = null;
+        try{
+        	soundUri = Uri.parse(options.optString("soundUri"));
+        	return soundUri;
+        } catch (Exception e){
+        	e.printStackTrace();
         }
-
         return null;
     }
 
@@ -177,11 +161,15 @@ public class Options {
     public Bitmap getIcon () {
         String icon = options.optString("icon", "icon");
         Bitmap bmp = null;
-
-        if (icon.startsWith("http")) {
-            bmp = getIconFromURL(icon);
-        } else if (icon.startsWith("file://") || (icon.startsWith("res"))) {
-            bmp = getIconFromURI(icon);
+        Uri iconUri = null;
+        try{
+        	iconUri = Uri.parse(options.optString("iconUri"));
+        } catch (Exception e){
+        	e.printStackTrace();
+        }
+        
+        if (iconUri != null) {
+            bmp = getIconFromUri(iconUri);
         }
 
         if (bmp == null) {
@@ -265,6 +253,14 @@ public class Options {
 
         return aRGB;
     }
+   
+	/**
+	 * Shows the behavior of notifications when the application is in foreground 
+	 * 
+	 */
+	public boolean getForegroundMode(){
+		return options.optBoolean("foregroundMode",false);	
+	}
 
     /**
      * Returns numerical icon Value
@@ -293,7 +289,7 @@ public class Options {
      *      The corresponding bitmap
      */
     private Bitmap getIconFromRes (String icon) {
-        Resources res = LocalNotification.context.getResources();
+        Resources res = context.getResources();
         int iconId = 0;
 
         iconId = getIconValue(packageName, icon);
@@ -311,41 +307,7 @@ public class Options {
         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.
@@ -355,12 +317,11 @@ public class Options {
      * @return
      *      The corresponding bitmap
      */
-    private Bitmap getIconFromURI (String src) {
+    private Bitmap getIconFromUri (Uri uri) {
         Bitmap bmp = null;
-        Uri uri = getURIfromPath(src);
 
         try {           
-            InputStream input = LocalNotification.activity.getContentResolver().openInputStream(uri);
+            InputStream input = context.getContentResolver().openInputStream(uri);
             bmp = BitmapFactory.decodeStream(input);
         } catch (IOException e) {
             e.printStackTrace();
@@ -369,165 +330,18 @@ public class Options {
         return bmp;
     }
     
-	/**
-	 * The URI for a path.
-	 * 
-	 * @param path The given path
-	 * 
-	 * @return The URI pointing to the given path
-	 */
-    private Uri getURIfromPath(String path){
-		if (path.startsWith("res:")) {
-			return getUriForResourcePath(path);
-		} else if (path.startsWith("file:///")) {
-			return getUriForAbsolutePath(path);
-		} else if (path.startsWith("file://")) {
-			return getUriForAssetPath(path);
-		}
-		return Uri.parse(path);
-	}
-    
-	/**
-	 * The URI for a file.
-	 * 
-	 * @param path
-	 *            The given absolute path
-	 * 
-	 * @return The URI pointing to the given path
-	 */
-	private Uri getUriForAbsolutePath(String path) {
-		String absPath = path.replaceFirst("file://", "");
-		File file = new File(absPath);
-		if (!file.exists()) {
-			Log.e("LocalNotifocation", "File not found: " + file.getAbsolutePath());
-		}
-		return Uri.fromFile(file);
-	}
-
-	/**
-	 * The URI for an asset.
-	 * 
-	 * @param path
-	 *            The given asset path
-	 * 
-	 * @return The URI pointing to the given path
-	 */
-	private Uri getUriForAssetPath(String path) {
-		String resPath = path.replaceFirst("file:/", "www");
-		String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
-		File dir = 		LocalNotification.activity.getExternalCacheDir();
-		if (dir == null) {
-			Log.e("LocalNotifocation", "Missing external cache dir");
-			return Uri.EMPTY;
-		}
-		String storage = dir.toString() + STORAGE_FOLDER;
-		File file = new File(storage, fileName);
-		new File(storage).mkdir();
-		try {
-			AssetManager assets = LocalNotification.activity.getAssets();
-			FileOutputStream outStream = new FileOutputStream(file);
-			InputStream inputStream = assets.open(resPath);
-			copyFile(inputStream, outStream);
-			outStream.flush();
-			outStream.close();
-		} catch (Exception e) {
-			Log.e("LocalNotifocation", "File not found: assets/" + resPath);
-			e.printStackTrace();
-		}
-		return Uri.fromFile(file);
-	}
-
-	/**
-	 * The URI for a resource.
-	 * 
-	 * @param path
-	 *            The given relative path
-	 * 
-	 * @return The URI pointing to the given path
-	 */
-	private Uri getUriForResourcePath(String path) {
-		String resPath = path.replaceFirst("res://", "");
-		String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
-		String resName = fileName.substring(0, fileName.lastIndexOf('.'));
-		String extension = resPath.substring(resPath.lastIndexOf('.'));
-		File dir = LocalNotification.activity.getExternalCacheDir();
-		if (dir == null) {
-			Log.e("LocalNotifocation", "Missing external cache dir");
-			return Uri.EMPTY;
-		}
-		String storage = dir.toString() + STORAGE_FOLDER;
-		int resId = getResId(resPath);
-		File file = new File(storage, resName + extension);
-		if (resId == 0) {
-			Log.e("LocalNotifocation", "File not found: " + resPath);
-		}
-		new File(storage).mkdir();
-		try {
-			Resources res = LocalNotification.activity.getResources();
-			FileOutputStream outStream = new FileOutputStream(file);
-			InputStream inputStream = res.openRawResource(resId);
-			copyFile(inputStream, outStream);
-			outStream.flush();
-			outStream.close();
-		} catch (Exception e) {
+    /**
+     * Function to set the value of "initialDate" in the JSONArray
+     * @param args The given JSONArray
+     * @return A new JSONArray with the parameter "initialDate" set.
+     */
+    public void setInitDate(){
+    	long initialDate = options.optLong("date", 0) * 1000;
+    	try {
+    		options.put("initialDate", initialDate);
+		} catch (JSONException e) {
 			e.printStackTrace();
 		}
-		return Uri.fromFile(file);
-	}
-
-	/**
-	 * Writes an InputStream to an OutputStream
-	 * 
-	 * @param in
-	 *            The input stream
-	 * @param out
-	 *            The output stream
-	 */
-	private void copyFile(InputStream in, OutputStream out) throws IOException {
-		byte[] buffer = new byte[1024];
-		int read;
-		while ((read = in.read(buffer)) != -1) {
-			out.write(buffer, 0, read);
-		}
-	}
-
-	/**
-	 * @return The resource ID for the given resource.
-	 */
-	private int getResId(String resPath) {
-		Resources res = LocalNotification.activity.getResources();
-		int resId;
-		String pkgName = getPackageName();
-		String dirName = "drawable";
-		String fileName = resPath;
-		if (resPath.contains("/")) {
-			dirName = resPath.substring(0, resPath.lastIndexOf('/'));
-			fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
-		}
-		String resName = fileName.substring(0, fileName.lastIndexOf('.'));
-		resId = res.getIdentifier(resName, dirName, pkgName);
-		if (resId == 0) {
-			resId = res.getIdentifier(resName, "drawable", pkgName);
-		}
-		return resId;
-	}
-	
-	/**
-	 * The name for the package.
-	 * 
-	 * @return The package name
-	 */
-	private String getPackageName() {
-		return LocalNotification.activity.getPackageName();
-	}
-	
-	/**
-	 * Shows the behavior of notifications when the application is in foreground
-	 * 
-	 * 
-	 */
-	public boolean getForegroundMode(){
-		return options.optBoolean("foregroundMode",false);	
-	}
+    }
 	
 }

+ 7 - 5
www/local-notification.js

@@ -120,7 +120,7 @@ exports.add = function (props, callback, scope) {
             this.convertProperties(properties);
         }
 
-        if (device.platform != 'iOS') {
+        if (device.platform != 'iOS'&&device.platform != 'Android' ) {
             notifications = notifications[0];
         }
 
@@ -152,10 +152,12 @@ exports.update = function (options, callback, scope) {
  * @param {Object?} scope
  *      The scope for the callback function
  */
-exports.clear = function (id, callback, scope) {
-    var notId = (id || '0').toString();
+exports.clear = function (ids, callback, scope) {
+    ids = Array.isArray(ids) ? ids : [ids];
+	
+	ids = this.convertIds(ids);
 
-    this.exec('clear', notId, callback, scope);
+    this.exec('clear', ids, callback, scope);
 };
 
 /**
@@ -186,7 +188,7 @@ exports.cancel = function (ids, callback, scope) {
 
     ids = this.convertIds(ids);
 
-    if (device.platform != 'iOS') {
+    if (device.platform != 'iOS'&&device.platform != 'Android' ) {
         ids = ids[0];
     }