Jelajahi Sumber

Huge Android rework.

Sebastián Katzer 12 tahun lalu
induk
melakukan
0c0b1079f4

+ 6 - 5
plugin.xml

@@ -50,14 +50,14 @@
              * Android notification bar. The notification uses the default notification
              * sound and it vibrates the phone.
             -->
-            <receiver android:name="de.appplant.cordova.plugin.localnotification.LocalNotificationReceiver" />
+            <receiver android:name="de.appplant.cordova.plugin.localnotification.Receiver" />
 
             <!--
              * This class is triggered upon reboot of the device. It needs to re-register
              * the alarms with the AlarmManager since these alarms are lost in case of
              * reboot.
              -->
-            <receiver android:name="de.appplant.cordova.plugin.localnotification.LocalNotificationRestore" >
+            <receiver android:name="de.appplant.cordova.plugin.localnotification.Restore" >
                 <intent-filter>
                     <action android:name="android.intent.action.BOOT_COMPLETED" />
                 </intent-filter>
@@ -66,12 +66,13 @@
 
         <config-file target="AndroidManifest.xml" parent="/manifest">
             <uses-permission android:name="android.permission.GET_TASKS" />
+            <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
         </config-file>
 
-        <source-file src="src/android/LocalNotificationReceiver.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
-        <source-file src="src/android/LocalNotificationOptions.java" target-dir="src/de/appplant/cordova/plugin/localnotification" />
-        <source-file src="src/android/LocalNotificationRestore.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/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" />
     </platform>
 
     <!-- wp8 -->

+ 143 - 0
src/android/Helper.java

@@ -0,0 +1,143 @@
+/**
+ *  Cordova LocalNotification Plugin
+ *
+ *  Created by Sebastian Katzer (github.com/katzer).
+ *  Copyright 2013 Sebastian Katzer. All rights reserved.
+ *  LGPL v2.1 licensed
+ */
+
+package de.appplant.cordova.plugin.localnotification;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONArray;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+public class Helper {
+
+	private Context context;
+
+    public Helper(Context context) {
+    	this.context = context;
+    }
+
+    /**
+     * Set an alarm.
+     *
+     * @param options
+     *            The options that can be specified per alarm.
+     */
+    public void add (Options options) {
+        long triggerTime = options.getDate();
+        Intent intent    = new Intent(context, Receiver.class);
+
+        intent.setAction("" + options.getId());
+        intent.putExtra(Receiver.OPTIONS, options.getJSONObject().toString());
+
+        AlarmManager am  = getAlarmManager();
+        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+        if (options.getInterval() > 0) {
+            am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, options.getInterval(), pi);
+        } else {
+            am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
+        }
+    }
+
+    /**
+     * 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 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);
+        intent.setAction("" + notificationId);
+
+        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+        AlarmManager am  = getAlarmManager();
+
+        try {
+            am.cancel(pi);
+        } catch (Exception e) {}
+    }
+
+    /**
+     * 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 = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE);
+        Map<String, ?> alarms      = settings.getAll();
+        Set<String> alarmIds       = alarms.keySet();
+
+        for (String alarmId : alarmIds) {
+            cancel(alarmId);
+        }
+    }
+
+    /**
+     * 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 args
+     *            The assumption is that parse has been called already.
+     */
+    public void persist (String alarmId, JSONArray args) {
+        Editor editor = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
+
+        if (alarmId != null) {
+            editor.putString(alarmId, args.toString());
+            editor.commit();
+        }
+    }
+
+    /**
+     * 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 = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
+
+        if (alarmId != null) {
+            editor.remove(alarmId);
+            editor.commit();
+        }
+    }
+
+    /**
+     * Clear all alarms from the Android shared Preferences.
+     */
+    public void unpersistAll () {
+        Editor editor = context.getSharedPreferences(LocalNotification.PLUGIN_NAME, Context.MODE_PRIVATE).edit();
+
+        editor.clear();
+        editor.commit();
+    }
+
+    private AlarmManager getAlarmManager () {
+        return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+    }
+}

+ 29 - 83
src/android/LocalNotification.java

@@ -1,30 +1,19 @@
 /**
- *  LocalNotification.java
  *  Cordova LocalNotification Plugin
  *
- *  Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
+ *  Created by Sebastian Katzer (github.com/katzer).
  *  Copyright 2013 Sebastian Katzer. All rights reserved.
- *  GPL v2 licensed
+ *  LGPL v2.1 licensed
  */
 
 package de.appplant.cordova.plugin.localnotification;
 
-import java.util.Map;
-import java.util.Set;
-
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
-import android.content.Intent;
 import android.content.Context;
-import android.app.Activity;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
 
-import org.apache.cordova.CordovaInterface;
 import org.apache.cordova.CordovaPlugin;
 import org.apache.cordova.CallbackContext;
 import org.apache.cordova.CordovaWebView;
@@ -39,15 +28,24 @@ public class LocalNotification extends CordovaPlugin {
 
     public static final String PLUGIN_NAME = "LocalNotification";
 
-    public static CordovaInterface cordova = null;
     public static CordovaWebView webView   = null;
+    public static Context context          = null;
 
     @Override
     public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
         rememberCordovaVarsForStaticUse();
 
         if (action.equalsIgnoreCase("add")) {
-            addWithoutBlocking(args);
+            JSONObject arguments  = args.optJSONObject(0);
+            final Options options = new Options(context).parse(arguments);
+
+            persist(options.getId(), args);
+
+            cordova.getThreadPool().execute( new Runnable() {
+                public void run() {
+                    add(options);
+                }
+            });
 
             return true;
         }
@@ -72,40 +70,16 @@ public class LocalNotification extends CordovaPlugin {
         return false;
     }
 
-    private static void addWithoutBlocking (final JSONArray args) {
-        cordova.getThreadPool().execute(new Runnable() {
-            public void run() {
-                JSONObject arguments             = args.optJSONObject(0);
-                Activity activity                = cordova.getActivity();
-                LocalNotificationOptions options = new LocalNotificationOptions(activity).parse(arguments);
-
-                persist(options.getId(), args);
-                add(options);
-            }
-        });
-    }
-
     /**
-     * Set an alarm
+     * Set an alarm.
      *
      * @param options
      *            The options that can be specified per alarm.
      */
-    public static void add (LocalNotificationOptions options) {
-        long triggerTime = options.getDate();
-        Intent intent    = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
-
-        intent.setAction("" + options.getId());
-        intent.putExtra(LocalNotificationReceiver.OPTIONS, options.getJSONObject().toString());
-
-        AlarmManager am  = getAlarmManager();
-        PendingIntent pi = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+    public static void add (Options options) {
+        Helper helper = new Helper(context);
 
-        if (options.getInterval() > 0) {
-            am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, options.getInterval(), pi);
-        } else {
-            am.set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
-        }
+        helper.add(options);
     }
 
     /**
@@ -116,22 +90,9 @@ public class LocalNotification extends CordovaPlugin {
      *            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(cordova.getActivity(), LocalNotificationReceiver.class);
-
-        intent.setAction("" + notificationId);
-
-        PendingIntent pi = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-        AlarmManager am  = getAlarmManager();
-
-        try {
-            am.cancel(pi);
-        } catch (Exception e) {}
+        Helper helper = new Helper(context);
+
+        helper.cancel(notificationId);
     }
 
     /**
@@ -143,13 +104,9 @@ public class LocalNotification extends CordovaPlugin {
      * by one.
      */
     public static void cancelAll() {
-        SharedPreferences settings = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
-        Map<String, ?> alarms      = settings.getAll();
-        Set<String> alarmIds       = alarms.keySet();
+        Helper helper = new Helper(context);
 
-        for (String alarmId : alarmIds) {
-            cancel(alarmId);
-        }
+        helper.cancelAll();
     }
 
     /**
@@ -161,12 +118,9 @@ public class LocalNotification extends CordovaPlugin {
      *            The assumption is that parse has been called already.
      */
     public static void persist (String alarmId, JSONArray args) {
-        Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit();
+        Helper helper = new Helper(context);
 
-        if (alarmId != null) {
-            editor.putString(alarmId, args.toString());
-            editor.commit();
-        }
+        helper.persist(alarmId, args);
     }
 
     /**
@@ -176,33 +130,25 @@ public class LocalNotification extends CordovaPlugin {
      *            The Id of the notification that must be removed.
      */
     public static void unpersist (String alarmId) {
-        Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit();
+        Helper helper = new Helper(context);
 
-        if (alarmId != null) {
-            editor.remove(alarmId);
-            editor.commit();
-        }
+        helper.unpersist(alarmId);
     }
 
     /**
      * Clear all alarms from the Android shared Preferences.
      */
     public static void unpersistAll () {
-        Editor editor = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE).edit();
-
-        editor.clear();
-        editor.commit();
-    }
+        Helper helper = new Helper(context);
 
-    private static AlarmManager getAlarmManager () {
-        return (AlarmManager) cordova.getActivity().getSystemService(Context.ALARM_SERVICE);
+        helper.unpersistAll();
     }
 
     /**
      * Save required Cordova specific variables for later use.
      */
     private void rememberCordovaVarsForStaticUse () {
-        LocalNotification.cordova = super.cordova;
         LocalNotification.webView = super.webView;
+        LocalNotification.context = super.cordova.getActivity();
     }
 }

+ 6 - 10
src/android/LocalNotificationOptions.java → src/android/Options.java

@@ -1,10 +1,9 @@
 /**
- *  LocalNotificationOptions.java
  *  Cordova LocalNotification Plugin
  *
- *  Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
+ *  Created by Sebastian Katzer (github.com/katzer).
  *  Copyright 2013 Sebastian Katzer. All rights reserved.
- *  GPL v2 licensed
+ *  LGPL v2.1 licensed
  */
 
 package de.appplant.cordova.plugin.localnotification;
@@ -23,29 +22,26 @@ import android.net.Uri;
 /**
  * Class that helps to store the options that can be specified per alarm.
  */
-public class LocalNotificationOptions {
+public class Options {
 
-    /*
-     * Options that can be set when this plugin is invoked
-     */
     private JSONObject options = new JSONObject();
     private String id          = null;
     private String packageName = null;
     private long interval      = 0;
     private long date          = 0;
 
-    LocalNotificationOptions (Activity activity) {
+    Options (Activity activity) {
         packageName = activity.getPackageName();
     }
 
-    LocalNotificationOptions (Context context) {
+    Options (Context context) {
         packageName = context.getPackageName();
     }
 
     /**
      * Parst die übergebenen Eigenschaften.
      */
-    public LocalNotificationOptions parse (JSONObject options) {
+    public Options parse (JSONObject options) {
         String repeat = options.optString("repeat");
 
         this.options = options;

+ 22 - 20
src/android/LocalNotificationReceiver.java → src/android/Receiver.java

@@ -1,10 +1,9 @@
 /**
- *  LocalNotificationReceiver.java
  *  Cordova LocalNotification Plugin
  *
- *  Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
+ *  Created by Sebastian Katzer (github.com/katzer).
  *  Copyright 2013 Sebastian Katzer. All rights reserved.
- *  GPL v2 licensed
+ *  LGPL v2.1 licensed
  */
 
 package de.appplant.cordova.plugin.localnotification;
@@ -32,22 +31,22 @@ import android.os.Bundle;
  * Android notification bar. The notification uses the default notification
  * sound and it vibrates the phone.
  */
-public class LocalNotificationReceiver extends BroadcastReceiver {
+public class Receiver extends BroadcastReceiver {
 
     public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
 
     private Context context;
-    private LocalNotificationOptions options;
+    private Options options;
 
     @Override
     public void onReceive (Context context, Intent intent) {
-        LocalNotificationOptions options = null;
-        Bundle bundle                    = intent.getExtras();
+        Options options = null;
+        Bundle bundle   = intent.getExtras();
         JSONObject args;
 
         try {
             args    = new JSONObject(bundle.getString(OPTIONS));
-            options = new LocalNotificationOptions(context).parse(args);
+            options = new Options(context).parse(args);
         } catch (JSONException e) {}
 
         this.context = context;
@@ -62,8 +61,7 @@ public class LocalNotificationReceiver extends BroadcastReceiver {
         Builder notification = buildNotification();
 
         if (!isInBackground(context)) {
-            // exec foreground callback
-            invokeForegroundCallback(options);
+            invokeForegroundCallback();
         }
 
         showNotification(notification);
@@ -154,22 +152,26 @@ public class LocalNotificationReceiver extends BroadcastReceiver {
     /**
      * Ruft die `foreground` Callback Funktion auf.
      */
-    private void invokeForegroundCallback (LocalNotificationOptions options) {
-        String function = options.getForeground();
+    private void invokeForegroundCallback () {
+            String function = options.getForeground();
 
-        if (function != null) {
-            LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
-        }
+            // after reboot, LocalNotification.webView is always null
+            // may be call foreground callback later
+            if (function != null && LocalNotification.webView != null) {
+                    LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
+            }
     }
 
     /**
      * Ruft die `background` Callback Funktion auf.
      */
-    private void invokeBackgroundCallback (LocalNotificationOptions options) {
-        String function = options.getBackground();
+    private void invokeBackgroundCallback () {
+            String function = options.getBackground();
 
-        if (function != null) {
-            LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
-        }
+            // after reboot, LocalNotification.webView is always null
+            // may be call background callback later
+            if (function != null && LocalNotification.webView != null) {
+                    LocalNotification.webView.sendJavascript(function + "(" + options.getId() + ")");
+            }
     }
 }

+ 7 - 14
src/android/LocalNotificationRestore.java → src/android/Restore.java

@@ -1,18 +1,17 @@
 /**
- *  LocalNotificationRestore.java
  *  Cordova LocalNotification Plugin
  *
- *  Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
+ *  Created by Sebastian Katzer (github.com/katzer).
  *  Copyright 2013 Sebastian Katzer. All rights reserved.
- *  GPL v2 licensed
+ *  LGPL v2.1 licensed
  */
 
 package de.appplant.cordova.plugin.localnotification;
 
 import java.util.Set;
 
+import org.json.JSONArray;
 import org.json.JSONException;
-import org.json.JSONObject;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -24,16 +23,12 @@ import android.content.SharedPreferences;
  * the alarms with the AlarmManager since these alarms are lost in case of
  * reboot.
  */
-public class LocalNotificationRestore extends BroadcastReceiver {
+public class Restore extends BroadcastReceiver {
 
     @Override
     public void onReceive(Context context, Intent intent) {
         String pluginName = LocalNotification.PLUGIN_NAME;
 
-        if (LocalNotification.cordova == null) {
-            return;
-        }
-
         // Obtain alarm details form Shared Preferences
         SharedPreferences alarms = context.getSharedPreferences(pluginName, Context.MODE_PRIVATE);
         Set<String> alarmIds     = alarms.getAll().keySet();
@@ -43,14 +38,12 @@ public class LocalNotificationRestore extends BroadcastReceiver {
          * the Alarm Manager
          */
         for (String alarmId : alarmIds) {
-            LocalNotificationOptions options;
-            JSONObject args;
-
             try {
-                args    = new JSONObject(alarms.getString(alarmId, ""));
-                options = new LocalNotificationOptions(context).parse(args);
+                JSONArray args  = new JSONArray(alarms.getString(alarmId, ""));
+                Options options = new Options(context).parse(args.getJSONObject(0));
 
                 LocalNotification.add(options);
+
             } catch (JSONException e) {}
         }
     }