Browse Source

Halbwegs funktionsfähiger Android Support

Sebastián Katzer 12 years ago
parent
commit
331227c6a8

+ 0 - 87
src/android/AlarmReceiver.java

@@ -1,87 +0,0 @@
-package de.appplant.cordova.plugin;
-
-import java.util.Calendar;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * 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
- * Android notification bar. The notification uses the default notification
- * sound and it vibrates the phone.
- *
- * @author dvtoever
- */
-public class AlarmReceiver extends BroadcastReceiver {
-
-	public static final String TITLE = "ALARM_TITLE";
-	public static final String SUBTITLE = "ALARM_SUBTITLE";
-	public static final String TICKER_TEXT = "ALARM_TICKER";
-	public static final String NOTIFICATION_ID = "NOTIFICATION_ID";
-
-	/* Contains time in 24hour format 'HH:mm' e.g. '04:30' or '18:23' */
-	public static final String HOUR_OF_DAY = "HOUR_OF_DAY";
-	public static final String MINUTE = "MINUTES";
-
-	@Override
-	public void onReceive(Context context, Intent intent) {
-		Log.d("AlarmReceiver", "AlarmReceiver invoked!");
-
-		final Bundle bundle = intent.getExtras();
-		final Object systemService = context.getSystemService(Context.NOTIFICATION_SERVICE);
-
-		// Retrieve notification details from the intent
-		final String tickerText = bundle.getString(TICKER_TEXT);
-		final String notificationTitle = bundle.getString(TITLE);
-		final String notificationSubText = bundle.getString(SUBTITLE);
-		int notificationId = 0;
-
-		try {
-			notificationId = Integer.parseInt(bundle.getString(NOTIFICATION_ID));
-		} catch (Exception e) {
-			Log.d("AlarmReceiver", "Unable to process alarm with id: " + bundle.getString(NOTIFICATION_ID));
-		}
-
-		Calendar currentCal = Calendar.getInstance();
-		int alarmHour = bundle.getInt(HOUR_OF_DAY);
-		int alarmMin = bundle.getInt(MINUTE);
-		int currentHour = currentCal.get(Calendar.HOUR_OF_DAY);
-		int currentMin = currentCal.get(Calendar.MINUTE);
-
-		if (currentHour != alarmHour && currentMin != alarmMin) {
-			/*
-			 * If you set a repeating alarm at 11:00 in the morning and it
-			 * should trigger every morning at 08:00 o'clock, it will
-			 * immediately fire. E.g. Android tries to make up for the
-			 * 'forgotten' reminder for that day. Therefore we ignore the event
-			 * if Android tries to 'catch up'.
-			 */
-			Log.d(LocalNotification.PLUGIN_NAME, "AlarmReceiver, ignoring alarm since it is due");
-			return;
-		}
-
-		// Construct the notification and notificationManager objects
-		final NotificationManager notificationMgr = (NotificationManager) systemService;
-		final Notification notification = new Notification(R.drawable.ic_launcher, tickerText,
-				System.currentTimeMillis());
-		final PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
-		notification.defaults |= Notification.DEFAULT_SOUND;
-		notification.vibrate = new long[] { 0, 100, 200, 300 };
-		notification.setLatestEventInfo(context, notificationTitle, notificationSubText, contentIntent);
-
-		/*
-		 * If you want all reminders to stay in the notification bar, you should
-		 * generate a random ID. If you want do replace an existing
-		 * notification, make sure the ID below matches the ID that you store in
-		 * the alarm intent.
-		 */
-		notificationMgr.notify(notificationId, notification);
-	}
-}

+ 0 - 63
src/android/AlarmRestoreOnBoot.java

