tracker service is now a so-called bound service
parent
39a4cbbe41
commit
8264a2b2af
|
@ -20,15 +20,18 @@ import android.Manifest;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
@ -52,6 +55,7 @@ import android.widget.Button;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.osmdroid.config.Configuration;
|
import org.osmdroid.config.Configuration;
|
||||||
|
import org.y20k.trackbook.core.Track;
|
||||||
import org.y20k.trackbook.helpers.DialogHelper;
|
import org.y20k.trackbook.helpers.DialogHelper;
|
||||||
import org.y20k.trackbook.helpers.LogHelper;
|
import org.y20k.trackbook.helpers.LogHelper;
|
||||||
import org.y20k.trackbook.helpers.NightModeHelper;
|
import org.y20k.trackbook.helpers.NightModeHelper;
|
||||||
|
@ -75,6 +79,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
|
|
||||||
|
|
||||||
/* Main class variables */
|
/* Main class variables */
|
||||||
|
private TrackerService mTrackerService;
|
||||||
private BottomNavigationView mBottomNavigationView;
|
private BottomNavigationView mBottomNavigationView;
|
||||||
private NonSwipeableViewPager mViewPager;
|
private NonSwipeableViewPager mViewPager;
|
||||||
private SectionsPagerAdapter mSectionsPagerAdapter;
|
private SectionsPagerAdapter mSectionsPagerAdapter;
|
||||||
|
@ -94,6 +99,8 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
private int mFloatingActionButtonState;
|
private int mFloatingActionButtonState;
|
||||||
private int mSelectedTab;
|
private int mSelectedTab;
|
||||||
|
|
||||||
|
boolean mBound = false;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -140,6 +147,10 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
|
// bind to TrackerService
|
||||||
|
Intent intent = new Intent(this, TrackerService.class);
|
||||||
|
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
|
||||||
// register broadcast receiver for changed tracking state
|
// register broadcast receiver for changed tracking state
|
||||||
mTrackingChangedReceiver = createTrackingChangedReceiver();
|
mTrackingChangedReceiver = createTrackingChangedReceiver();
|
||||||
IntentFilter trackingStoppedIntentFilter = new IntentFilter(ACTION_TRACKING_STATE_CHANGED);
|
IntentFilter trackingStoppedIntentFilter = new IntentFilter(ACTION_TRACKING_STATE_CHANGED);
|
||||||
|
@ -170,6 +181,14 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
unbindService(mConnection);
|
||||||
|
mBound = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
@ -250,13 +269,21 @@ 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
|
||||||
mBottomNavigationView.setSelectedItemId(R.id.navigation_last_tracks);
|
mBottomNavigationView.setSelectedItemId(R.id.navigation_last_tracks);
|
||||||
|
|
||||||
// dismiss notification
|
// dismiss notification
|
||||||
startTrackerService(ACTION_DISMISS, null);
|
dismissNotification();
|
||||||
|
|
||||||
// hide Floating Action Button sub menu
|
// hide Floating Action Button sub menu
|
||||||
showFloatingActionButtonMenu(false);
|
showFloatingActionButtonMenu(false);
|
||||||
|
@ -267,17 +294,11 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Start/stop tracker service */
|
/* Start tracker service */
|
||||||
private void startTrackerService(String intentAction, @Nullable Location lastLocation) {
|
private void startTrackerService() {
|
||||||
// build intent
|
// start service so that it keeps running after unbind
|
||||||
Intent intent = new Intent(this, TrackerService.class);
|
Intent intent = new Intent(this, TrackerService.class);
|
||||||
intent.setAction(intentAction);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
if (lastLocation != null && intentAction.equals(ACTION_START)) {
|
|
||||||
intent.putExtra(EXTRA_LAST_LOCATION, lastLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// communicate with service
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && intentAction.equals(ACTION_START)) {
|
|
||||||
// ... start service in foreground to prevent it being killed on Oreo
|
// ... start service in foreground to prevent it being killed on Oreo
|
||||||
startForegroundService(intent);
|
startForegroundService(intent);
|
||||||
} else {
|
} else {
|
||||||
|
@ -286,6 +307,39 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Start recording movements */
|
||||||
|
private void startRecording(Location lastLocation) {
|
||||||
|
startTrackerService();
|
||||||
|
if (mBound) {
|
||||||
|
mTrackerService.startTracking(lastLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Resume recording movements */
|
||||||
|
private void resumeRecording() {
|
||||||
|
startTrackerService();
|
||||||
|
if (mBound) {
|
||||||
|
mTrackerService.resumeTracking();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Stop recording movements */
|
||||||
|
private void stopRecording() {
|
||||||
|
if (mBound) {
|
||||||
|
mTrackerService.stopTracking();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dismiss notification */
|
||||||
|
private void dismissNotification() {
|
||||||
|
if (mBound) {
|
||||||
|
mTrackerService.dismissNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Handles the visual state after a save action */
|
/* Handles the visual state after a save action */
|
||||||
private void handleStateAfterClear() {
|
private void handleStateAfterClear() {
|
||||||
|
@ -293,7 +347,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
// dismiss notification
|
// dismiss notification
|
||||||
startTrackerService(ACTION_DISMISS, null);
|
dismissNotification();
|
||||||
|
|
||||||
// hide Floating Action Button sub menu
|
// hide Floating Action Button sub menu
|
||||||
showFloatingActionButtonMenu(false);
|
showFloatingActionButtonMenu(false);
|
||||||
|
@ -335,7 +389,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
Snackbar.make(view, R.string.snackbar_message_tracking_resumed, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
Snackbar.make(view, R.string.snackbar_message_tracking_resumed, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
||||||
|
|
||||||
// resume tracking
|
// resume tracking
|
||||||
startTrackerService(ACTION_RESUME, null);
|
resumeRecording();
|
||||||
|
|
||||||
// hide sub menu
|
// hide sub menu
|
||||||
showFloatingActionButtonMenu(false);
|
showFloatingActionButtonMenu(false);
|
||||||
|
@ -500,7 +554,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
Snackbar.make(view, R.string.snackbar_message_tracking_started, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
Snackbar.make(view, R.string.snackbar_message_tracking_started, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
||||||
|
|
||||||
// start tracker service
|
// start tracker service
|
||||||
startTrackerService(ACTION_START, lastLocation);
|
startRecording(lastLocation);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, getString(R.string.toast_message_location_services_not_ready), Toast.LENGTH_LONG).show();
|
Toast.makeText(this, getString(R.string.toast_message_location_services_not_ready), Toast.LENGTH_LONG).show();
|
||||||
|
@ -518,7 +572,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
// --> is handled by broadcast receiver
|
// --> is handled by broadcast receiver
|
||||||
|
|
||||||
// stop tracker service
|
// stop tracker service
|
||||||
startTrackerService(ACTION_STOP, null);
|
stopRecording();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -756,6 +810,25 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines callbacks for service binding, passed to bindService()
|
||||||
|
*/
|
||||||
|
private ServiceConnection mConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
||||||
|
TrackerService.LocalBinder binder = (TrackerService.LocalBinder) service;
|
||||||
|
mTrackerService = binder.getService();
|
||||||
|
mBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName arg0) {
|
||||||
|
mBound = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class: SectionsPagerAdapter that returns a fragment corresponding to one of the tabs.
|
* Inner class: SectionsPagerAdapter that returns a fragment corresponding to one of the tabs.
|
||||||
|
|
|
@ -228,9 +228,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
|
||||||
// CASE 1: recording active
|
// CASE 1: recording active
|
||||||
if (mTrackerServiceRunning) {
|
if (mTrackerServiceRunning) {
|
||||||
// request an updated track recording from service
|
// request an updated track recording from service
|
||||||
Intent intent = new Intent(mActivity, TrackerService.class);
|
((MainActivity)mActivity).requestTrack();
|
||||||
intent.setAction(ACTION_TRACK_REQUEST);
|
|
||||||
mActivity.startService(intent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CASE 2: recording stopped - temp file exists
|
// CASE 2: recording stopped - temp file exists
|
||||||
|
@ -580,6 +578,8 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
|
||||||
|
|
||||||
/* Loads state tracker service from preferences */
|
/* Loads state tracker service from preferences */
|
||||||
private void loadTrackerServiceState(Context context) {
|
private void loadTrackerServiceState(Context context) {
|
||||||
|
// TODO: get state directly from service, create a ServiceConnection.
|
||||||
|
// see: https://github.com/ena1106/FragmentBoundServiceExample/blob/master/app/src/main/java/it/ena1106/fragmentboundservice/BoundFragment.java
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
mTrackerServiceRunning = settings.getBoolean(PREFS_TRACKER_SERVICE_RUNNING, false);
|
mTrackerServiceRunning = settings.getBoolean(PREFS_TRACKER_SERVICE_RUNNING, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -50,6 +51,7 @@ 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;
|
||||||
|
|
||||||
|
@ -79,6 +81,8 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
private boolean mTrackerServiceRunning;
|
private boolean mTrackerServiceRunning;
|
||||||
private boolean mLocationSystemSetting;
|
private boolean mLocationSystemSetting;
|
||||||
|
|
||||||
|
private final IBinder mBinder = new LocalBinder(); // todo move to onCreate
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
|
@ -102,69 +106,101 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
// a client is binding to the service with bindService()
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onUnbind(Intent intent) {
|
||||||
|
// All clients have unbound with unbindService()
|
||||||
|
// return mAllowRebind; // todo change
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRebind(Intent intent) {
|
||||||
|
// A client is binding to the service with bindService(),
|
||||||
|
// after onUnbind() has already been called
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
|
||||||
// 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
|
// ACTION STOP
|
||||||
else if (intent.getAction().equals(ACTION_STOP) || !mLocationSystemSetting) {
|
if (ACTION_STOP.equals(intent.getAction())) {
|
||||||
mTrackerServiceRunning = false;
|
|
||||||
if (mTrack != null && mTimer != null) {
|
|
||||||
stopTracking();
|
stopTracking();
|
||||||
} else {
|
|
||||||
// handle error - save state
|
|
||||||
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
// ACTION RESUME
|
||||||
|
else if (ACTION_RESUME.equals(intent.getAction())) {
|
||||||
|
resumeTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACTION DISMISS
|
// // check if user did turn off location in device settings
|
||||||
else if (intent.getAction().equals(ACTION_DISMISS)) {
|
// if (!mLocationSystemSetting) {
|
||||||
// save state
|
// LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
||||||
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
|
// Toast.makeText(getApplicationContext(), R.string.toast_message_location_offline, Toast.LENGTH_LONG).show();
|
||||||
// dismiss notification
|
// stopTracking();
|
||||||
mNotificationManager.cancel(TRACKER_SERVICE_NOTIFICATION_ID); // todo check if necessary?
|
// return START_STICKY;
|
||||||
stopForeground(true);
|
// }
|
||||||
}
|
//
|
||||||
|
// // RESTART CHECK: checking for empty intent - try to get saved track
|
||||||
// ACTION TRACK REQUEST
|
// if (intent == null || intent.getAction() == null) {
|
||||||
else if (intent.getAction().equals(ACTION_TRACK_REQUEST)) {
|
// LogHelper.w(LOG_TAG, "Null-Intent received. Trying to restart tracking.");
|
||||||
// send track via broadcast
|
// startTracking(intent, false);
|
||||||
sendTrackUpdate();
|
// }
|
||||||
}
|
//
|
||||||
|
// // 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
|
// @Nullable
|
||||||
@Override
|
// @Override
|
||||||
public IBinder onBind(Intent intent) {
|
// public IBinder onBind(Intent intent) {
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -204,6 +240,153 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
|
|
||||||
|
|
||||||
/* Start tracking location */
|
/* Start tracking location */
|
||||||
|
public void startTracking(Location lastLocation) {
|
||||||
|
if (mLocationSystemSetting) {
|
||||||
|
LogHelper.v(LOG_TAG, "Start tracking");
|
||||||
|
|
||||||
|
// create a new track - if requested
|
||||||
|
mTrack = new Track();
|
||||||
|
|
||||||
|
// get last location
|
||||||
|
if (lastLocation != null) {
|
||||||
|
mCurrentBestLocation = lastLocation;
|
||||||
|
} else {
|
||||||
|
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize step counter
|
||||||
|
mStepCountOffset = 0;
|
||||||
|
|
||||||
|
// begin recording
|
||||||
|
recordMovements();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.toast_message_location_offline, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Resume tracking after stop/pause */
|
||||||
|
public void resumeTracking() {
|
||||||
|
if (mLocationSystemSetting) {
|
||||||
|
LogHelper.v(LOG_TAG, "Recording resumed");
|
||||||
|
|
||||||
|
// create a new track - if requested
|
||||||
|
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 (mTrack.getSize() > 0) {
|
||||||
|
mCurrentBestLocation = mTrack.getWayPointLocation(mTrack.getSize() -1);
|
||||||
|
} else {
|
||||||
|
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize step counter
|
||||||
|
mStepCountOffset = mTrack.getStepCount();
|
||||||
|
|
||||||
|
// begin recording
|
||||||
|
recordMovements();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LogHelper.i(LOG_TAG, "Location Setting is turned off.");
|
||||||
|
Toast.makeText(getApplicationContext(), R.string.toast_message_location_offline, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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) {
|
private void startTracking(@Nullable Intent intent, boolean createNewTrack) {
|
||||||
LogHelper.v(LOG_TAG, "Service received command: START");
|
LogHelper.v(LOG_TAG, "Service received command: START");
|
||||||
|
|
||||||
|
@ -301,8 +484,8 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
|
|
||||||
|
|
||||||
/* Stop tracking location */
|
/* Stop tracking location */
|
||||||
private void stopTracking() {
|
public void stopTracking() {
|
||||||
LogHelper.v(LOG_TAG, "Service received command: STOP");
|
LogHelper.v(LOG_TAG, "Recording stopped");
|
||||||
|
|
||||||
// store current date and time
|
// store current date and time
|
||||||
mTrack.setRecordingEnd();
|
mTrack.setRecordingEnd();
|
||||||
|
@ -318,9 +501,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
saveTempTrackAsyncHelper.execute();
|
saveTempTrackAsyncHelper.execute();
|
||||||
|
|
||||||
// change notification
|
// change notification
|
||||||
mNotificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL);
|
displayNotification(false);
|
||||||
mNotification = NotificationHelper.getNotification(this, mNotificationBuilder, mTrack, false);
|
|
||||||
mNotificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
|
||||||
|
|
||||||
// remove listeners
|
// remove listeners
|
||||||
stopFindingLocation();
|
stopFindingLocation();
|
||||||
|
@ -334,6 +515,17 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dismiss notification */
|
||||||
|
public void dismissNotification() {
|
||||||
|
// save state
|
||||||
|
saveTrackerServiceState(mTrackerServiceRunning, FAB_STATE_DEFAULT);
|
||||||
|
// cancel notification
|
||||||
|
mNotificationManager.cancel(TRACKER_SERVICE_NOTIFICATION_ID); // todo check if necessary?
|
||||||
|
stopForeground(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Adds a new WayPoint to current track */
|
/* Adds a new WayPoint to current track */
|
||||||
private void addWayPointToTrack() {
|
private void addWayPointToTrack() {
|
||||||
|
|
||||||
|
@ -376,7 +568,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
|
|
||||||
|
|
||||||
/* Broadcasts a track update */
|
/* Broadcasts a track update */
|
||||||
private void sendTrackUpdate() {
|
public void sendTrackUpdate() {
|
||||||
if (mTrack != null) {
|
if (mTrack != null) {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setAction(ACTION_TRACK_UPDATED);
|
i.setAction(ACTION_TRACK_UPDATED);
|
||||||
|
@ -467,6 +659,20 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner class: Local Binder that returns this service
|
||||||
|
*/
|
||||||
|
public class LocalBinder extends Binder {
|
||||||
|
TrackerService getService() {
|
||||||
|
// return this instance of TrackerService so clients can call public methods
|
||||||
|
return TrackerService.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* End of inner class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class: SettingsContentObserver is a custom ContentObserver for changes in Android Settings
|
* Inner class: SettingsContentObserver is a custom ContentObserver for changes in Android Settings
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -6,7 +6,7 @@ buildscript {
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
classpath 'com.android.tools.build:gradle:3.1.0'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#Thu Nov 02 15:43:54 CET 2017
|
#Wed Apr 04 15:52:45 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||||
|
|
Loading…
Reference in New Issue