Commit add9a85c authored by Chris Scott's avatar Chris Scott

Implement Android auto-boot on device startup. Implemented Android setConfig...

Implement Android auto-boot on device startup.  Implemented Android setConfig method.  Implement Android onStationary method.  Refactoring and cleanup.
parent 5710fba8
...@@ -16,7 +16,7 @@ Cordova Background Geolocation - Terms and conditions ...@@ -16,7 +16,7 @@ Cordova Background Geolocation - Terms and conditions
- Allowing 3rd Parties to run Software on Licensee's Website[s] and Server[s]; - Allowing 3rd Parties to run Software on Licensee's Website[s] and Server[s];
- Publishing Software’s output to Licensee and 3rd Parties; - Publishing Software’s output to Licensee and 3rd Parties;
- Distribute verbatim copies of Software's output (including compiled binaries); - Distribute verbatim copies of Software's output (including compiled binaries);
- Modify Software to suit Licensee’s needs and specifications. - Modify Software to suit Licensee's needs and specifications.
2.2 Binary Restricted: Licensee may sublicense Software as a part of a larger work containing more than Software, distributed solely in Object or Binary form under a personal, non-sublicensable, limited license. Such redistribution shall be limited to unlimited codebases.</li><li> 2.2 Binary Restricted: Licensee may sublicense Software as a part of a larger work containing more than Software, distributed solely in Object or Binary form under a personal, non-sublicensable, limited license. Such redistribution shall be limited to unlimited codebases.</li><li>
......
/**
* cordova-background-geolocation
* Copyright (c) 2015, Transistor Software (9224-2932 Quebec Inc)
* All rights reserved.
* sales@transistorsoft.com
* http://transistorsoft.com
* @see LICENSE
*/
var ENV = (function() { var ENV = (function() {
var localStorage = window.localStorage; var localStorage = window.localStorage;
...@@ -133,7 +141,7 @@ var app = { ...@@ -133,7 +141,7 @@ var app = {
* This callback will be executed every time a geolocation is recorded in the background. * This callback will be executed every time a geolocation is recorded in the background.
*/ */
var callbackFn = function(location) { var callbackFn = function(location) {
console.log('[js] BackgroundGeoLocation callback: ' + location.latitude + ',' + location.longitude); console.log('[js] BackgroundGeoLocation callback: ' + JSON.stringify(location));
// Update our current-position marker. // Update our current-position marker.
app.setCurrentLocation(location); app.setCurrentLocation(location);
...@@ -148,6 +156,7 @@ var app = { ...@@ -148,6 +156,7 @@ var app = {
// Only ios emits this stationary event // Only ios emits this stationary event
bgGeo.onStationary(function(location) { bgGeo.onStationary(function(location) {
console.log('[js] BackgroundGeoLocation onStationary ' + JSON.stringify(location));
if (!app.stationaryRadius) { if (!app.stationaryRadius) {
app.stationaryRadius = new google.maps.Circle({ app.stationaryRadius = new google.maps.Circle({
fillColor: '#cc0000', fillColor: '#cc0000',
...@@ -165,14 +174,14 @@ var app = { ...@@ -165,14 +174,14 @@ var app = {
// BackgroundGeoLocation is highly configurable. // BackgroundGeoLocation is highly configurable.
bgGeo.configure(callbackFn, failureFn, { bgGeo.configure(callbackFn, failureFn, {
desiredAccuracy: 0, // <-- 0: highest power, highest accuracy; 1000: lowest power, lowest accuracy. desiredAccuracy: 0,
stationaryRadius: 50, stationaryRadius: 50,
distanceFilter: 50, // <-- minimum distance between location events distanceFilter: 30,
activityType: 'AutomotiveNavigation', // <-- [ios] locationUpdateInterval: 30000,
locationUpdateInterval: 30000, // <-- [android] minimum time between location updates, used in conjunction with #distanceFilter activityRecognitionInterval: 10000,
activityRecognitionInterval: 10000, // <-- [android] sampling-rate activity-recognition system for movement/stationary detection activityType: 'AutomotiveNavigation',
debug: true, // <-- enable this hear sounds, see notifications during life-cycle events. debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
stopOnTerminate: false // <-- enable this to clear background location settings when the app terminates stopOnTerminate: false // <-- enable this to clear background location settings when the app terminates
}); });
// Turn ON the background-geolocation system. The user will be tracked whenever they suspend the app. // Turn ON the background-geolocation system. The user will be tracked whenever they suspend the app.
...@@ -347,4 +356,4 @@ var app = { ...@@ -347,4 +356,4 @@ var app = {
} }
}; };
app.initialize(); app.initialize();
\ No newline at end of file
...@@ -30,6 +30,13 @@ ...@@ -30,6 +30,13 @@
<config-file target="AndroidManifest.xml" parent="/manifest/application"> <config-file target="AndroidManifest.xml" parent="/manifest/application">
<service android:name="com.transistorsoft.cordova.bggeo.BackgroundGeolocationService" /> <service android:name="com.transistorsoft.cordova.bggeo.BackgroundGeolocationService" />
<!-- autorun on boot receiver -->
<receiver android:name="com.transistorsoft.cordova.bggeo.BootReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</config-file> </config-file>
<config-file target="AndroidManifest.xml" parent="/manifest"> <config-file target="AndroidManifest.xml" parent="/manifest">
...@@ -40,6 +47,10 @@ ...@@ -40,6 +47,10 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Autorun your app on device BOOT. REMOVE THIS LINE TO DISABLE AUTO-BOOT -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</config-file> </config-file>
<config-file target="res/xml/config.xml" parent="/*"> <config-file target="res/xml/config.xml" parent="/*">
<feature name="BackgroundGeoLocation"> <feature name="BackgroundGeoLocation">
......
...@@ -21,6 +21,9 @@ public class BackgroundGeolocationService extends IntentService { ...@@ -21,6 +21,9 @@ public class BackgroundGeolocationService extends IntentService {
@Override @Override
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
// Determine whether the fore-ground Activity is running. If it's not, we'll reboot it.
boolean isPluginActive = BackgroundGeolocationPlugin.isActive();
if (ActivityRecognitionResult.hasResult(intent)) { if (ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent); ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
DetectedActivity probableActivity = result.getMostProbableActivity(); DetectedActivity probableActivity = result.getMostProbableActivity();
...@@ -35,6 +38,7 @@ public class BackgroundGeolocationService extends IntentService { ...@@ -35,6 +38,7 @@ public class BackgroundGeolocationService extends IntentService {
case DetectedActivity.IN_VEHICLE: case DetectedActivity.IN_VEHICLE:
case DetectedActivity.ON_BICYCLE: case DetectedActivity.ON_BICYCLE:
case DetectedActivity.ON_FOOT: case DetectedActivity.ON_FOOT:
case DetectedActivity.WALKING:
case DetectedActivity.RUNNING: case DetectedActivity.RUNNING:
isMoving = true; isMoving = true;
break; break;
...@@ -46,17 +50,20 @@ public class BackgroundGeolocationService extends IntentService { ...@@ -46,17 +50,20 @@ public class BackgroundGeolocationService extends IntentService {
break; break;
} }
boolean isPushPluginActive = BackgroundGeolocationPlugin.isActive(); // Force main-activity reload (if not running) if we're detected to be moving.
if (isMoving && !isPushPluginActive) { if (isMoving && !isPluginActive) {
forceMainActivityReload(); forceMainActivityReload();
} }
// Post activity to the bus.
EventBus.getDefault().post(probableActivity); EventBus.getDefault().post(probableActivity);
} else { } else {
final Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED); final Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
if (location != null) { if (location != null) {
Log.i(TAG, "Location received: " + location.toString()); Log.i(TAG, "Location received: " + location.toString());
boolean isPushPluginActive = BackgroundGeolocationPlugin.isActive();
if (!isPushPluginActive) { // Force main-activity reload when a location comes in.
if (!isPluginActive) {
forceMainActivityReload(); forceMainActivityReload();
} }
EventBus.getDefault().post(location); EventBus.getDefault().post(location);
...@@ -64,26 +71,34 @@ public class BackgroundGeolocationService extends IntentService { ...@@ -64,26 +71,34 @@ public class BackgroundGeolocationService extends IntentService {
} }
} }
/**
* This method has no other purpose than formatting the Activity for log-messages
*/
private String getActivityName(int activityType) { private String getActivityName(int activityType) {
switch (activityType) { switch (activityType) {
case DetectedActivity.IN_VEHICLE: case DetectedActivity.IN_VEHICLE:
return "in_vehicle"; return "in_vehicle";
case DetectedActivity.ON_BICYCLE: case DetectedActivity.ON_BICYCLE:
return "on_bicycle"; return "on_bicycle";
case DetectedActivity.ON_FOOT: case DetectedActivity.ON_FOOT:
return "on_foot"; return "on_foot";
case DetectedActivity.STILL: case DetectedActivity.RUNNING:
return "still"; return "running";
case DetectedActivity.UNKNOWN: case DetectedActivity.WALKING:
return "unknown"; return "walking";
case DetectedActivity.TILTING: case DetectedActivity.STILL:
return "tilting"; return "still";
} case DetectedActivity.UNKNOWN:
return "unknown"; return "unknown";
} case DetectedActivity.TILTING:
return "tilting";
}
return "unknown";
}
/** /**
* Forces the main activity to re-launch if it's unloaded. * Forces the main activity to re-launch if it's unloaded. This is how we're able to rely upon Javascript
* running always, since we for the app to boot.
*/ */
private void forceMainActivityReload() { private void forceMainActivityReload() {
Log.w(TAG, "- Forcing main-activity reload"); Log.w(TAG, "- Forcing main-activity reload");
......
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
*
*/
public class BootReceiver extends BroadcastReceiver implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "BackgroundGeolocation";
private GoogleApiClient googleApiClient;
private PendingIntent locationUpdateService;
private Integer activityRecognitionInterval = 10000;
private PendingResult pendingResult;
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "- BootReceiver auto-running ActivityRecognition system");
// GoogleApiClient connection is asynchronous process. @see #onConnected
pendingResult = goAsync();
// 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");
}
// This is the IntentService we'll provide to google-play API.
locationUpdateService = PendingIntent.getService(context, 0, new Intent(context, BackgroundGeolocationService.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
private void requestActivityUpdates() {
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(googleApiClient, activityRecognitionInterval, locationUpdateService);
}
@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
/**
* cordova-background-geolocation
* Copyright (c) 2015, Transistor Software (9224-2932 Quebec Inc)
* All rights reserved.
* sales@transistorsoft.com
* http://transistorsoft.com
* @see LICENSE
*/
var exec = require("cordova/exec"); var exec = require("cordova/exec");
module.exports = { module.exports = {
/** /**
......
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