diff --git a/app/src/main/java/org/y20k/trackbook/MainActivityFragment.java b/app/src/main/java/org/y20k/trackbook/MainActivityFragment.java index e7b840c..b2d345c 100644 --- a/app/src/main/java/org/y20k/trackbook/MainActivityFragment.java +++ b/app/src/main/java/org/y20k/trackbook/MainActivityFragment.java @@ -17,7 +17,10 @@ package org.y20k.trackbook; import android.app.Activity; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.location.Location; import android.location.LocationListener; @@ -25,6 +28,7 @@ import android.location.LocationManager; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; +import android.support.v4.content.LocalBroadcastManager; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.MenuItem; @@ -58,6 +62,8 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { /* Main class variables */ private Activity mActivity; + private boolean mFirstStart; + private BroadcastReceiver mWayPointReceiver; private MapView mMapView; private IMapController mController; private LocationManager mLocationManager; @@ -82,6 +88,17 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { // action bar has options menu setHasOptionsMenu(true); + // restore first start state + mFirstStart = true; + if (savedInstanceState != null) { + mFirstStart = savedInstanceState.getBoolean(INSTANCE_FIRST_START, true); + } + + // register broadcast receiver for new WayPoints + mWayPointReceiver = createNewWayPointReceiver(); + IntentFilter newWayPointReceiverIntentFilter = new IntentFilter(ACTION_WAYPOINT_ADDED); + LocalBroadcastManager.getInstance(mActivity).registerReceiver(mWayPointReceiver, newWayPointReceiverIntentFilter); + // acquire reference to Location Manager mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE); @@ -180,11 +197,23 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { public void onDestroyView(){ super.onDestroyView(); + // unregister broadcast receiver + LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mWayPointReceiver); + // deactivate map mMapView.onDetach(); } + @Override + public void onDestroy() { + // reset first start state + mFirstStart = true; + + super.onDestroy(); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { @@ -233,6 +262,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { @Override public void onSaveInstanceState(Bundle outState) { // save map position + outState.putBoolean(INSTANCE_FIRST_START, mFirstStart); outState.putDouble(INSTANCE_LATITUDE, mMapView.getMapCenter().getLatitude()); outState.putDouble(INSTANCE_LONGITUDE, mMapView.getMapCenter().getLongitude()); outState.putInt(INSTANCE_ZOOM_LEVEL, mMapView.getZoomLevel()); @@ -249,7 +279,10 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { mNetworkListener = createLocationListener(); // inform user that Trackbook is getting location updates - Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_acquiring_location), Toast.LENGTH_LONG).show(); + if (mFirstStart) { + Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_acquiring_location), Toast.LENGTH_LONG).show(); + mFirstStart = false; + } // start listener List locationProviders = mLocationManager.getProviders(true); @@ -333,6 +366,20 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys { } + /* Creates receiver for new WayPoints */ + private BroadcastReceiver createNewWayPointReceiver () { + return new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.hasExtra(EXTRA_WAYPOINT_LOCATION) && intent.hasExtra(EXTRA_WAYPOINT_IS_STOPOVER)) { + // TODO draw location on map + Toast.makeText(mActivity, "New WayPoint: " + intent.getParcelableExtra(EXTRA_WAYPOINT_LOCATION).toString(), Toast.LENGTH_LONG).show(); // TODO Remove + } + } + }; + } + + /* Saves state of map */ private void saveMaoState(Context context) { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); diff --git a/app/src/main/java/org/y20k/trackbook/TrackerService.java b/app/src/main/java/org/y20k/trackbook/TrackerService.java index 3d2cf8e..40806d4 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackerService.java +++ b/app/src/main/java/org/y20k/trackbook/TrackerService.java @@ -29,6 +29,7 @@ import android.support.annotation.Nullable; import android.util.Log; import org.y20k.trackbook.core.Track; +import org.y20k.trackbook.helpers.LocationHelper; import org.y20k.trackbook.helpers.TrackbookKeys; @@ -45,11 +46,11 @@ public class TrackerService extends Service implements TrackbookKeys { private Track mTrack; private CountDownTimer mTimer; private LocationManager mLocationManager; - private LocationListener mLocationListener; + private LocationListener mGPSListener; + private LocationListener mNetworkListener; @Override public int onStartCommand(Intent intent, int flags, int startId) { -// return super.onStartCommand(intent, flags, startId); // checking for empty intent if (intent == null) { @@ -64,33 +65,23 @@ public class TrackerService extends Service implements TrackbookKeys { Log.v(LOG_TAG, "Service received command: START"); // create a new track - mTrack = new Track(); + mTrack = new Track(getApplicationContext()); // acquire reference to Location Manager mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - // listener that responds to location updates - mLocationListener = new LocationListener() { - public void onLocationChanged(Location location) { - // add new location to track - mTrack.addWayPoint(location, false); - } - - public void onStatusChanged(String provider, int status, Bundle extras) { - // TODO do something - } - - public void onProviderEnabled(String provider) { - // TODO do something - } - - public void onProviderDisabled(String provider) { - // TODO do something - } - }; + // listeners that responds to location updates + mGPSListener = createLocationListener(); + mNetworkListener = createLocationListener(); + // register location listeners and request updates try { - mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); + mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mGPSListener); + } catch (SecurityException e) { + e.printStackTrace(); + } + try { + mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mNetworkListener); } catch (SecurityException e) { e.printStackTrace(); } @@ -111,9 +102,14 @@ public class TrackerService extends Service implements TrackbookKeys { // ACTION STOP else if (intent.getAction().equals(ACTION_STOP)) { - // Remove the listener you previously added + // remove listeners try { - mLocationManager.removeUpdates(mLocationListener); + mLocationManager.removeUpdates(mGPSListener); + } catch (SecurityException e) { + e.printStackTrace(); + } + try { + mLocationManager.removeUpdates(mNetworkListener); } catch (SecurityException e) { e.printStackTrace(); } @@ -136,17 +132,56 @@ public class TrackerService extends Service implements TrackbookKeys { public void onDestroy() { super.onDestroy(); - Log.v(LOG_TAG, "onDestroy called."); - - // Remove the listener you previously added + // remove listeners try { - mLocationManager.removeUpdates(mLocationListener); + mLocationManager.removeUpdates(mGPSListener); } catch (SecurityException e) { e.printStackTrace(); } + try { + mLocationManager.removeUpdates(mNetworkListener); + } catch (SecurityException e) { + e.printStackTrace(); + } + + Log.v(LOG_TAG, "onDestroy called."); // cancel notification stopForeground(true); } + + /* Creates a location listener */ + private LocationListener createLocationListener() { + return new LocationListener() { + public void onLocationChanged(Location location) { + + // get number of tracked WayPoints + int trackSize = mTrack.getWayPoints().size(); + + if (trackSize >= 2) { + Location lastWayPoint = mTrack.getWayPointLocation(trackSize-2); + if (LocationHelper.isNewWayPoint(lastWayPoint, location)) { + // add new location to track + mTrack.addWayPoint(location); + } + } else { + // add first location to track + mTrack.addWayPoint(location); + } + } + + public void onStatusChanged(String provider, int status, Bundle extras) { + // TODO do something + } + + public void onProviderEnabled(String provider) { + // TODO do something + } + + public void onProviderDisabled(String provider) { + // TODO do something + } + }; + } } diff --git a/app/src/main/java/org/y20k/trackbook/core/Track.java b/app/src/main/java/org/y20k/trackbook/core/Track.java index 523687a..d38a93d 100644 --- a/app/src/main/java/org/y20k/trackbook/core/Track.java +++ b/app/src/main/java/org/y20k/trackbook/core/Track.java @@ -16,14 +16,19 @@ package org.y20k.trackbook.core; +import android.content.Context; +import android.content.Intent; import android.location.Location; -import android.util.Log; +import android.support.v4.content.LocalBroadcastManager; +import org.y20k.trackbook.helpers.LocationHelper; +import org.y20k.trackbook.helpers.LogHelper; import org.y20k.trackbook.helpers.TrackbookKeys; import java.util.ArrayList; import java.util.List; + /** * Track class */ @@ -34,49 +39,58 @@ public class Track implements TrackbookKeys { /* Main class variables */ - private List mWayPoints; + private Context mContext; + private List mWayPoints; /* Constructor */ - public Track() { + public Track(Context context) { + mContext = context; mWayPoints = new ArrayList(); } /* Adds new waypoint */ - public void addWayPoint(Location location, boolean isStopOver) { + public void addWayPoint(Location location) { // create new waypoint - WayPoint wayPoint = new WayPoint(location, isStopOver); - - // TODO check if last waypoint is a stopover - if (CONSTANT_MINIMAL_STOP_TIME != CONSTANT_MINIMAL_STOP_TIME) { - wayPoint.isStopOver = true; - } else { - wayPoint.isStopOver = false; - } + WayPoint wayPoint = new WayPoint(); + wayPoint.location = location; + wayPoint.isStopOver = LocationHelper.isStopOver(location); // add new waypoint to track mWayPoints.add(wayPoint); - // TODO remove debugging log - Log.v(LOG_TAG, "!!! new location: " + wayPoint.location.toString()); + // send local broadcast: new WayPoint added + Intent i = new Intent(); + i.setAction(ACTION_WAYPOINT_ADDED); + i.putExtra(EXTRA_WAYPOINT_LOCATION, location); + i.putExtra(EXTRA_WAYPOINT_IS_STOPOVER, wayPoint.isStopOver); + LocalBroadcastManager.getInstance(mContext).sendBroadcast(i); + + LogHelper.v(LOG_TAG, "!!! Waypoint No. " + mWayPoints.indexOf(wayPoint) + " Location: " + wayPoint.location.toString()); // TODO remove + } + + + /* Getter for mWayPoints */ + public List getWayPoints() { + return mWayPoints; + } + + + /* Getter for location of specific WayPoint */ + public Location getWayPointLocation(int index) { + return mWayPoints.get(index).location; } /** - * Inner class: Defines data type WayPoint *** + * Inner class: Defines data type WayPoint */ private class WayPoint { private Location location; private boolean isStopOver; - /* Constructor */ - public WayPoint(Location location, boolean isStopOver) { - this.location = location; - this.isStopOver = isStopOver; - } - } /** * End of inner class diff --git a/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java index 31106b5..c5430bd 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java @@ -34,7 +34,8 @@ public final class LocationHelper { /* Main class variables */ // private static final int TWO_MINUTES = 1000 * 1000 * 60 * 2; - private static final long TWO_MINUTES = 2L * 60000000000L; // 5 minutes + private static final long TWO_MINUTES = 2L * 60000000000L; // 2 minutes + private static final long TWENTY_SECONDS = 20000000000L; // 20 seconds /* Determines last known location */ @@ -140,6 +141,23 @@ public final class LocationHelper { } + /* Checks if given location is a new waypoint over */ + public static boolean isNewWayPoint(Location lastWayPoint, Location newLocation) { + float distance = newLocation.distanceTo(lastWayPoint); + long timeDifference = newLocation.getElapsedRealtimeNanos() - lastWayPoint.getElapsedRealtimeNanos(); + + // distance is bigger than 10 meters and time difference bigger than 20 seconds + return distance > 10 && timeDifference > TWENTY_SECONDS; + } + + + /* Checks if given location is a stop over */ + public static boolean isStopOver(Location location) { + // TODO determine, if location is stopover + return false; + } + + /* Checks whether two location providers are the same */ private static boolean isSameProvider(String provider1, String provider2) { // credit: the isSameProvider method was sample code from: https://developer.android.com/guide/topics/location/strategies.html diff --git a/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java b/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java index 63d6857..b61b1b7 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java @@ -25,8 +25,11 @@ public interface TrackbookKeys { /* ACTIONS */ public static final String ACTION_START = "org.y20k.transistor.action.START"; public static final String ACTION_STOP = "org.y20k.transistor.action.STOP"; + public static final String ACTION_WAYPOINT_ADDED = "WAYPOINT_ADDED"; /* EXTRAS */ + public static final String EXTRA_WAYPOINT_LOCATION = "WAYPOINT_LOCATION"; + public static final String EXTRA_WAYPOINT_IS_STOPOVER = "WAYPOINT_IS_STOPOVER"; /* ARGS */ public static final String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted"; @@ -41,6 +44,7 @@ public interface TrackbookKeys { public static final String PREFS_SHOW_COMPASS = "showCompass"; /* INSTANCE STATE */ + public static final String INSTANCE_FIRST_START = "firstStart"; public static final String INSTANCE_LATITUDE = "latitude"; public static final String INSTANCE_LONGITUDE = "longitude"; public static final String INSTANCE_ZOOM_LEVEL = "zoomLevel"; diff --git a/app/src/main/res/drawable/ic_my_location_crumb_blue_24dp.xml b/app/src/main/res/drawable/ic_my_location_crumb_blue_24dp.xml new file mode 100644 index 0000000..8994111 --- /dev/null +++ b/app/src/main/res/drawable/ic_my_location_crumb_blue_24dp.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_my_location_dot_red_24dp.xml b/app/src/main/res/drawable/ic_my_location_dot_red_24dp.xml new file mode 100644 index 0000000..9c79b58 --- /dev/null +++ b/app/src/main/res/drawable/ic_my_location_dot_red_24dp.xml @@ -0,0 +1,13 @@ + + + +