diff --git a/README.md b/README.md
index 463b8d7d..771286a9 100644
--- a/README.md
+++ b/README.md
@@ -217,6 +217,95 @@ window.geofence.getWatched().then(function (geofencesJson) {
});
```
+## Frequency Limiting
+
+```javascript
+notification: {
+ frequency: Number(600), //Seconds required between retriggering a fence.
+}
+```
+
+## Using On/Off Schedule Data
+
+ScheduleData is an array consisting of a start and end time for each day. Array begins on Sunday. All times are local to the device.
+
+```javascript
+notification: {
+ scheduleData: [
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ },
+ {
+ "on": {
+ "hour": "0",
+ "minute": "0"
+ },
+ "off": {
+ "hour": "23",
+ "minute": "59"
+ }
+ }
+ ]
+}
+```
+
## Listening for geofence transitions
```javascript
diff --git a/plugin.xml b/plugin.xml
index f2034ad2..cbba8fdd 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -44,10 +44,14 @@
+
+
-
+
+
+
diff --git a/src/android/GeoNotification.java b/src/android/GeoNotification.java
index 24b13f06..a985bc35 100644
--- a/src/android/GeoNotification.java
+++ b/src/android/GeoNotification.java
@@ -1,5 +1,8 @@
package com.cowbell.cordova.geofence;
+import android.util.Log;
+import android.text.format.Time;
+
import com.google.android.gms.location.Geofence;
import com.google.gson.annotations.Expose;
@@ -14,12 +17,42 @@ public class GeoNotification {
public GeoNotification() {
}
+
+ public boolean isScheduled(){
+ Schedule schedule = new Schedule(this.notification.getScheduleDataJson());
+
+ if(schedule.week == null)
+ return true;
+
+ Time time = new Time();
+ time.setToNow();
+
+ Schedule.WeekDay day = schedule.week[time.weekDay];
+
+ if(day == null)
+ return true;
+
+ if(time.hour >= day.on.hour && time.hour <= day.off.hour){
+ if(time.minute >= day.on.minute && time.minute <= day.off.minute){
+ Log.i("Geofence", "GeoFence is active.");
+ return true;
+ }
+ }
+ Log.i("Geofence", "GeoFence is inactive.");
+ return false;
+ }
+
+ public boolean isFrequencyOk(){
+ Time time = new Time();
+ time.setToNow();
+ return (this.notification.lastTriggered + this.notification.frequency * 1000 < time.toMillis(false));
+ }
public Geofence toGeofence() {
return new Geofence.Builder().setRequestId(id)
.setTransitionTypes(transitionType)
.setCircularRegion(latitude, longitude, radius)
- .setExpirationDuration(Long.MAX_VALUE).build();
+ .setExpirationDuration(Geofence.NEVER_EXPIRE).build();
}
public String toJson() {
diff --git a/src/android/GeoNotificationManager.java b/src/android/GeoNotificationManager.java
index e22942e3..2c68796a 100644
--- a/src/android/GeoNotificationManager.java
+++ b/src/android/GeoNotificationManager.java
@@ -8,6 +8,7 @@
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
+import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.LocationRequest;
@@ -58,14 +59,15 @@ public List getWatched() {
private boolean areGoogleServicesAvailable() {
// Check that Google Play services is available
- int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
-
- // If Google Play services is available
- if (ConnectionResult.SUCCESS == resultCode) {
- return true;
- } else {
- return false;
- }
+ int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this.context);
+
+
+ // If Google Play services is available
+ if (ConnectionResult.SUCCESS == resultCode) {
+ return true;
+ } else {
+ return false;
+ }
}
public void addGeoNotifications(List geoNotifications,
diff --git a/src/android/GeofencePlugin.java b/src/android/GeofencePlugin.java
index 6d4c1aa7..bc540373 100644
--- a/src/android/GeofencePlugin.java
+++ b/src/android/GeofencePlugin.java
@@ -128,6 +128,7 @@ private void deviceReady() {
if (data == null) {
Log.d(TAG, "No notifications clicked.");
} else {
+ intent.removeExtra("geofence.notification.data");
webView.sendJavascript(js);
}
}
diff --git a/src/android/Notification.java b/src/android/Notification.java
index a1be5de6..3b56253e 100644
--- a/src/android/Notification.java
+++ b/src/android/Notification.java
@@ -3,6 +3,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.text.format.Time;
import com.google.gson.annotations.Expose;
@@ -18,6 +19,9 @@ public class Notification {
@Expose public String smallIcon = "";
@Expose public Object data;
@Expose public boolean openAppOnClick;
+ @Expose public Object scheduleData;
+ @Expose public int frequency;
+ @Expose public long lastTriggered = 0;
public void setContext(Context context) {
this.context = context;
@@ -66,6 +70,20 @@ public String getDataJson() {
public long[] getVibrate() {
return concat(new long[] {0}, vibrate);
}
+
+ public String getScheduleDataJson() {
+ if (this.scheduleData == null) {
+ return "";
+ }
+
+ return Gson.get().toJson(this.scheduleData);
+ }
+
+ public void setLastTriggered(){
+ Time time = new Time();
+ time.setToNow();
+ this.lastTriggered = time.toMillis(false);
+ }
public String toString() {
return "Notification title: " + getTitle()
diff --git a/src/android/ReceiveTransitionsIntentService.java b/src/android/ReceiveTransitionsIntentService.java
index 6e6a9f6a..3cf72c79 100644
--- a/src/android/ReceiveTransitionsIntentService.java
+++ b/src/android/ReceiveTransitionsIntentService.java
@@ -70,7 +70,11 @@ protected void onHandleIntent(Intent intent) {
if (geoNotification != null) {
if (geoNotification.notification != null) {
- notifier.notify(geoNotification.notification);
+ if(geoNotification.isScheduled() && geoNotification.isFrequencyOk()){
+ geoNotification.notification.setLastTriggered();
+ store.setGeoNotification(geoNotification);
+ notifier.notify(geoNotification.notification);
+ }
}
geoNotification.transitionType = transitionType;
geoNotifications.add(geoNotification);
diff --git a/src/android/Schedule.java b/src/android/Schedule.java
new file mode 100644
index 00000000..bc59997e
--- /dev/null
+++ b/src/android/Schedule.java
@@ -0,0 +1,32 @@
+package com.cowbell.cordova.geofence;
+
+import com.google.gson.annotations.Expose;
+
+public class Schedule {
+ public class WeekDay{
+ public class On{
+ @Expose public int hour;
+ @Expose public int minute;
+ }
+ public class Off{
+ @Expose public int hour;
+ @Expose public int minute;
+ }
+
+ @Expose public On on;
+ @Expose public Off off;
+
+ public WeekDay(String json){
+ on = Gson.get().fromJson(json, On.class);
+ off = Gson.get().fromJson(json, Off.class);
+ }
+ }
+
+ @Expose public WeekDay[] week;
+
+ public Schedule(String json){
+ week = Gson.get().fromJson(json, WeekDay[].class);
+ }
+
+
+}
diff --git a/src/ios/GeofencePlugin.swift b/src/ios/GeofencePlugin.swift
index eab02270..64c753ad 100644
--- a/src/ios/GeofencePlugin.swift
+++ b/src/ios/GeofencePlugin.swift
@@ -153,6 +153,7 @@ func log(messages: [String]) {
func didReceiveLocalNotification (notification: NSNotification) {
log("didReceiveLocalNotification")
+
if UIApplication.sharedApplication().applicationState != UIApplicationState.Active {
var data = "undefined"
if let uiNotification = notification.object as? UILocalNotification {
@@ -391,13 +392,55 @@ class GeoNotificationManager : NSObject, CLLocationManagerDelegate {
if var geoNotification = store.findById(region.identifier) {
geoNotification["transitionType"].int = transitionType
+ isScheduled(geoNotification)
+ isFrequencyOk(geoNotification)
if geoNotification["notification"].isExists() {
- notifyAbout(geoNotification)
+ if(isScheduled(geoNotification) && isFrequencyOk(geoNotification)){
+ notifyAbout(geoNotification)
+ }
}
NSNotificationCenter.defaultCenter().postNotificationName("handleTransition", object: geoNotification.rawString(NSUTF8StringEncoding, options: []))
}
}
+
+ func isScheduled(geo: JSON) -> Bool{
+
+ let date = NSDate()
+ let components = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)?.components([NSCalendarUnit.Weekday, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: date)
+
+ if(geo["notification"]["scheduleData"][(components?.weekday)!] != nil){
+
+ let day = geo["notification"]["scheduleData"][((components?.weekday)!-1)]
+ if(((components?.hour)! as Int) >= (Int(day["on"]["hour"].string!)) && ((components?.hour)! as Int) <= (Int(day["off"]["hour"].string!))){
+ if(((components?.minute)! as Int) >= (Int(day["on"]["minute"].string!)) && ((components?.minute)! as Int) <= (Int(day["off"]["minute"].string!))){
+ log("GeoFence scheduled as active.")
+ return true
+ }
+ }
+ log("GeoFence scheduled as inactive.")
+ return false
+ }
+ log("GeoFence has no schedule today.")
+ return true
+
+ }
+
+ func isFrequencyOk(var geo: JSON) -> Bool{
+ let store = GeoNotificationStore()
+
+ if(geo["notification"]["lastTriggered"] != nil){
+ if(Int(NSDate().timeIntervalSince1970) < geo["notification"]["lastTriggered"].int! + geo["notification"]["frequency"].int!){
+ log("GeoFence triggered before frequency limit elapsed.")
+ return false
+ }
+ }
+ geo["notification"]["lastTriggered"] = JSON(NSDate().timeIntervalSince1970)
+ log("New Geo Obj: \(geo["notification"])")
+ store.update(geo)
+
+ return true
+ }
func notifyAbout(geo: JSON) {
log("Creating notification")