@@ -1,63 +0,0 @@
-package de.appplant.cordova.plugin;
-
-import java.util.Calendar;
-import java.util.Map;
-import java.util.Set;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-/**
- * 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.
- *
- * @author dvtoever
- */
-public class AlarmRestoreOnBoot extends BroadcastReceiver {
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-	final String pluginName = LocalNotification.PLUGIN_NAME;
-
-	// Obtain alarm details form Shared Preferences
-	final SharedPreferences alarmSettings = context.getSharedPreferences(pluginName, Context.MODE_PRIVATE);
-	final Map<String, ?> allAlarms = alarmSettings.getAll();
-	final Set<String> alarmIds = allAlarms.keySet();
-
-	/*
-	 * For each alarm, parse its alarm options and register is again with
-	 * the Alarm Manager
-	 */
-	for (String alarmId : alarmIds) {
-	    try {
-		final AlarmHelper alarm = new AlarmHelper(context);
-		final JSONArray alarmDetails = new JSONArray(alarmSettings.getString(alarmId, ""));
-		final AlarmOptions options = new AlarmOptions();
-
-		options.parseOptions(alarmDetails);
-
-		final boolean daily = options.isRepeatDaily();
-		final String title = options.getAlarmTitle();
-		final String subTitle = options.getAlarmSubTitle();
-		final String ticker = options.getAlarmTicker();
-		final String id = options.getNotificationId();
-		final Calendar cal = options.getCal();
-
-		alarm.addAlarm(daily, title, subTitle, ticker, id, cal);
-
-	    } catch (JSONException e) {
-		Log.d(pluginName,
-			"AlarmRestoreOnBoot: Error while restoring alarm details after reboot: " + e.toString());
-	    }
-
-	    Log.d(pluginName, "AlarmRestoreOnBoot: Successfully restored alarms upon reboot");
-	}
-    }
-}

+ 17 - 28
src/android/LocalNotification.java

@@ -9,7 +9,6 @@
 
 package de.appplant.cordova.plugin;
 
-import java.util.Calendar;
 import java.util.Map;
 import java.util.Set;
 
@@ -40,14 +39,14 @@ public class LocalNotification extends CordovaPlugin {
     @Override
     public boolean execute (String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
         JSONObject arguments             = args.getJSONObject(0);
-        LocalNotificationOptions options = new LocalNotificationOptions();
+        LocalNotificationOptions options = new LocalNotificationOptions(arguments);
 
-        options.parse(arguments);
-
-        String alarmId = options.getNotificationId();
+        String alarmId = options.getId();
 
         if (action.equalsIgnoreCase("add")) {
-            persist(alarmId, args);
+            if (alarmId != null)
+                persist(alarmId, args);
+
             add(options);
 
             return true;
@@ -58,10 +57,9 @@ public class LocalNotification extends CordovaPlugin {
             cancel(alarmId);
 
             return true;
-
         }
 
-        if (action.equalsIgnoreCase("cancelall")) {
+        if (action.equalsIgnoreCase("cancelAll")) {
             unpersistAll();
             cancelAll();
 
@@ -78,27 +76,18 @@ public class LocalNotification extends CordovaPlugin {
      * @param options
      *            The options that can be specified per alarm.
      */
-    public void add(LocalNotificationOptions options) {
-        Calendar calendar = options.getCalendar();
-        long triggerTime  = calendar.getTimeInMillis();
-        int hour          = calendar.get(Calendar.HOUR_OF_DAY);
-        int min           = calendar.get(Calendar.MINUTE);
-
-        Intent intent     = new Intent(cordova.getActivity(), AlarmReceiver.class);
-
-        intent.setAction("" + options.getNotificationId());
-        intent.putExtra(AlarmReceiver.TITLE, options.getTitle());
-        intent.putExtra(AlarmReceiver.SUBTITLE, options.getSubTitle());
-        intent.putExtra(AlarmReceiver.TICKER_TEXT, options.getTicker());
-        intent.putExtra(AlarmReceiver.NOTIFICATION_ID, options.getNotificationId());
-        intent.putExtra(AlarmReceiver.HOUR_OF_DAY, hour);
-        intent.putExtra(AlarmReceiver.MINUTE, min);
+    private 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());
 
-        PendingIntent sender = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
         /* Get the AlarmManager service */
         AlarmManager am      = getAlarmManager();
+        PendingIntent sender = PendingIntent.getBroadcast(cordova.getActivity(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
 
-        if (options.isRepeatDaily()) {
+        if (options.getInterval() > 0) {
             am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, AlarmManager.INTERVAL_DAY, sender);
         } else {
             am.set(AlarmManager.RTC_WAKEUP, triggerTime, sender);
@@ -112,14 +101,14 @@ public class LocalNotification extends CordovaPlugin {
      *            The original ID of the notification that was used when it was
      *            registered using add()
      */
-    public void cancel (String notificationId) {
+    private 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(), AlarmReceiver.class);
+        Intent intent = new Intent(cordova.getActivity(), LocalNotificationReceiver.class);
 
         intent.setAction("" + notificationId);
 
@@ -139,7 +128,7 @@ public class LocalNotification extends CordovaPlugin {
      * all our alarms to loop through these alarms and unregister them one
      * by one.
      */
-    public void cancelAll() {
+    private void cancelAll() {
         SharedPreferences settings = cordova.getActivity().getSharedPreferences(PLUGIN_NAME, Context.MODE_PRIVATE);
         Map<String, ?> alarms      = settings.getAll();
         Set<String> alarmIds       = alarms.keySet();

+ 37 - 46
src/android/LocalNotificationOptions.java

@@ -9,10 +9,10 @@
 
 package de.appplant.cordova.plugin;
 
-import java.util.Calendar;
-
 import org.json.JSONObject;
 
+import android.R;
+
 /**
  * Class that helps to store the options that can be specified per alarm.
  */
@@ -21,113 +21,104 @@ public class LocalNotificationOptions {
     /*
      * Options that can be set when this plugin is invoked
      */
-    private Calendar calendar = Calendar.getInstance();
-    private String title      = null;
-    private String subTitle   = null;
-    private String sound      = null;
-    private long interval     = 0;
-    private String foreground = null;
-    private String background = null;
-    private int icon          = -1;
-    private int badge         = 0;
-    private String id         = null;
+    private JSONObject options = new JSONObject();
+    private String id          = null;
+    private long interval      = 0;
+    private long date          = 0;
 
     /**
      * Parse options passed from javascript part of this plugin.
      */
-    public void parse (JSONObject options) {
-        String date    = options.optString("date");
-        String message = options.optString("message");
-
-        if (!"".equals(date)) {
-            calendar.setTimeInMillis(1000*Long.parseLong(date));
-        }
-
-        if (!"".equals(message)) {
-            String lines[] = message.split("\\r?\\n");
-
-            title = lines[0];
+    LocalNotificationOptions (JSONObject options) {
+        this.options = options;
+        date         = options.optLong("date") * 1000;
+        //interval   = options.optString("repeat");
+        id           = options.optString("id");
+    }
 
-            if (lines.length > 1)
-                subTitle = lines[1];
-        }
+    /**
+     * Gibt die Eigenschaften als JSONObjekt an.
+     */
+    public JSONObject getJSONObject() {
+        return options;
+    }
 
-        sound      = options.optString("sound");
-        icon       = options.optInt("icon");
-        //interval   = options.optString("repeat");
-        foreground = options.optString("foreground");
-        background = options.optString("background");
-        badge      = options.optInt("badge");
-        id         = options.optString("id");
+    /**
+     * Gibt die Zeit in Sekunden an, wann die Notification aufpoppen soll.
+     */
+    public long getDate() {
+        return date;
     }
 
     /**
-     * Gibt den Kalender mit dem Datum der nächsten Notification an.
+     * Gibt die Nachricht der Notification an.
      */
-    public Calendar getCalendar() {
-       return calendar;
+    public String getMessage () {
+        return options.optString("message");
     }
 
     /**
      * Gibt den Titel der Notification an.
      */
     public String getTitle () {
-       return title;
+        return getMessage().split("\\r?\\n")[0];
     }
 
     /**
      * Gibt den Untertitel der Notification an.
      */
     public String getSubTitle () {
-       return subTitle;
+        String[] lines = getMessage().split("\\r?\\n");
+
+        return (lines.length > 1) ? lines[1] : "";
     }
 
     /**
      * Gibt den Pfad zum Sound der Notification an.
      */
     public String getSound () {
-       return sound;
+        return options.optString("sound", null);
     }
 
     /**
      * Gibt den Pfad zum Icon der Notification an.
      */
     public int getIcon () {
-       return icon;
+        return options.optInt("icon", R.drawable.ic_menu_info_details);
     }
 
     /**
      * Gibt den Pfad zur Callback-Funktion der Notification an.
      */
     public String getForeground () {
-       return foreground;
+        return options.optString("foreground", null);
     }
 
     /**
      * Gibt den Pfad zur Callback-Funktion der Notification an.
      */
     public String getBackground () {
-       return background;
+        return options.optString("background", null);
     }
 
     /**
      * Gibt das Intervall an, in dem die Notification aufpoppen soll (daily, weekly, monthly, yearly)
      */
     public long getInterval () {
-       return interval;
+        return interval;
     }
 
     /**
      * Gibt die Badge-Nummer der Notification an.
      */
     public int getBadge () {
-       return badge;
+        return options.optInt("badge", 0);
     }
 
     /**
      * Gibt die Callback-ID des PluginResults an.
      */
     public String getId () {
-       return id;
+        return id;
     }
 }

+ 93 - 0
src/android/LocalNotificationReceiver.java

@@ -0,0 +1,93 @@
+/**
+ *  LocalNotificationReceiver.java
+ *  Cordova LocalNotification Plugin
+ *
+ *  Created by Sebastian Katzer (github.com/katzer) on 31/08/2013.
+ *  Copyright 2013 Sebastian Katzer. All rights reserved.
+ *  GPL v2 licensed
+ */
+
+package de.appplant.cordova.plugin;
+
+import java.util.Calendar;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.R;
+import android.annotation.TargetApi;
+import android.app.Notification;
+import android.app.Notification.Builder;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+
+/**
+ * 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
+ * Android notification bar. The notification uses the default notification
+ * sound and it vibrates the phone.
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class LocalNotificationReceiver extends BroadcastReceiver {
+
+	public static final String OPTIONS = "LOCAL_NOTIFICATION_OPTIONS";
+
+	@Override
+	public void onReceive (Context context, Intent intent) {
+		NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+		LocalNotificationOptions options    = null;
+		Bundle bundle                       = intent.getExtras();
+		int id                              = 0;
+		JSONObject args;
+
+		try {
+			args    = new JSONObject(bundle.getString(OPTIONS));
+			options = new LocalNotificationOptions(args);
+		} catch (JSONException e) {}
+
+		try {
+			id = Integer.parseInt(options.getId());
+		} catch (Exception e) {}
+
+		/*
+		 * If you set a repeating alarm at 11:00 in the morning and it
+		 * should trigger every morning at 08:00 o'clock, it will
+		 * immediately fire. E.g. Android tries to make up for the
+		 * 'forgotten' reminder for that day. Therefore we ignore the event
+		 * if Android tries to 'catch up'.
+		 */
+		if (options.getInterval() > 0) {
+			Calendar now    = Calendar.getInstance();
+			int alarmHour   = 0;//bundle.getInt(HOUR_OF_DAY);
+			int alarmMin    = 0;//bundle.getInt(MINUTE);
+			int currentHour = now.get(Calendar.HOUR_OF_DAY);
+			int currentMin  = now.get(Calendar.MINUTE);
+
+			if (currentHour != alarmHour && currentMin != alarmMin) {
+
+				return;
+			}
+		}
+
+		Builder notification = new Notification.Builder(context)
+		.setContentTitle(options.getTitle())
+		.setContentText(options.getSubTitle())
+		//.setVibrate(new long[] { 0, 100, 200, 300 })
+		.setDefaults(Notification.DEFAULT_SOUND)
+		.setNumber(0)
+		.setSmallIcon(options.getIcon());
+
+		/*
+		 * If you want all reminders to stay in the notification bar, you should
+		 * generate a random ID. If you want do replace an existing
+		 * notification, make sure the ID below matches the ID that you store in
+		 * the alarm intent.
+		 */
+		notificationMgr.notify(id, notification.build());
+	}
+}