Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added On/Off Scheduling and Frequency Limiting (Android and iOS) #136

Open
wants to merge 40 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
2c03d02
Adding scheduling and frequency limits.
Dec 8, 2015
52bb594
Adding scheduling and frequency limits.
Dec 8, 2015
6eccd34
Trying play services dependency instead
QuantumRand Dec 10, 2015
9913fe6
Adding scheduling and frequency limits iOS
Dec 10, 2015
083ee07
Merge branch 'master' of https://github.com/QuantumRand/cordova-plugi…
Dec 10, 2015
af40f0a
Including latest play-services
Dec 11, 2015
de4afd1
Using google-play-services plugin v28.0.0
Dec 11, 2015
56e6f6d
Using google-play-services plugin v28.0.0
Dec 11, 2015
d0e782f
Dependencies
Dec 11, 2015
06a726d
Dependencies
Dec 11, 2015
aabc32f
Dependencies
Dec 11, 2015
d8ca4d1
Dependencies
Dec 11, 2015
9f0c433
Dependencies
Dec 11, 2015
448fece
Update plugin.xml
QuantumRand Dec 11, 2015
268f26a
Dependencies
Dec 11, 2015
be00b9c
Update plugin.xml
QuantumRand Dec 11, 2015
b8d5730
Update plugin.xml
QuantumRand Dec 11, 2015
9b4f209
Update plugin.xml
QuantumRand Dec 11, 2015
6de8d14
Update plugin.xml
QuantumRand Dec 12, 2015
04ad4d8
Update plugin.xml
QuantumRand Dec 14, 2015
a3dbb65
Update plugin.xml
QuantumRand Dec 14, 2015
f8efdf0
Google Play Services error
Dec 14, 2015
11ce688
Google Play Services error
Dec 14, 2015
10b11e6
Google Play Services error
Dec 14, 2015
d6d2da2
Google Play Services error
Dec 14, 2015
0e6c480
Google Play Services error
Dec 14, 2015
6165f18
Google Play Services error
Dec 14, 2015
7fae388
Google Play Services error
Dec 14, 2015
cca11cb
Google Play Services error
Dec 14, 2015
d6b1745
Scheduling fix, onNotificationClicked fix
Dec 18, 2015
5eeb942
Use NEVER_EXPIRE
Dec 19, 2015
87afeab
iOS Scheduling fix
Dec 21, 2015
9c0786f
iOS Scheduling fix
Dec 21, 2015
c866ffc
Merge pull request #1 from cowbell/master
QuantumRand Mar 22, 2016
3c4bbbe
Added Schedule and Frequency examples
QuantumRand Apr 2, 2016
5d65dcc
Merge pull request #2 from QuantumRand/master
QuantumRand Apr 2, 2016
3052bd8
cleanup
QuantumRand Apr 4, 2016
caa2e15
cleanup
QuantumRand Apr 4, 2016
2d5d504
cleanup
QuantumRand Apr 4, 2016
5cd188f
Merge pull request #3 from cowbell/master
QuantumRand Sep 30, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,95 @@ window.geofence.getWatched().then(function (geofencesJson) {
});
```

## Frequency Limiting

```javascript
notification: {
frequency: Number(600), //Seconds required between retriggering a fence.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering about the name here. Maybe throttle

}
```

## 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: [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking how to make this simpler. How about:

notification: {
     weekSchedule: {
           monday: "8:00-16:30",
           tuesday: "9:00-14:00",
           .....
     }

but actually, parse this in javascript and send to a Java code using your way.

{
"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
Expand Down
6 changes: 5 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@
<source-file src="src/android/Notification.java" target-dir="src/com/cowbell/cordova/geofence" />
<source-file src="src/android/ReceiveTransitionsIntentService.java" target-dir="src/com/cowbell/cordova/geofence" />
<source-file src="src/android/RemoveGeofenceCommand.java" target-dir="src/com/cowbell/cordova/geofence" />
<source-file src="src/android/Schedule.java" target-dir="src/com/cowbell/cordova/geofence" />


<framework src="com.google.android.gms:play-services-location:+" />
<lib-file src="src/android/libs/gson-2.3.jar" />




<config-file target="config.xml" parent="/*">
<feature name="GeofencePlugin">
<param name="android-package" value="com.cowbell.cordova.geofence.GeofencePlugin" />
Expand Down
35 changes: 34 additions & 1 deletion src/android/GeoNotification.java
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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() {
Expand Down
18 changes: 10 additions & 8 deletions src/android/GeoNotificationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -58,14 +59,15 @@ public List<GeoNotification> 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<GeoNotification> geoNotifications,
Expand Down
1 change: 1 addition & 0 deletions src/android/GeofencePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/android/Notification.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion src/android/ReceiveTransitionsIntentService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
32 changes: 32 additions & 0 deletions src/android/Schedule.java
Original file line number Diff line number Diff line change
@@ -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);
}


}
45 changes: 44 additions & 1 deletion src/ios/GeofencePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")
Expand Down