Commit ae05c066 authored by Chris Scott's avatar Chris Scott

Merge pull request #15 from christocracy/http_service

Http service
parents ca77173d b8362a8b
......@@ -178,10 +178,10 @@ var app = {
distanceFilter: 50,
locationUpdateInterval: 5000,
activityRecognitionInterval: 10000,
stopTimeout: 1,
forceReload: true, // <-- If the user closes the app **while location-tracking is started** , reboot app (WARNING: possibly distruptive to user)
activityType: 'AutomotiveNavigation',
stopOnTerminate: false // <-- Allow the background-service to run headless when user closes the app.
stopTimeout: 0,
forceReload: true, // <-- If the user closes the app **while location-tracking is started** , reboot app (WARNING: possibly distruptive to user)
stopOnTerminate: false, // <-- Allow the background-service to run headless when user closes the app.
activityType: 'AutomotiveNavigation'
/**
* HTTP Feature: set an url to allow the native background service to POST locations to your server
*
......
......@@ -29,6 +29,7 @@
<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" />
......
......@@ -15,6 +15,7 @@ import com.transistorsoft.cordova.bggeo.BackgroundGeolocationService.StationaryL
import de.greenrobot.event.EventBus;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.util.Log;
......@@ -48,7 +49,7 @@ public class BackgroundGeolocationPlugin extends CordovaPlugin {
@Override
protected void pluginInitialize() {
gWebView = this.webView;
// Register for events fired by our IntentService "LocationService"
EventBus.getDefault().register(this);
}
......
......@@ -35,6 +35,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings.Secure;
import android.util.Log;
public class BackgroundGeolocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
......@@ -101,7 +102,7 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
/**
* @config {JSONObject} headers For sending location to your server
*/
private JSONObject headers = null;
private JSONObject headers = new JSONObject();
// Flags
private Boolean isEnabled = false;
......@@ -150,6 +151,7 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
Log.i(TAG, " locationUpdateInterval: " + locationUpdateInterval);
Log.i(TAG, " activityRecognitionInterval: " + activityRecognitionInterval);
Log.i(TAG, " stopTimeout: " + stopTimeout);
Log.i(TAG, " stopOnTerminate: " + stopOnTerminate);
Log.i(TAG, " forceReload: " + forceReload);
Log.i(TAG, "----------------------------------------");
......@@ -158,13 +160,6 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
}
// Configure FusedLocationProvider
locationRequest = LocationRequest.create()
.setPriority(translateDesiredAccuracy(desiredAccuracy))
.setInterval(this.locationUpdateInterval)
.setFastestInterval(30000)
.setSmallestDisplacement(distanceFilter);
// Connect to google-play services.
if (ConnectionResult.SUCCESS == GooglePlayServicesUtil.isGooglePlayServicesAvailable(this)) {
Log.i(TAG, "- Connecting to GooglePlayServices...");
......@@ -199,6 +194,13 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
public void onConnected(Bundle arg0) {
Log.i(TAG, "- GooglePlayServices connected");
// Configure FusedLocationProvider
locationRequest = LocationRequest.create()
.setPriority(translateDesiredAccuracy(desiredAccuracy))
.setInterval(this.locationUpdateInterval)
.setFastestInterval(30000)
.setSmallestDisplacement(distanceFilter);
Intent arsIntent = new Intent(this, ActivityRecognitionService.class);
activityRecognitionPI = PendingIntent.getService(this, 0, arsIntent, PendingIntent.FLAG_UPDATE_CURRENT);
......@@ -217,12 +219,12 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
* @param {PausedEvent} event
*/
public void onEventMainThread(PausedEvent event) {
isPaused = event.isPaused;
if (isPaused) {
setPace(isMoving);
} else {
removeLocationUpdates();
}
isPaused = event.isPaused;
if (isPaused) {
setPace(isMoving);
} else {
removeLocationUpdates();
}
}
/**
......@@ -231,7 +233,7 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
* @param {PaceChangeEvent} event
*/
public void onEventMainThread(PaceChangeEvent event) {
setPace(event.isMoving);
setPace(event.isMoving);
}
/**
......@@ -243,6 +245,12 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
String probableActivityName = getActivityName(currentActivity.getType());
Log.i(TAG, "- Activity received: " + probableActivityName + ", confidence: " + currentActivity.getConfidence());
// If configured to stop when user closes app, kill this service.
if (!BackgroundGeolocationPlugin.isActive() && stopOnTerminate) {
stopSelf();
return;
}
boolean wasMoving = isMoving;
boolean nowMoving = false;
......@@ -408,7 +416,15 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
JSONObject data = locationToJson(location);
params.put("location", data);
// Append android UUID to params so that server can map the UUID to some user in your database on server.
// If you've configured the plugin to execute on BOOT, there's no way to append your user's auth-token to the params
// since this BackgroundGeolocationService will be running in "headless" mode.
//
// It's up to you to register this UUID with your system. You can fetch this UUID using the
// Cordova Device plugin org.apache.cordova.device http://plugins.cordova.io/#/package/org.apache.cordova.device
params.put("android_id", Secure.getString(this.getContentResolver(), Secure.ANDROID_ID));
Log.i(TAG, "data: " + params.toString());
StringEntity se = new StringEntity(params.toString());
......@@ -462,7 +478,7 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
}
private void requestLocationUpdates() {
if (!isPaused || !isEnabled) { return; } // <-- Don't engage GPS when app is in foreground
if (!isPaused || !isEnabled) { return; } // <-- Don't engage GPS when app is in foreground
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, locationUpdatePI);
}
......@@ -541,18 +557,18 @@ public class BackgroundGeolocationService extends Service implements GoogleApiCl
}
public static class PausedEvent {
public boolean isPaused;
public PausedEvent(boolean paused) {
isPaused = paused;
}
public boolean isPaused;
public PausedEvent(boolean paused) {
isPaused = paused;
}
}
public static class PaceChangeEvent {
public boolean isMoving;
public PaceChangeEvent(boolean moving) {
isMoving = moving;
}
}
public static class PaceChangeEvent {
public boolean isMoving;
public PaceChangeEvent(boolean moving) {
isMoving = moving;
}
}
class StationaryLocation extends Location {
......
package com.transistorsoft.cordova.bggeo;
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.location.ActivityRecognition;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
/**
* This boot receiver is meant to handle the case where device is first booted after power up. This will initiate
* Google Play's ActivityRecognition API, whose events will be sent to BackgroundGeolocationService as usual.
* @author chris
* 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 implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public class BootReceiver extends BroadcastReceiver {
private static final String TAG = "BackgroundGeolocation";
private GoogleApiClient googleApiClient;
private PendingIntent locationUpdateService;
private Integer activityRecognitionInterval = 10000;
private PendingResult pendingResult;
/**
* Background Geolocation Configuration params.
* If you're auto-running the service on BOOT, you need to manually configure the params here since the foreground app will not have been booted.
*/
private float distanceFilter = 50;
private Integer desiredAccuracy = 0;
private Integer locationUpdateInterval = 5000;
private Integer activityRecognitionInterval = 10000;
private long stopTimeout = 0;
private boolean debug = true;
private boolean stopOnTerminate = false;
private boolean forceReload = false;
private String url = "http://posttestserver.com/post.php?dir=cordova-background-geolocation";
private String params = "{'foo':'bar'}";
private String headers = "{'X-FOO':'BAR'}";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "- BootReceiver auto-running ActivityRecognition system");
Log.i(TAG, "- BootReceiver booting service");
// GoogleApiClient connection is asynchronous process. @see #onConnected
pendingResult = goAsync();
Intent backgroundServiceIntent = new Intent(context, BackgroundGeolocationService.class);
// Connect to google-play services.
if (ConnectionResult.SUCCESS == GooglePlayServicesUtil.isGooglePlayServicesAvailable(context)) {
Log.i(TAG, "- Connecting to GooglePlayServices...");
googleApiClient = new GoogleApiClient.Builder(context)
.addApi(ActivityRecognition.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
} else {
Log.e(TAG, "- GooglePlayServices unavailable");
}
// Configure background geolocation service params.
backgroundServiceIntent.putExtra("distanceFilter", distanceFilter);
backgroundServiceIntent.putExtra("desiredAccuracy", desiredAccuracy);
backgroundServiceIntent.putExtra("locationUpdateInterval", locationUpdateInterval);
backgroundServiceIntent.putExtra("activityRecognitionInterval", activityRecognitionInterval);
backgroundServiceIntent.putExtra("stopTimeout", stopTimeout);
backgroundServiceIntent.putExtra("debug", debug);
backgroundServiceIntent.putExtra("stopOnTerminate", stopOnTerminate);
backgroundServiceIntent.putExtra("forceReload", forceReload);
backgroundServiceIntent.putExtra("url", url);
backgroundServiceIntent.putExtra("params", params);
backgroundServiceIntent.putExtra("headers", headers);
// This is the IntentService we'll provide to google-play API.
locationUpdateService = PendingIntent.getService(context, 0, new Intent(context, LocationService.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
private void requestActivityUpdates() {
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(googleApiClient, activityRecognitionInterval, locationUpdateService);
// Start the service.
context.startService(backgroundServiceIntent);
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
pendingResult.finish();
}
@Override
public void onConnected(Bundle arg0) {
requestActivityUpdates();
pendingResult.finish();
}
@Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
pendingResult.finish();
}
}
\ No newline at end of file
}
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