Commit 2a6ef1c0 authored by Chris Scott's avatar Chris Scott

Merge pull request #48 from christocracy/edge

Merging edge to master finally
parents 6bef7fed b8b92c56
.DS_Store
This diff is collapsed.
......@@ -9,4 +9,19 @@
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
</widget>
......@@ -24,12 +24,11 @@
<meta name="msapplication-tap-highlight" content="no" />
<!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src * 'unsafe-inline' data:; img-src *; script-src * 'unsafe-inline' 'unsafe-eval'">
<link rel="stylesheet" type="text/css" href="css/bootstrap-min.css" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>BG GeoLocation</title>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=true&libraries=geometry">
</script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=geometry"></script>
</head>
<body>
......@@ -51,6 +50,7 @@
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/jquery-2.1.1.js"></script>
<script type="text/javascript" src="js/LongPress.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
/**
* Custom google-maps @event LongClick hack.
*/
function LongPress(map, maxTime) {
this.maxTime = maxTime;
this.isDragging = false;
var me = this;
me.map = map;
google.maps.event.addListener(map, 'mousedown', function(e) {
me.onMouseDown_(e);
});
google.maps.event.addListener(map, 'mouseup', function(e) {
me.onMouseUp_(e);
});
google.maps.event.addListener(map, 'drag', function(e) {
me.onMapDrag_(e);
});
}
LongPress.prototype.onMouseUp_ = function(e) {
var now = +new Date;
if (now - this.downTime > this.maxTime && this.isDragging === false) {
google.maps.event.trigger(this.map, 'longpress', e);
}
}
LongPress.prototype.onMouseDown_ = function() {
this.downTime = +new Date;
this.isDragging = false;
}
LongPress.prototype.onMapDrag_ = function(e) {
this.isDragging = true;
};
This diff is collapsed.
......@@ -3,47 +3,34 @@
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="com.transistorsoft.cordova.background-geolocation"
version="0.3.6">
version="0.4.1">
<name>BackgroundGeolocation</name>
<description>Sophisticated, battery-efficient background-geolocation plugin for Cordova</description>
<license>MIT</license>
<keywords>phonegap,background geolocation</keywords>
<keywords>cordova, phonegap, background geolocation</keywords>
<engines>
<engine name="cordova" version=">=3.0.0" />
</engines>
<dependency id="org.apache.cordova.geolocation" />
<dependency id="org.apache.cordova.dialogs" />
<dependency id="com.google.playservices" url="https://github.com/MobileChromeApps/google-play-services.git" />
<js-module src="www/BackgroundGeoLocation.js" name="BackgroundGeoLocation">
<clobbers target="plugins.backgroundGeoLocation" />
</js-module>
<!-- android -->
<platform name="android">
<framework src="com.google.android.gms:play-services-location:7.3.0" />
<source-file src="src/android/libs/eventbus-2.4.0.jar" target-dir="libs" />
<source-file src="src/android/BackgroundGeolocationPlugin.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<source-file src="src/android/BackgroundGeolocationService.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<source-file src="src/android/ActivityRecognitionService.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<source-file src="src/android/LocationService.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<source-file src="src/android/BootReceiver.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<!-- For SQLite persistence NOT YET IMPLEMENTED
<source-file src="src/android/data/LocationDAO.java" target-dir="src/com/tenforwardconsulting/cordova/bgloc/data" />
<source-file src="src/android/data/sqlite/LocationOpenHelper.java" target-dir="src/com/tenforwardconsulting/cordova/bgloc/data/sqlite" />
<source-file src="src/android/data/sqlite/SQLiteLocationDAO.java" target-dir="src/com/tenforwardconsulting/cordova/bgloc/data/sqlite" />
-->
<source-file src="src/android/libs/transistor-locationmanager.jar" target-dir="libs" />
<source-file src="src/android/CDVBackgroundGeolocation.java" target-dir="src/com/transistorsoft/cordova/bggeo" />
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<service android:name="com.transistorsoft.cordova.bggeo.BackgroundGeolocationService" />
<service android:name="com.transistorsoft.cordova.bggeo.LocationService" />
<service android:name="com.transistorsoft.cordova.bggeo.ActivityRecognitionService" />
<!-- autorun on boot receiver -->
<receiver android:name="com.transistorsoft.cordova.bggeo.BootReceiver" android:enabled="true" android:exported="false">
<service android:name="com.transistorsoft.locationmanager.BackgroundGeolocationService" />
<service android:name="com.transistorsoft.locationmanager.LocationService" />
<service android:name="com.transistorsoft.locationmanager.ActivityRecognitionService" />
<receiver android:name="com.transistorsoft.locationmanager.BootReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
......@@ -63,7 +50,7 @@
</config-file>
<config-file target="res/xml/config.xml" parent="/*">
<feature name="BackgroundGeoLocation">
<param name="android-package" value="com.transistorsoft.cordova.bggeo.BackgroundGeolocationPlugin"/>
<param name="android-package" value="com.transistorsoft.cordova.bggeo.CDVBackgroundGeolocation"/>
</feature>
</config-file>
</platform>
......@@ -83,13 +70,15 @@
<config-file target="config.xml" parent="/*">
<feature name="BackgroundGeoLocation">
<param name="ios-package" value="CDVBackgroundGeoLocation"/>
<param name="ios-package" value="CDVBackgroundGeolocation"/>
</feature>
</config-file>
<framework src="AudioToolbox.framework" weak="true" />
<framework src="AVFoundation.framework" weak="true" />
<source-file src="src/ios/CDVBackgroundGeoLocation.m" />
<header-file src="src/ios/CDVBackgroundGeoLocation.h" />
<framework src="libsqlite3.dylib" weak="true" />
<framework src="src/ios/TSLocationManager.framework" custom="true" />
<source-file src="src/ios/CDVBackgroundGeolocation.m" />
<header-file src="src/ios/CDVBackgroundGeolocation.h" />
</platform>
<!-- wp8 -->
......
package com.transistorsoft.cordova.bggeo;
import de.greenrobot.event.EventBus;
import com.google.android.gms.location.DetectedActivity;
import com.google.android.gms.location.ActivityRecognitionResult;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class ActivityRecognitionService extends IntentService {
private static final String TAG = "BackgroundGeolocation";
public ActivityRecognitionService() {
super("com.transistorsoft.cordova.bggeo.ActivityRecognitionService");
}
@Override
protected void onHandleIntent(Intent intent) {
// Determine whether the fore-ground Activity is running. If it's not, we'll reboot it.
if (ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
DetectedActivity probableActivity = result.getMostProbableActivity();
Log.w(TAG, "Activity detected:" + getActivityName(probableActivity.getType()) + ", confidence:" + probableActivity.getConfidence());
if (probableActivity.getConfidence() < 80) {
return;
}
switch (probableActivity.getType()) {
case DetectedActivity.IN_VEHICLE:
case DetectedActivity.ON_BICYCLE:
case DetectedActivity.ON_FOOT:
case DetectedActivity.WALKING:
case DetectedActivity.RUNNING:
case DetectedActivity.STILL:
EventBus.getDefault().post(result);
break;
case DetectedActivity.UNKNOWN:
return;
case DetectedActivity.TILTING:
return;
}
}
}
/**
* This method has no other purpose than formatting the Activity for log-messages
*/
private String getActivityName(int activityType) {
switch (activityType) {
case DetectedActivity.IN_VEHICLE:
return "in_vehicle";
case DetectedActivity.ON_BICYCLE:
return "on_bicycle";
case DetectedActivity.ON_FOOT:
return "on_foot";
case DetectedActivity.RUNNING:
return "running";
case DetectedActivity.WALKING:
return "walking";
case DetectedActivity.STILL:
return "still";
case DetectedActivity.UNKNOWN:
return "unknown";
case DetectedActivity.TILTING:
return "tilting";
}
return "unknown";
}
}
\ No newline at end of file
This diff is collapsed.
package com.transistorsoft.cordova.bggeo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
/**
* This boot receiver is meant to handle the case where device is first booted after power up.
* This boot the headless BackgroundGeolocationService as configured by this class.
* @author chris scott
*
*/
public class BootReceiver extends BroadcastReceiver {
private static final String TAG = "BackgroundGeolocation";
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences settings = context.getSharedPreferences(TAG, 0);
boolean startOnBoot = settings.getBoolean("startOnBoot", false);
boolean enabled = settings.getBoolean("enabled", false);
if (!startOnBoot || !enabled) {
return;
}
Log.i(TAG, "- BootReceiver booting service");
// Start the service.
context.startService(new Intent(context, BackgroundGeolocationService.class));
}
}
package com.transistorsoft.cordova.bggeo;
import de.greenrobot.event.EventBus;
import com.google.android.gms.location.FusedLocationProviderApi;
import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.util.Log;
public class LocationService extends IntentService {
private static final String TAG = "BackgroundGeolocation";
public LocationService() {
super("com.transistorsoft.cordova.bggeo.LocationUpdateService");
}
@Override
protected void onHandleIntent(Intent intent) {
final Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
if (location != null) {
Log.i(TAG, "Location received: " + location.toString());
EventBus.getDefault().post(location);
}
}
}
\ No newline at end of file
package com.transistorsoft.cordova.bggeo.data;
import org.json.JSONObject;
import org.json.JSONException;
public interface LocationDAO {
public JSONObject[] getAllLocations();
public boolean persistLocation(JSONObject l);
public void deleteLocation(JSONObject l);
}
\ No newline at end of file
package com.transistorsoft.cordova.bggeo.data.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class LocationOpenHelper extends SQLiteOpenHelper {
private static final String SQLITE_DATABASE_NAME = "cordova_background_geolocation";
private static final int DATABASE_VERSION = 1;
public static final String LOCATION_TABLE_NAME = "locations";
private static final String LOCATION_TABLE_COLUMNS = "timestamp INTEGER PRIMARY KEY, json TEXT";
private static final String LOCATION_TABLE_CREATE = "CREATE TABLE " + LOCATION_TABLE_NAME + " (" + LOCATION_TABLE_COLUMNS + ");";
LocationOpenHelper(Context context) {
super(context, SQLITE_DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(LOCATION_TABLE_CREATE);
Log.d(this.getClass().getName(), LOCATION_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
package com.transistorsoft.cordova.bggeo.data.sqlite;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
import java.util.List;
import org.json.JSONObject;
import org.json.JSONException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.transistorsoft.cordova.bggeo.data.LocationDAO;
public class SQLiteLocationDAO implements LocationDAO {
private static final String TAG = "SQLiteLocationDAO";
private Context context;
public SQLiteLocationDAO(Context context) {
this.context = context;
}
/*
public JSONObject[] getAllLocations() {
SQLiteDatabase db = null;
Cursor c = null;
List<JSONObject> all = new ArrayList<JSONObject>();
try {
db = new LocationOpenHelper(context).getReadableDatabase();
c = db.query(LocationOpenHelper.LOCATION_TABLE_NAME, null);
while (c.moveToNext()) {
all.add(hydrate(c));
}
} finally {
if (c != null) {
c.close();
}
if (db != null) {
db.close();
}
}
return all.toArray(new JSONObject[all.size()]);
}
public boolean persistLocation(JSONObject location) {
SQLiteDatabase db = new LocationOpenHelper(context).getWritableDatabase();
db.beginTransaction();
ContentValues values = getContentValues(location);
long rowId = db.insert(LocationOpenHelper.LOCATION_TABLE_NAME, null, values);
Log.d(TAG, "After insert, rowId = " + rowId);
db.setTransactionSuccessful();
db.endTransaction();
db.close();
if (rowId > -1) {
return true;
} else {
return false;
}
}
public void deleteLocation(JSONObject location) {
SQLiteDatabase db = new LocationOpenHelper(context).getWritableDatabase();
db.beginTransaction();
db.delete(LocationOpenHelper.LOCATION_TABLE_NAME, "timestamp = ?", location.getString("timestamp"));
db.setTransactionSuccessful();
db.endTransaction();
db.close();
}
private JSONObject hydrate(Cursor c) {
JSONObject l = new JSONObject(c);
return l;
}
private ContentValues getContentValues(JSONObject location) {
ContentValues values = new ContentValues();
values.put("latitude", location.get("latitude"));
values.put("longitude", location.get("longitude"));
values.put("timestamp", location.get("timestamp"));
values.put("accuracy", location.get("accuracy"));
values.put("altitude", location.get("altitude"));
values.put("bearing", location.get("bearing"));
values.put("speed", location.get("speed"));
return values;
}
*/
}
\ No newline at end of file
......@@ -5,12 +5,12 @@
//
#import <Cordova/CDVPlugin.h>
#import "CDVLocation.h"
#import <AudioToolbox/AudioToolbox.h>
#import <TSLocationManager/TSLocationManager.h>
@interface CDVBackgroundGeoLocation : CDVPlugin <CLLocationManagerDelegate>
@interface CDVBackgroundGeolocation : CDVPlugin
@property (nonatomic, strong) NSString* syncCallbackId;
@property (nonatomic, strong) NSString* geofenceCallbackId;
@property (nonatomic, strong) NSMutableArray* stationaryRegionListeners;
- (void) configure:(CDVInvokedUrlCommand*)command;
......@@ -21,9 +21,11 @@
- (void) setConfig:(CDVInvokedUrlCommand*)command;
- (void) addStationaryRegionListener:(CDVInvokedUrlCommand*)command;
- (void) getStationaryLocation:(CDVInvokedUrlCommand *)command;
- (void) onSuspend:(NSNotification *)notification;
- (void) onResume:(NSNotification *)notification;
- (void) onAppTerminate;
- (void) getLocations:(CDVInvokedUrlCommand *)command;
- (void) sync:(CDVInvokedUrlCommand *)command;
- (void) getOdometer:(CDVInvokedUrlCommand *)command;
- (void) resetOdometer:(CDVInvokedUrlCommand *)command;
- (void) addGeofence:(CDVInvokedUrlCommand *)command;
- (void) onGeofence:(CDVInvokedUrlCommand *)command;
@end
This diff is collapsed.
Versions/Current/Headers
\ No newline at end of file
Versions/Current/Resources
\ No newline at end of file
Versions/Current/TSLocationManager
\ No newline at end of file
#import <CoreLocation/CoreLocation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <sqlite3.h>
@interface TSLocationManager : NSObject <CLLocationManagerDelegate>
@property (nonatomic) CLLocationDistance odometer;
- (void) configure:(NSDictionary*)config;
- (void) start;
- (void) stop;
- (void) finish;
- (NSArray*) sync;
- (NSArray*) getLocations;
- (void) stopBackgroundTask;
- (void) onPaceChange:(BOOL)value;
- (void) setConfig:(NSDictionary*)command;
- (NSDictionary*) getStationaryLocation;
- (void) onSuspend:(NSNotification *)notification;
- (void) onResume:(NSNotification *)notification;
- (void) onAppTerminate;
- (BOOL) isEnabled;
- (NSDictionary*) locationToDictionary:(CLLocation*)location;
- (void) addGeofence:(NSString*)identifier radius:(CLLocationDistance)radius latitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude;
@end
framework module TSLocationManager {
umbrella header "TSLocationManager.h"
export *
module * { export * }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/TSLocationManager.h</key>
<data>
93eNJDqyN5vuBJn9oYeT7lb2x1w=
</data>
<key>Info.plist</key>
<data>
1G+AqP61j6Sq6MmsyYP98Uqa1/Y=
</data>
<key>Modules/module.modulemap</key>
<data>
ZlH8rkma2jB7yWJU5dFqHfgbHZc=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/TSLocationManager.h</key>
<data>
93eNJDqyN5vuBJn9oYeT7lb2x1w=
</data>
<key>Modules/module.modulemap</key>
<data>
ZlH8rkma2jB7yWJU5dFqHfgbHZc=
</data>
</dict>
<key>rules</key>
<dict>
<key>^</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
......@@ -20,8 +20,15 @@ module.exports = {
configure: function(success, failure, config) {
config = config || {};
this.config = config;
exec(success || function() {},
success = success || function(location) {};
var mySuccess = function(location) {
// Transform timestamp to Date instance.
if (location.timestamp) {
location.timestamp = new Date(location.timestamp);
}
success.call(this, location);
}
exec(mySuccess,
failure || function() {},
'BackgroundGeoLocation',
'configure',
......@@ -98,6 +105,96 @@ module.exports = {
'addStationaryRegionListener',
[]);
},
getLocations: function(success, failure) {
if (typeof(success) !== 'function') {
throw "BackgroundGeolocation#getLocations requires a success callback";
}
var me = this;
var mySuccess = function(locations) {
success.call(this, me._setTimestamp(locations));
}
exec(mySuccess,
failure || function() {},
'BackgroundGeoLocation',
'getLocations',
[]);
},
/**
* Signal native plugin to sync locations queue to HTTP
*/
sync: function(success, failure) {
if (typeof(success) !== 'function') {
throw "BackgroundGeolocation#sync requires a success callback";
}
var me = this;
var mySuccess = function(locations) {
success.call(this, me._setTimestamp(locations));
}
exec(mySuccess,
failure || function() {},
'BackgroundGeoLocation',
'sync',
[]);
},
/**
* Fetch current odometer value
*/
getOdometer: function(success, failure) {
exec(success || function() {},
failure || function() {},
'BackgroundGeoLocation',
'getOdometer',
[]);
},
/**
* Reset Odometer to 0
*/
resetOdometer: function(success, failure) {
exec(success || function() {},
failure || function() {},
'BackgroundGeoLocation',
'resetOdometer',
[]);
},
/**
* add geofence
*/
addGeofence: function(config, success, failure) {
config = config || {};
if (!config.identifier) {
throw "#addGeofence requires an 'identifier'";
}
if (!(config.latitude && config.longitude)) {
throw "#addGeofence requires a #latitude and #longitude";
}
if (!config.radius) {
throw "#addGeofence requires a #radius";
}
exec(success || function() {},
failure || function() {},
'BackgroundGeoLocation',
'addGeofence',
[config]);
},
onGeofence: function(success, failure) {
if (!typeof(success) === 'function') {
throw "#onGeofence requires a success callback";
}
exec(success,
failure || function() {},
'BackgroundGeoLocation',
'onGeofence',
[]);
},
_setTimestamp: function(rs) {
// Transform timestamp to Date instance.
if (typeof(rs) === 'object') {
for (var n=0,len=rs.length;n<len;n++) {
rs[n].timestamp = new Date(rs[n].timestamp);
}
}
return rs;
},
apply: function(destination, source) {
source = source || {};
for (var property in source) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment