making trackerservice resumable (see #29)

master
y20k 2018-01-21 22:28:32 +01:00
parent db1e70c370
commit 707c02a092
7 changed files with 116 additions and 48 deletions

View File

@ -249,9 +249,13 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
mBottomNavigationView.setSelectedItemId(R.id.navigation_last_tracks);
// dismiss notification
Intent intent = new Intent(this, TrackerService.class);
intent.setAction(ACTION_DISMISS);
startService(intent);
startTrackerService(ACTION_DISMISS, null);
// Intent intent = new Intent(this, TrackerService.class);
// intent.setAction(ACTION_DISMISS);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// startForegroundService(intent);
// }
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
@ -262,15 +266,37 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
}
/* Start/stop tracker service */
private void startTrackerService(String intentAction, @Nullable Location lastLocation) {
// build intent
Intent intent = new Intent(this, TrackerService.class);
intent.setAction(intentAction);
if (lastLocation != null && intentAction.equals(ACTION_START)) {
intent.putExtra(EXTRA_LAST_LOCATION, lastLocation);
}
// start service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// ... in foreground to prevent it being killed on Oreo
startForegroundService(intent);
} else {
startService(intent);
}
}
/* Handles the visual state after a save action */
private void handleStateAfterClear() {
// notify user
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
// dismiss notification
Intent intent = new Intent(this, TrackerService.class);
intent.setAction(ACTION_DISMISS);
startService(intent);
startTrackerService(ACTION_DISMISS, null);
// Intent intent = new Intent(this, TrackerService.class); // todo remove
// intent.setAction(ACTION_DISMISS);
// startService(intent);
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
@ -446,14 +472,16 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
if (lastLocation != null) {
// start tracker service
Intent intent = new Intent(this, TrackerService.class);
intent.setAction(ACTION_START);
intent.putExtra(EXTRA_LAST_LOCATION, lastLocation);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}
startTrackerService(ACTION_START, lastLocation);
// Intent intent = new Intent(this, TrackerService.class); // todo remove
// intent.setAction(ACTION_START);
// intent.putExtra(EXTRA_LAST_LOCATION, lastLocation);
// if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
// startForegroundService(intent);
// } else {
// startService(intent);
// }
} else {
Toast.makeText(this, getString(R.string.toast_message_location_services_not_ready), Toast.LENGTH_LONG).show();
@ -472,9 +500,11 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
// --> is handled by broadcast receiver
// stop tracker service
Intent intent = new Intent(this, TrackerService.class);
intent.setAction(ACTION_STOP);
startService(intent);
startTrackerService(ACTION_STOP, null);
// Intent intent = new Intent(this, TrackerService.class); // todo remove
// intent.setAction(ACTION_STOP);
// startService(intent);
break;

View File

@ -353,10 +353,10 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
}
// populate views
mDistanceView.setText(mTrack.getTrackDistance());
mDistanceView.setText(mTrack.getTrackDistanceString());
mStepsView.setText(stepsTaken);
mWaypointsView.setText(String.valueOf(mTrack.getWayPoints().size()));
mDurationView.setText(mTrack.getTrackDuration());
mDurationView.setText(mTrack.getTrackDurationString());
mRecordingStartView.setText(recordingStart);
mRecordingStopView.setText(recordingStop);
@ -480,7 +480,7 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
int dialogNegativeButton = R.string.dialog_default_action_cancel;
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault());
String recordingStartDate = df.format(mTrack.getRecordingStart());
String dialogMessage = getString(R.string.dialog_delete_content) + " " + recordingStartDate + " | " + mTrack.getTrackDistance();
String dialogMessage = getString(R.string.dialog_delete_content) + " " + recordingStartDate + " | " + mTrack.getTrackDistanceString();
// show delete dialog - results are handles by onActivityResult
DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton);
@ -511,13 +511,13 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
if (exportHelper.gpxFileExists(mTrack)) {
// CASE: OVERWRITE - GPX file exists
dialogTitle = R.string.dialog_export_title_overwrite;
dialogMessage = getString(R.string.dialog_export_content_overwrite) + " (" + recordingStartDate + " | " + mTrack.getTrackDistance() + ")";
dialogMessage = getString(R.string.dialog_export_content_overwrite) + " (" + recordingStartDate + " | " + mTrack.getTrackDistanceString() + ")";
dialogPositiveButton = R.string.dialog_export_action_overwrite;
dialogNegativeButton = R.string.dialog_default_action_cancel;
} else {
// CASE: EXPORT - GPX file does NOT yet exits
dialogTitle = R.string.dialog_export_title_export;
dialogMessage = getString(R.string.dialog_export_content_export) + " (" + recordingStartDate + " | " + mTrack.getTrackDistance() + ")";
dialogMessage = getString(R.string.dialog_export_content_export) + " (" + recordingStartDate + " | " + mTrack.getTrackDistanceString() + ")";
dialogPositiveButton = R.string.dialog_export_action_export;
dialogNegativeButton = R.string.dialog_default_action_cancel;
}

View File

@ -16,6 +16,7 @@
package org.y20k.trackbook;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
@ -49,6 +50,7 @@ import org.y20k.trackbook.helpers.NotificationHelper;
import org.y20k.trackbook.helpers.StorageHelper;
import org.y20k.trackbook.helpers.TrackbookKeys;
import java.util.Iterator;
import java.util.List;
@ -111,16 +113,20 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
return START_STICKY;
}
// checking for empty intent
// RESTART CHECK: checking for empty intent - try to get saved track
if (intent == null || intent.getAction() == null) {
LogHelper.e(LOG_TAG, "Null-Intent received. Stopping self.");
// stopSelf triggers onDestroy
stopSelf();
LogHelper.e(LOG_TAG, "Null-Intent received. Are we being restarted?");
StorageHelper storageHelper = new StorageHelper(this);
if (storageHelper.tempFileExists()) {
mTrack = storageHelper.loadTrack(FILE_TEMP_TRACK);
// restart tracking
startTracking(intent, false);
}
}
// ACTION START
else if (intent.getAction().equals(ACTION_START) && mLocationSystemSetting) {
startTracking(intent);
startTracking(intent, true);
}
// ACTION STOP
@ -130,14 +136,14 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
stopTracking();
} else {
// handle error - save state
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
saveTrackerServiceState(mTrackerServiceRunning, 0, FAB_STATE_DEFAULT);
}
}
// ACTION DISMISS
else if (intent.getAction().equals(ACTION_DISMISS)) {
// save state
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
saveTrackerServiceState(mTrackerServiceRunning, mTrack.getTrackDuration(), FAB_STATE_DEFAULT);
// dismiss notification
mNotificationManager.cancel(TRACKER_SERVICE_NOTIFICATION_ID); // todo check if necessary?
stopForeground(true);
@ -169,10 +175,6 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
stopTracking();
}
// // remove listeners
// stopFindingLocation();
// mSensorManager.unregisterListener(this);
// remove TrackerService from foreground state
stopForeground(true);
@ -202,14 +204,16 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
/* Start tracking location */
private void startTracking(Intent intent) {
private void startTracking(@Nullable Intent intent, boolean createNewTrack) {
LogHelper.v(LOG_TAG, "Service received command: START");
// create a new track
mTrack = new Track();
// create a new track -- if necessary
if (createNewTrack) {
mTrack = new Track();
}
// get last location
if (intent.hasExtra(EXTRA_LAST_LOCATION)) {
if (intent != null && intent.hasExtra(EXTRA_LAST_LOCATION)) {
mCurrentBestLocation = intent.getParcelableExtra(EXTRA_LAST_LOCATION);
}
// get last location - fallback
@ -226,11 +230,13 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification); // todo check if necessary in pre Android O
// set timer to retrieve new locations and to prevent endless tracking
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
final long previouslyRecorded = settings.getLong(PREFS_CURRENT_TRACK_DURATION, 0);// todo describe
mTimer = new CountDownTimer(EIGHT_HOURS_IN_MILLISECONDS, FIFTEEN_SECONDS_IN_MILLISECONDS) {
@Override
public void onTick(long millisUntilFinished) {
// update track duration
long duration = EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished;
long duration = EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished + previouslyRecorded;
mTrack.setDuration(duration);
// try to add WayPoint to Track
addWayPointToTrack();
@ -305,6 +311,25 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
/* Adds a new WayPoint to current track */
private void addWayPointToTrack() {
// TODO REMOVE
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> l = am.getRunningServices(50);
Iterator<ActivityManager.RunningServiceInfo> i = l.iterator();
while (i.hasNext()) {
ActivityManager.RunningServiceInfo runningServiceInfo = i
.next();
if(runningServiceInfo.service.getClassName().contains("TrackerService")){
if(runningServiceInfo.foreground)
{
LogHelper.e(LOG_TAG, "Foreground State? YES");
}
}
}
// TODO REMOVE
// create new WayPoint
WayPoint newWayPoint = null;
@ -334,11 +359,17 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
newWayPoint = mTrack.addWayPoint(mCurrentBestLocation);
}
// save state
saveTrackerServiceState(mTrackerServiceRunning, mTrack.getTrackDuration(), FAB_STATE_RECORDING);
}
// send local broadcast if new WayPoint added
if (newWayPoint != null) {
sendTrackUpdate();
// save a temp file in case the service has been killed by the system
SaveTempTrackAsyncHelper saveTempTrackAsyncHelper = new SaveTempTrackAsyncHelper();
saveTempTrackAsyncHelper.execute();
}
}
@ -396,7 +427,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
mTrackerServiceRunning = true;
}
LocationHelper.registerLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_RECORDING);
saveTrackerServiceState(mTrackerServiceRunning, mTrack.getTrackDuration(), FAB_STATE_RECORDING);
}
@ -405,7 +436,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
// remove listeners
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
mTrackerServiceRunning = false;
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_SAVE);
saveTrackerServiceState(mTrackerServiceRunning, mTrack.getTrackDuration(),FAB_STATE_SAVE);
// notify MainActivityMapFragment
Intent i = new Intent();
@ -417,10 +448,11 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
/* Saves state of Tracker Service and floating Action Button */
private void saveTrackerServiceState(boolean trackerServiceRunning, int fabState) {
private void saveTrackerServiceState(boolean trackerServiceRunning, long currentTrackDuration, int fabState) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(PREFS_TRACKER_SERVICE_RUNNING, trackerServiceRunning);
editor.putLong(PREFS_CURRENT_TRACK_DURATION, currentTrackDuration);
editor.putInt(PREFS_FAB_STATE, fabState);
editor.apply();
}

