re-worked the resume functionality
This commit is contained in:
parent
8264a2b2af
commit
dd13d1f462
8 changed files with 125 additions and 289 deletions
5
app/proguard-rules.pro
vendored
5
app/proguard-rules.pro
vendored
|
@ -15,8 +15,3 @@
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
# public *;
|
# public *;
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
|
||||||
# needed for osmdroid v5.6.5 if using SDK version 26 TODO remove as soom as osmdroid v5.6.6 is released
|
|
||||||
# see https://github.com/osmdroid/osmdroid/issues/633
|
|
||||||
# -dontwarn org.osmdroid.tileprovider.modules.NetworkAvailabliltyCheck
|
|
||||||
|
|
|
@ -178,14 +178,15 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
|
// unbind from TrackerService
|
||||||
unbindService(mConnection);
|
unbindService(mConnection);
|
||||||
mBound = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,14 +270,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Request the current Track from TrackerService */
|
|
||||||
public void requestTrack() {
|
|
||||||
if (mBound) {
|
|
||||||
mTrackerService.sendTrackUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Handles the visual state after a save action */
|
/* Handles the visual state after a save action */
|
||||||
private void handleStateAfterSave() {
|
private void handleStateAfterSave() {
|
||||||
// display and update tracks tab
|
// display and update tracks tab
|
||||||
|
|
|
@ -225,19 +225,25 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
|
||||||
// load state of tracker service - see if anything changed
|
// load state of tracker service - see if anything changed
|
||||||
loadTrackerServiceState(mActivity);
|
loadTrackerServiceState(mActivity);
|
||||||
|
|
||||||
// CASE 1: recording active
|
|
||||||
if (mTrackerServiceRunning) {
|
|
||||||
// request an updated track recording from service
|
|
||||||
((MainActivity)mActivity).requestTrack();
|
|
||||||
}
|
|
||||||
|
|
||||||
// CASE 2: recording stopped - temp file exists
|
|
||||||
else if (mStorageHelper.tempFileExists()) {
|
|
||||||
// load track from temp file if it exists
|
// load track from temp file if it exists
|
||||||
|
if (mStorageHelper.tempFileExists()) {
|
||||||
LoadTempTrackAsyncHelper loadTempTrackAsyncHelper = new LoadTempTrackAsyncHelper();
|
LoadTempTrackAsyncHelper loadTempTrackAsyncHelper = new LoadTempTrackAsyncHelper();
|
||||||
loadTempTrackAsyncHelper.execute();
|
loadTempTrackAsyncHelper.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // CASE 1: recording active
|
||||||
|
// if (mTrackerServiceRunning) {
|
||||||
|
// // request an updated track recording from service
|
||||||
|
// ((MainActivity)mActivity).requestTrack();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // CASE 2: recording stopped - temp file exists
|
||||||
|
// else if (mStorageHelper.tempFileExists()) {
|
||||||
|
// // load track from temp file if it exists
|
||||||
|
// LoadTempTrackAsyncHelper loadTempTrackAsyncHelper = new LoadTempTrackAsyncHelper();
|
||||||
|
// loadTempTrackAsyncHelper.execute();
|
||||||
|
// }
|
||||||
|
|
||||||
// // CASE 3: not recording and no temp file
|
// // CASE 3: not recording and no temp file
|
||||||
// else if (mTrack != null) {
|
// else if (mTrack != null) {
|
||||||
// // just draw existing track data (from saved instance)
|
// // just draw existing track data (from saved instance)
|
||||||
|
@ -551,7 +557,6 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.hasExtra(EXTRA_TRACK) && intent.hasExtra(EXTRA_LAST_LOCATION)) {
|
if (intent.hasExtra(EXTRA_TRACK) && intent.hasExtra(EXTRA_LAST_LOCATION)) {
|
||||||
LogHelper.v(LOG_TAG, "Track update received.");
|
|
||||||
// draw track on map
|
// draw track on map
|
||||||
mTrack = intent.getParcelableExtra(EXTRA_TRACK);
|
mTrack = intent.getParcelableExtra(EXTRA_TRACK);
|
||||||
drawTrackOverlay(mTrack);
|
drawTrackOverlay(mTrack);
|
||||||
|
|
|
@ -37,7 +37,6 @@ import android.os.CountDownTimer;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -51,7 +50,6 @@ import org.y20k.trackbook.helpers.StorageHelper;
|
||||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import static android.hardware.Sensor.TYPE_STEP_COUNTER;
|
import static android.hardware.Sensor.TYPE_STEP_COUNTER;
|
||||||
|
|
||||||
|
@ -115,17 +113,14 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onUnbind(Intent intent) {
|
public boolean onUnbind(Intent intent) {
|
||||||
// All clients have unbound with unbindService()
|
// return true if you would like to have the service's onRebind(Intent) method later called when new clients bind to it.
|
||||||
// return mAllowRebind; // todo change
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRebind(Intent intent) {
|
public void onRebind(Intent intent) {
|
||||||
// A client is binding to the service with bindService(),
|
// a client is binding to the service with bindService(), after onUnbind() has already been called
|
||||||
// after onUnbind() has already been called
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,68 +136,11 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
resumeTracking();
|
resumeTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
// // check if user did turn off location in device settings
|
|
||||||
// if (!mLocationSystemSetting) {
|
|
||||||
// LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
|
||||||
// Toast.makeText(getApplicationContext(), R.string.toast_message_location_offline, Toast.LENGTH_LONG).show();
|
|
||||||
// stopTracking();
|
|
||||||
// return START_STICKY;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // RESTART CHECK: checking for empty intent - try to get saved track
|
|
||||||
// if (intent == null || intent.getAction() == null) {
|
|
||||||
// LogHelper.w(LOG_TAG, "Null-Intent received. Trying to restart tracking.");
|
|
||||||
// startTracking(intent, false);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ACTION START
|
|
||||||
// else if (intent.getAction().equals(ACTION_START) && mLocationSystemSetting) {
|
|
||||||
// startTracking(intent, true);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ACTION RESUME
|
|
||||||
// else if (intent.getAction().equals(ACTION_RESUME) && mLocationSystemSetting) {
|
|
||||||
// startTracking(intent, false);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ACTION STOP
|
|
||||||
// else if (intent.getAction().equals(ACTION_STOP) || !mLocationSystemSetting) {
|
|
||||||
// mTrackerServiceRunning = false;
|
|
||||||
// if (mTrack != null && mTimer != null) {
|
|
||||||
// stopTracking();
|
|
||||||
// } else {
|
|
||||||
// // handle error - save state
|
|
||||||
// saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ACTION DISMISS
|
|
||||||
// else if (intent.getAction().equals(ACTION_DISMISS)) {
|
|
||||||
// // save state
|
|
||||||
// saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
|
|
||||||
// // dismiss notification
|
|
||||||
// mNotificationManager.cancel(TRACKER_SERVICE_NOTIFICATION_ID); // todo check if necessary?
|
|
||||||
// stopForeground(true);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ACTION TRACK REQUEST
|
|
||||||
// else if (intent.getAction().equals(ACTION_TRACK_REQUEST)) {
|
|
||||||
// // send track via broadcast
|
|
||||||
// sendTrackUpdate();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// START_STICKY is used for services that are explicitly started and stopped as needed
|
// START_STICKY is used for services that are explicitly started and stopped as needed
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Nullable
|
|
||||||
// @Override
|
|
||||||
// public IBinder onBind(Intent intent) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
LogHelper.v(LOG_TAG, "onDestroy called.");
|
LogHelper.v(LOG_TAG, "onDestroy called.");
|
||||||
|
@ -258,7 +196,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
mStepCountOffset = 0;
|
mStepCountOffset = 0;
|
||||||
|
|
||||||
// begin recording
|
// begin recording
|
||||||
recordMovements();
|
startMovementRecording();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
||||||
|
@ -299,7 +237,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
mStepCountOffset = mTrack.getStepCount();
|
mStepCountOffset = mTrack.getStepCount();
|
||||||
|
|
||||||
// begin recording
|
// begin recording
|
||||||
recordMovements();
|
startMovementRecording();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
||||||
|
@ -308,185 +246,17 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Record movements */
|
|
||||||
private void recordMovements() {
|
|
||||||
// add last location as WayPoint to track
|
|
||||||
addWayPointToTrack();
|
|
||||||
|
|
||||||
// put up notification
|
|
||||||
displayNotification(true);
|
|
||||||
|
|
||||||
// create gps and network location listeners
|
|
||||||
startFindingLocation();
|
|
||||||
|
|
||||||
// start timer that periodically request a location update
|
|
||||||
startIntervalTimer();
|
|
||||||
|
|
||||||
// start counting steps
|
|
||||||
startStepCounter();
|
|
||||||
|
|
||||||
// register content observer for changes in System Settings
|
|
||||||
this.getContentResolver().registerContentObserver(android.provider.Settings.Secure.CONTENT_URI, true, mSettingsContentObserver);
|
|
||||||
|
|
||||||
// start service in foreground
|
|
||||||
startForeground(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void startStepCounter() {
|
|
||||||
boolean stepCounterAvailable;
|
|
||||||
stepCounterAvailable = mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI);
|
|
||||||
if (stepCounterAvailable) {
|
|
||||||
LogHelper.v(LOG_TAG, "Pedometer sensor available: Registering listener.");
|
|
||||||
} else {
|
|
||||||
LogHelper.i(LOG_TAG, "Pedometer sensor not available.");
|
|
||||||
mTrack.setStepCount(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Set timer to retrieve new locations and to prevent endless tracking */
|
|
||||||
private void startIntervalTimer() {
|
|
||||||
mTimer = new CountDownTimer(EIGHT_HOURS_IN_MILLISECONDS, FIFTEEN_SECONDS_IN_MILLISECONDS) {
|
|
||||||
@Override
|
|
||||||
public void onTick(long millisUntilFinished) {
|
|
||||||
// update track duration - and add duration from previously interrupted / paused session
|
|
||||||
long previouslyRecordedDuration = mTrack.getTrackDuration();
|
|
||||||
long duration = EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished + previouslyRecordedDuration;
|
|
||||||
mTrack.setDuration(duration);
|
|
||||||
// try to add WayPoint to Track
|
|
||||||
addWayPointToTrack();
|
|
||||||
// update notification
|
|
||||||
|
|
||||||
mNotification = NotificationHelper.getUpdatedNotification(TrackerService.this, mNotificationBuilder, mTrack);
|
|
||||||
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
|
||||||
// save a temp file in case the service has been killed by the system
|
|
||||||
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
|
|
||||||
saveTempTrackAsyncHelper.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
// stop tracking after eight hours
|
|
||||||
stopTracking();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mTimer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Display notification */
|
|
||||||
private void displayNotification(boolean trackingState) {
|
|
||||||
mNotificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL);
|
|
||||||
mNotification = NotificationHelper.getNotification(this, mNotificationBuilder, mTrack, trackingState);
|
|
||||||
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification); // todo check if necessary in pre Android O
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Start tracking location */ // todo remove
|
|
||||||
private void startTracking(@Nullable Intent intent, boolean createNewTrack) {
|
|
||||||
LogHelper.v(LOG_TAG, "Service received command: START");
|
|
||||||
|
|
||||||
// create a new track - if requested
|
|
||||||
if (createNewTrack) {
|
|
||||||
mTrack = new Track();
|
|
||||||
} else {
|
|
||||||
StorageHelper storageHelper = new StorageHelper(this);
|
|
||||||
if (storageHelper.tempFileExists()) {
|
|
||||||
// load temp track file
|
|
||||||
mTrack = storageHelper.loadTrack(FILE_TEMP_TRACK);
|
|
||||||
// try to mark last waypoint as stopover
|
|
||||||
int lastWayPoint = mTrack.getWayPoints().size() - 1;
|
|
||||||
if (lastWayPoint >= 0) {
|
|
||||||
mTrack.getWayPoints().get(lastWayPoint).setIsStopOver(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// fallback, if tempfile did not exist
|
|
||||||
LogHelper.e(LOG_TAG, "Unable to find previously saved track temp file.");
|
|
||||||
mTrack = new Track();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get last location
|
|
||||||
if (intent != null && ACTION_START.equals(intent.getAction()) && intent.hasExtra(EXTRA_LAST_LOCATION)) {
|
|
||||||
// received START intent and last location - unpack last location
|
|
||||||
mCurrentBestLocation = intent.getParcelableExtra(EXTRA_LAST_LOCATION);
|
|
||||||
} else if (ACTION_RESUME.equals(intent.getAction()) && mTrack.getSize() > 0) {
|
|
||||||
// received RESUME intent - use last waypoint
|
|
||||||
mCurrentBestLocation = mTrack.getWayPointLocation(mTrack.getSize() -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get last location - fallback
|
|
||||||
if (mCurrentBestLocation == null) {
|
|
||||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add last location as WayPoint to track
|
|
||||||
addWayPointToTrack();
|
|
||||||
|
|
||||||
// put up notification
|
|
||||||
mNotificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL);
|
|
||||||
mNotification = NotificationHelper.getNotification(this, mNotificationBuilder, mTrack, true);
|
|
||||||
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification); // todo check if necessary in pre Android O
|
|
||||||
|
|
||||||
// get duration of previously recorded track - in case this service has been restarted / resumed
|
|
||||||
final long previouslyRecordedDuration = mTrack.getTrackDuration();
|
|
||||||
|
|
||||||
// set timer to retrieve new locations and to prevent endless tracking
|
|
||||||
mTimer = new CountDownTimer(EIGHT_HOURS_IN_MILLISECONDS, FIFTEEN_SECONDS_IN_MILLISECONDS) {
|
|
||||||
@Override
|
|
||||||
public void onTick(long millisUntilFinished) {
|
|
||||||
// update track duration - and add duration from previously interrupted / paused session
|
|
||||||
long duration = EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished + previouslyRecordedDuration;
|
|
||||||
mTrack.setDuration(duration);
|
|
||||||
// try to add WayPoint to Track
|
|
||||||
addWayPointToTrack();
|
|
||||||
// update notification
|
|
||||||
mNotification = NotificationHelper.getUpdatedNotification(TrackerService.this, mNotificationBuilder, mTrack);
|
|
||||||
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
|
||||||
// save a temp file in case the service has been killed by the system
|
|
||||||
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
|
|
||||||
saveTempTrackAsyncHelper.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
// stop tracking after eight hours
|
|
||||||
stopTracking();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mTimer.start();
|
|
||||||
|
|
||||||
// initialize step counter
|
|
||||||
mStepCountOffset = 0;
|
|
||||||
|
|
||||||
boolean stepCounterAvailable;
|
|
||||||
stepCounterAvailable = mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI);
|
|
||||||
if (stepCounterAvailable) {
|
|
||||||
LogHelper.v(LOG_TAG, "Pedometer sensor available: Registering listener.");
|
|
||||||
} else {
|
|
||||||
LogHelper.i(LOG_TAG, "Pedometer sensor not available.");
|
|
||||||
mTrack.setStepCount(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create gps and network location listeners
|
|
||||||
startFindingLocation();
|
|
||||||
|
|
||||||
// register content observer for changes in System Settings
|
|
||||||
this.getContentResolver().registerContentObserver(android.provider.Settings.Secure.CONTENT_URI, true, mSettingsContentObserver);
|
|
||||||
|
|
||||||
// start service in foreground
|
|
||||||
startForeground(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Stop tracking location */
|
/* Stop tracking location */
|
||||||
public void stopTracking() {
|
public void stopTracking() {
|
||||||
LogHelper.v(LOG_TAG, "Recording stopped");
|
LogHelper.v(LOG_TAG, "Recording stopped");
|
||||||
|
|
||||||
|
// catches a bug that leaves the ui in a incorrect state after a crash
|
||||||
|
if (!mTrackerServiceRunning) {
|
||||||
|
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_SAVE);
|
||||||
|
broadcastTrackingStateChange();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// store current date and time
|
// store current date and time
|
||||||
mTrack.setRecordingEnd();
|
mTrack.setRecordingEnd();
|
||||||
|
|
||||||
|
@ -494,7 +264,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
mTimer.cancel();
|
mTimer.cancel();
|
||||||
|
|
||||||
// broadcast an updated track
|
// broadcast an updated track
|
||||||
sendTrackUpdate();
|
broadcastTrackUpdate();
|
||||||
|
|
||||||
// save a temp file in case the activity has been killed
|
// save a temp file in case the activity has been killed
|
||||||
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
|
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
|
||||||
|
@ -525,6 +295,80 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Starts to record movements */
|
||||||
|
private void startMovementRecording() {
|
||||||
|
// add last location as WayPoint to track
|
||||||
|
addWayPointToTrack();
|
||||||
|
|
||||||
|
// put up notification
|
||||||
|
displayNotification(true);
|
||||||
|
|
||||||
|
// create gps and network location listeners
|
||||||
|
startFindingLocation();
|
||||||
|
|
||||||
|
// start timer that periodically request a location update
|
||||||
|
startRequestingLocationChanges();
|
||||||
|
|
||||||
|
// start counting steps
|
||||||
|
startStepCounter();
|
||||||
|
|
||||||
|
// register content observer for changes in System Settings
|
||||||
|
this.getContentResolver().registerContentObserver(android.provider.Settings.Secure.CONTENT_URI, true, mSettingsContentObserver);
|
||||||
|
|
||||||
|
// start service in foreground
|
||||||
|
startForeground(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Registers a step counter listener */
|
||||||
|
private void startStepCounter() {
|
||||||
|
boolean stepCounterAvailable;
|
||||||
|
stepCounterAvailable = mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI);
|
||||||
|
if (stepCounterAvailable) {
|
||||||
|
LogHelper.v(LOG_TAG, "Pedometer sensor available: Registering listener.");
|
||||||
|
} else {
|
||||||
|
LogHelper.i(LOG_TAG, "Pedometer sensor not available.");
|
||||||
|
mTrack.setStepCount(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Set timer to periodically retrieve new locations and to prevent endless tracking */
|
||||||
|
private void startRequestingLocationChanges() {
|
||||||
|
final long previouslyRecordedDuration = mTrack.getTrackDuration();
|
||||||
|
mTimer = new CountDownTimer(EIGHT_HOURS_IN_MILLISECONDS, FIFTEEN_SECONDS_IN_MILLISECONDS) {
|
||||||
|
@Override
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
// update track duration - and add duration from previously interrupted / paused session
|
||||||
|
long duration = EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished + previouslyRecordedDuration;
|
||||||
|
mTrack.setDuration(duration);
|
||||||
|
// try to add WayPoint to Track
|
||||||
|
addWayPointToTrack();
|
||||||
|
// update notification
|
||||||
|
mNotification = NotificationHelper.getUpdatedNotification(TrackerService.this, mNotificationBuilder, mTrack);
|
||||||
|
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
||||||
|
// save a temp file in case the service has been killed by the system
|
||||||
|
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
|
||||||
|
saveTempTrackAsyncHelper.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
// stop tracking after eight hours
|
||||||
|
stopTracking();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Display notification */
|
||||||
|
private void displayNotification(boolean trackingState) {
|
||||||
|
mNotificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL);
|
||||||
|
mNotification = NotificationHelper.getNotification(this, mNotificationBuilder, mTrack, trackingState);
|
||||||
|
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification); // todo check if necessary in pre Android O
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Adds a new WayPoint to current track */
|
/* Adds a new WayPoint to current track */
|
||||||
private void addWayPointToTrack() {
|
private void addWayPointToTrack() {
|
||||||
|
@ -550,7 +394,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
Location firstWayPoint = mTrack.getWayPointLocation(0);
|
Location firstWayPoint = mTrack.getWayPointLocation(0);
|
||||||
float distance = firstWayPoint.distanceTo(lastWayPoint);
|
float distance = firstWayPoint.distanceTo(lastWayPoint);
|
||||||
long timeDifference = lastWayPoint.getElapsedRealtimeNanos() - firstWayPoint.getElapsedRealtimeNanos();
|
long timeDifference = lastWayPoint.getElapsedRealtimeNanos() - firstWayPoint.getElapsedRealtimeNanos();
|
||||||
averageSpeed = distance / ((float) timeDifference / ONE_NANOSECOND);
|
averageSpeed = distance / ((float) timeDifference / ONE_SECOND_IN_NANOSECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocationHelper.isNewWayPoint(lastWayPoint, mCurrentBestLocation, averageSpeed)) {
|
if (LocationHelper.isNewWayPoint(lastWayPoint, mCurrentBestLocation, averageSpeed)) {
|
||||||
|
@ -561,14 +405,14 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
|
|
||||||
// send local broadcast if new WayPoint added
|
// send local broadcast if new WayPoint added
|
||||||
if (newWayPoint != null) {
|
if (newWayPoint != null) {
|
||||||
sendTrackUpdate();
|
broadcastTrackUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Broadcasts a track update */
|
/* Broadcasts a track update */
|
||||||
public void sendTrackUpdate() {
|
private void broadcastTrackUpdate() {
|
||||||
if (mTrack != null) {
|
if (mTrack != null) {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setAction(ACTION_TRACK_UPDATED);
|
i.setAction(ACTION_TRACK_UPDATED);
|
||||||
|
|
|
@ -143,7 +143,7 @@ public final class LocationHelper implements TrackbookKeys {
|
||||||
if (newLocation.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
|
if (newLocation.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
|
||||||
// calculate speed difference
|
// calculate speed difference
|
||||||
float speedDifference;
|
float speedDifference;
|
||||||
float currentSpeed = distance / ((float)timeDifference / ONE_NANOSECOND);
|
float currentSpeed = distance / ((float)timeDifference / ONE_SECOND_IN_NANOSECOND);
|
||||||
if (currentSpeed > averageSpeed) {
|
if (currentSpeed > averageSpeed) {
|
||||||
speedDifference = currentSpeed / averageSpeed;
|
speedDifference = currentSpeed / averageSpeed;
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,11 +163,11 @@ public final class LocationHelper implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEFAULT network: distance is bigger than 30 meters and time difference bigger than 12 seconds
|
// DEFAULT network: distance is bigger than 30 meters and time difference bigger than 12 seconds
|
||||||
return distance > 30 && timeDifference >= 12 * ONE_NANOSECOND; // TODO add minimal accuracy
|
return distance > 30 && timeDifference >= 12 * ONE_SECOND_IN_NANOSECOND; // TODO add minimal accuracy
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// DEFAULT GPS: distance is bigger than 10 meters and time difference bigger than 12 seconds
|
// DEFAULT GPS: distance is bigger than 10 meters and time difference bigger than 12 seconds
|
||||||
return distance > 10 && timeDifference >= 12 * ONE_NANOSECOND;
|
return distance > 10 && timeDifference >= 12 * ONE_SECOND_IN_NANOSECOND;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,6 @@ public final class NotificationHelper implements TrackbookKeys {
|
||||||
// create notification channel
|
// create notification channel
|
||||||
createNotificationChannel(context);
|
createNotificationChannel(context);
|
||||||
|
|
||||||
// build context text for notification builder
|
|
||||||
String contentText = getContextString(context, track);
|
|
||||||
|
|
||||||
// ACTION: NOTIFICATION TAP & BUTTON SHOW
|
// ACTION: NOTIFICATION TAP & BUTTON SHOW
|
||||||
Intent tapActionIntent = new Intent(context, MainActivity.class);
|
Intent tapActionIntent = new Intent(context, MainActivity.class);
|
||||||
tapActionIntent.setAction(ACTION_SHOW_MAP);
|
tapActionIntent.setAction(ACTION_SHOW_MAP);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.y20k.trackbook.helpers;
|
package org.y20k.trackbook.helpers;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.location.Location;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.os.EnvironmentCompat;
|
import android.support.v4.os.EnvironmentCompat;
|
||||||
|
@ -369,8 +370,8 @@ public class StorageHelper implements TrackbookKeys {
|
||||||
double negativeElevation = 0;
|
double negativeElevation = 0;
|
||||||
|
|
||||||
if (track != null && track.getWayPoints().size() > 0) {
|
if (track != null && track.getWayPoints().size() > 0) {
|
||||||
double previousLocationHeight;
|
double previousLocationAltitude;
|
||||||
double currentLocationHeight;
|
double currentLocationAltitude;
|
||||||
long previousTimeStamp;
|
long previousTimeStamp;
|
||||||
long currentTimeStamp;
|
long currentTimeStamp;
|
||||||
|
|
||||||
|
@ -379,7 +380,7 @@ public class StorageHelper implements TrackbookKeys {
|
||||||
minAltitude = maxAltitude;
|
minAltitude = maxAltitude;
|
||||||
|
|
||||||
// apply filter & smooth data
|
// apply filter & smooth data
|
||||||
// track = lowPass(track, 15f, 35f);
|
// track = smoothTrack(track, 15f, 35f);
|
||||||
|
|
||||||
// iterate over track
|
// iterate over track
|
||||||
for (int i = 1; i < track.getWayPoints().size(); i++ ) {
|
for (int i = 1; i < track.getWayPoints().size(); i++ ) {
|
||||||
|
@ -393,23 +394,23 @@ public class StorageHelper implements TrackbookKeys {
|
||||||
double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS;
|
double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS;
|
||||||
|
|
||||||
// height of previous and current waypoints
|
// height of previous and current waypoints
|
||||||
previousLocationHeight = track.getWayPointLocation(i -1).getAltitude();
|
previousLocationAltitude = track.getWayPointLocation(i -1).getAltitude();
|
||||||
currentLocationHeight = track.getWayPointLocation(i).getAltitude();
|
currentLocationAltitude = track.getWayPointLocation(i).getAltitude();
|
||||||
|
|
||||||
// check for new min and max heights
|
// check for new min and max heights
|
||||||
if (currentLocationHeight > maxAltitude) {
|
if (currentLocationAltitude > maxAltitude) {
|
||||||
maxAltitude = currentLocationHeight;
|
maxAltitude = currentLocationAltitude;
|
||||||
}
|
}
|
||||||
if (minAltitude == 0 || currentLocationHeight < minAltitude) {
|
if (minAltitude == 0 || currentLocationAltitude < minAltitude) {
|
||||||
minAltitude = currentLocationHeight;
|
minAltitude = currentLocationAltitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get elevation difference and sum it up
|
// get elevation difference and sum it up
|
||||||
double altitudeDiff = currentLocationHeight - previousLocationHeight;
|
double altitudeDiff = currentLocationAltitude - previousLocationAltitude;
|
||||||
if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) {
|
if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
|
||||||
positiveElevation = positiveElevation + altitudeDiff;
|
positiveElevation = positiveElevation + altitudeDiff;
|
||||||
}
|
}
|
||||||
if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationHeight != 0) {
|
if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
|
||||||
negativeElevation = negativeElevation + altitudeDiff;
|
negativeElevation = negativeElevation + altitudeDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,8 +425,9 @@ public class StorageHelper implements TrackbookKeys {
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Tries to smooth the elevation data using a low pass filter */
|
/* Tries to smooth the elevation data using a low pass filter */
|
||||||
private Track lowPass(Track input, float dt, float rc) {
|
private Track smoothTrack(Track input, float dt, float rc) {
|
||||||
|
|
||||||
// The following code is adapted from https://en.wikipedia.org/wiki/Low-pass_filter
|
// The following code is adapted from https://en.wikipedia.org/wiki/Low-pass_filter
|
||||||
//
|
//
|
||||||
|
|
|
@ -86,7 +86,7 @@ public interface TrackbookKeys {
|
||||||
int RESULT_EXPORT_DIALOG = 4;
|
int RESULT_EXPORT_DIALOG = 4;
|
||||||
|
|
||||||
/* CONSTANTS */
|
/* CONSTANTS */
|
||||||
long ONE_NANOSECOND = 1000000000L;
|
long ONE_SECOND_IN_NANOSECOND = 1000000000L;
|
||||||
long EIGHT_HOURS_IN_MILLISECONDS = 43200000; // maximum tracking duration
|
long EIGHT_HOURS_IN_MILLISECONDS = 43200000; // maximum tracking duration
|
||||||
long FIFTEEN_SECONDS_IN_MILLISECONDS = 15000; // timer interval for tracking
|
long FIFTEEN_SECONDS_IN_MILLISECONDS = 15000; // timer interval for tracking
|
||||||
long FIVE_MINUTES_IN_NANOSECONDS = 5L * 60000000000L; // determines a stop over
|
long FIVE_MINUTES_IN_NANOSECONDS = 5L * 60000000000L; // determines a stop over
|
||||||
|
|
Loading…
Reference in a new issue