View File

@ -149,8 +149,8 @@ public class Track implements TrackbookKeys, Parcelable {
/* Getter for duration of track */
public String getTrackDuration() {
return LocationHelper.convertToReadableTime(mDuration, true);
public long getTrackDuration() {
return mDuration;
}
/* Getter for start date of recording */
@ -171,8 +171,13 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Getter for distance of track */
public String getTrackDistance() {
/* Getter for string representation of track duration */
public String getTrackDurationString() {
return LocationHelper.convertToReadableTime(mDuration, true);
}
/* Getter for string representation of track distance */
public String getTrackDistanceString() {
float trackDistance;
String unit;

View File

@ -26,7 +26,7 @@ import android.util.Log;
*/
public final class LogHelper {
private final static boolean mTesting = false;
private final static boolean mTesting = true;
public static void d(final String tag, String message) {
// include logging only in debug versions

View File

@ -158,8 +158,8 @@ public class NotificationHelper implements TrackbookKeys {
/* Build context text for notification builder */
private static String getContextString(Context context, Track track) {
return context.getString(R.string.notification_content_distance) + ": " + track.getTrackDistance() + " | " +
context.getString(R.string.notification_content_duration) + ": " + track.getTrackDuration();
return context.getString(R.string.notification_content_distance) + ": " + track.getTrackDistanceString() + " | " +
context.getString(R.string.notification_content_duration) + ": " + track.getTrackDurationString();
}
}

View File

@ -50,6 +50,7 @@ public interface TrackbookKeys {
/* PREFS */
String PREFS_FAB_STATE = "fabStatePrefs";
String PREFS_TRACKER_SERVICE_RUNNING = "trackerServiceRunning";
String PREFS_CURRENT_TRACK_DURATION = "currentTrackDuration";
/* INSTANCE STATE */
String INSTANCE_FIRST_START = "firstStart";