older locations fixes are now grey (my location) - refining the locations tracking. - some logging statements for debugging

master
y20k 2016-08-29 21:43:49 +02:00
parent 33606faac1
commit e21879756b
9 changed files with 118 additions and 40 deletions

View File

@ -60,12 +60,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
private Activity mActivity; private Activity mActivity;
private MapView mMapView; private MapView mMapView;
private IMapController mController; private IMapController mController;
private CompassOverlay mCompassOverlay = null;
private LocationManager mLocationManager; private LocationManager mLocationManager;
private LocationListener mGPSListener; private LocationListener mGPSListener;
private LocationListener mNetworkListener; private LocationListener mNetworkListener;
private Location mCurrentBestLocation;
private ItemizedIconOverlay mMyLocationOverlay; private ItemizedIconOverlay mMyLocationOverlay;
private Location mCurrentBestLocation;
/* Constructor (default) */ /* Constructor (default) */
@ -86,14 +85,28 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
// acquire reference to Location Manager // acquire reference to Location Manager
mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE); mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
// get last know location // check if location services are available
List locationProviders = mLocationManager.getProviders(true); if (mLocationManager.getProviders(true).size() == 0) {
if (locationProviders.size() > 0) { // ask user to turn on location services
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
} else {
promptUserForLocation(); promptUserForLocation();
} }
// CASE 1: get saved location if possible
if (savedInstanceState != null) {
Location savedLocation = savedInstanceState.getParcelable(INSTANCE_CURRENT_LOCATION);
// check if saved location is still current
if (LocationHelper.isNewLocation(savedLocation)) {
mCurrentBestLocation = savedLocation;
} else {
mCurrentBestLocation = null;
}
}
// CASE 2: get last known location if no saved location or saved location is too old
if (mCurrentBestLocation == null && mLocationManager.getProviders(true).size() > 0) {
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
}
} }
@ -131,13 +144,13 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
} }
// add compass to map // add compass to map
mCompassOverlay = new CompassOverlay(mActivity, new InternalCompassOrientationProvider(mActivity), mMapView); CompassOverlay compassOverlay = new CompassOverlay(mActivity, new InternalCompassOrientationProvider(mActivity), mMapView);
mCompassOverlay.enableCompass(); compassOverlay.enableCompass();
mMapView.getOverlays().add(mCompassOverlay); mMapView.getOverlays().add(compassOverlay);
// mark user's location on map // mark user's location on map
if (mCurrentBestLocation != null) { if (mCurrentBestLocation != null) {
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation); mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation));
mMapView.getOverlays().add(mMyLocationOverlay); mMapView.getOverlays().add(mMyLocationOverlay);
} }
@ -205,7 +218,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
// mark user's new location on map and remove last marker // mark user's new location on map and remove last marker
mMapView.getOverlays().remove(mMyLocationOverlay); mMapView.getOverlays().remove(mMyLocationOverlay);
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation); mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation));
mMapView.getOverlays().add(mMyLocationOverlay); mMapView.getOverlays().add(mMyLocationOverlay);
return true; return true;
@ -232,8 +245,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
private void startFindingLocation() { private void startFindingLocation() {
// listener that responds to location updates // listener that responds to location updates
mGPSListener = createLocationsListener(); mGPSListener = createLocationListener();
mNetworkListener = createLocationsListener(); 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();
// start listener // start listener
List locationProviders = mLocationManager.getProviders(true); List locationProviders = mLocationManager.getProviders(true);
@ -280,17 +296,17 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
/* Creates listener for changes in location status */ /* Creates listener for changes in location status */
private LocationListener createLocationsListener() { private LocationListener createLocationListener() {
return new LocationListener() { return new LocationListener() {
public void onLocationChanged(Location location) { public void onLocationChanged(Location location) {
// check if the new location is better // check if the new location is better
if (LocationHelper.isBetterLocation(location, mCurrentBestLocation)) { if (LocationHelper.isBetterLocation(location, mCurrentBestLocation)) {
// save location // save location
mCurrentBestLocation = location; mCurrentBestLocation = location;
LogHelper.v(LOG_TAG, "Location isBetterLocation(!): " + location.getProvider()); // TODO remove
// mark user's new location on map and remove last marker // mark user's new location on map and remove last marker
mMapView.getOverlays().remove(mMyLocationOverlay); mMapView.getOverlays().remove(mMyLocationOverlay);
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation); mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation));
mMapView.getOverlays().add(mMyLocationOverlay); mMapView.getOverlays().add(mMyLocationOverlay);
} }
} }

View File

@ -37,8 +37,6 @@ import org.y20k.trackbook.helpers.TrackbookKeys;
*/ */
public class TrackerService extends Service implements TrackbookKeys { public class TrackerService extends Service implements TrackbookKeys {
// TODO study this https://developer.android.com/guide/topics/location/strategies.html
/* Define log tag */ /* Define log tag */
private static final String LOG_TAG = TrackerService.class.getSimpleName(); private static final String LOG_TAG = TrackerService.class.getSimpleName();
@ -91,10 +89,11 @@ public class TrackerService extends Service implements TrackbookKeys {
} }
}; };
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
} catch (SecurityException e) {
e.printStackTrace();
}
mTimer = new CountDownTimer(CONSTANT_MAXIMAL_DURATION, CONSTANT_TRACKING_INTERVAL) { mTimer = new CountDownTimer(CONSTANT_MAXIMAL_DURATION, CONSTANT_TRACKING_INTERVAL) {
@Override @Override
@ -113,7 +112,11 @@ public class TrackerService extends Service implements TrackbookKeys {
// ACTION STOP // ACTION STOP
else if (intent.getAction().equals(ACTION_STOP)) { else if (intent.getAction().equals(ACTION_STOP)) {
// Remove the listener you previously added // Remove the listener you previously added
mLocationManager.removeUpdates(mLocationListener); try {
mLocationManager.removeUpdates(mLocationListener);
} catch (SecurityException e) {
e.printStackTrace();
}
Log.v(LOG_TAG, "Service received command: STOP"); Log.v(LOG_TAG, "Service received command: STOP");
} }
@ -136,7 +139,11 @@ public class TrackerService extends Service implements TrackbookKeys {
Log.v(LOG_TAG, "onDestroy called."); Log.v(LOG_TAG, "onDestroy called.");
// Remove the listener you previously added // Remove the listener you previously added
mLocationManager.removeUpdates(mLocationListener); try {
mLocationManager.removeUpdates(mLocationListener);
} catch (SecurityException e) {
e.printStackTrace();
}
// cancel notification // cancel notification
stopForeground(true); stopForeground(true);

View File

@ -18,6 +18,7 @@ package org.y20k.trackbook.helpers;
import android.location.Location; import android.location.Location;
import android.location.LocationManager; import android.location.LocationManager;
import android.os.SystemClock;
import java.util.List; import java.util.List;
@ -27,8 +28,13 @@ import java.util.List;
*/ */
public final class LocationHelper { public final class LocationHelper {
/* Define log tag */
private static final String LOG_TAG = LocationHelper.class.getSimpleName();
/* Main class variables */ /* Main class variables */
private static final int TWO_MINUTES = 1000 * 60 * 2; // private static final int TWO_MINUTES = 1000 * 1000 * 60 * 2;
private static final long TWO_MINUTES = 2L * 60000000000L; // 5 minutes
/* Determines last known location */ /* Determines last known location */
@ -64,12 +70,13 @@ public final class LocationHelper {
} }
// return best estimate location // return best estimate location
if (isBetterLocation(gpsLocation, networkLocation)) { if (isBetterLocation(networkLocation, gpsLocation)) {
return gpsLocation; LogHelper.v(LOG_TAG, "Best last known location came from: " + networkLocation.getProvider()); // TODO remove
} else {
return networkLocation; return networkLocation;
} else {
LogHelper.v(LOG_TAG, "Best last known location came from: " + gpsLocation.getProvider()); // TODO remove
return gpsLocation;
} }
} }
@ -83,15 +90,17 @@ public final class LocationHelper {
} }
// check whether the new location fix is newer or older // check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime(); long timeDelta = location.getElapsedRealtimeNanos() - currentBestLocation.getElapsedRealtimeNanos();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0; boolean isNewer = timeDelta > 0;
// if it's been more than two minutes since the current location, use the new location because the user has likely moved // if it's been more than two minutes since the current location, use the new location because the user has likely moved
if (isSignificantlyNewer) { if (isSignificantlyNewer) {
LogHelper.v(LOG_TAG, "Location isSignificantlyNewer: " + location.getProvider()); // TODO remove
return true; return true;
} else if (isSignificantlyOlder) { } else if (isSignificantlyOlder) {
LogHelper.v(LOG_TAG, "Location isSignificantlyOlder: " + location.getProvider()); // TODO remove
return false; return false;
} }
@ -102,21 +111,35 @@ public final class LocationHelper {
boolean isSignificantlyLessAccurate = accuracyDelta > 200; boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// check if the old and new location are from the same provider // check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(), boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
currentBestLocation.getProvider());
// determine location quality using a combination of timeliness and accuracy // determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) { if (isMoreAccurate) {
LogHelper.v(LOG_TAG, "Location isMoreAccurate: " + location.getProvider()); // TODO remove
return true; return true;
} else if (isNewer && !isLessAccurate) { } else if (isNewer && !isLessAccurate) {
LogHelper.v(LOG_TAG, "Location isNewer && !isLessAccurate: " + location.getProvider()); // TODO remove
return true; return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
LogHelper.v(LOG_TAG, "Location isNewer && !isSignificantlyLessAccurate && isFromSameProvider: " + location.getProvider()); // TODO remove
return true; return true;
} }
LogHelper.v(LOG_TAG, "Location is not better: " + location.getProvider()); // TODO remove
return false; return false;
} }
/* Checks if given location is newer than two minutes */
public static boolean isNewLocation(Location location) {
if (location == null) {
return false;
} else {
long locationTime = SystemClock.elapsedRealtimeNanos() - location.getElapsedRealtimeNanos();
return locationTime < TWO_MINUTES;
}
}
/* Checks whether two location providers are the same */ /* Checks whether two location providers are the same */
private static boolean isSameProvider(String provider1, String provider2) { 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 // credit: the isSameProvider method was sample code from: https://developer.android.com/guide/topics/location/strategies.html

View File

@ -39,13 +39,19 @@ public final class MapHelper {
/* Creates icon overlay for current position */ /* Creates icon overlay for current position */
public static ItemizedIconOverlay createMyLocationOverlay(Context context, Location currentBestLocation) { public static ItemizedIconOverlay createMyLocationOverlay(Context context, Location currentBestLocation, boolean locationIsNew) {
final GeoPoint position = new GeoPoint(currentBestLocation.getLatitude(), currentBestLocation.getLongitude()); final GeoPoint position = new GeoPoint(currentBestLocation.getLatitude(), currentBestLocation.getLongitude());
final ArrayList<OverlayItem> overlayItems = new ArrayList<>(); final ArrayList<OverlayItem> overlayItems = new ArrayList<>();
LogHelper.v(LOG_TAG, "Location is new? " + locationIsNew + " Provider: " + currentBestLocation.getProvider()); // TODO remove
// create marker // create marker
Drawable newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_loacation_dot_blue_24dp); Drawable newMarker;
if (locationIsNew) {
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_blue_24dp);
} else {
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp);
}
OverlayItem overlayItem = new OverlayItem(context.getString(R.string.marker_my_location_title), context.getString(R.string.marker_my_location_description), position); OverlayItem overlayItem = new OverlayItem(context.getString(R.string.marker_my_location_title), context.getString(R.string.marker_my_location_description), position);
overlayItem.setMarker(newMarker); overlayItem.setMarker(newMarker);
overlayItems.add(overlayItem); overlayItems.add(overlayItem);

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:viewportHeight="96.0"
android:viewportWidth="96.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillAlpha="0.33" android:fillColor="#2095F2" android:pathData="M48,48m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
<path android:fillColor="#2095F2" android:pathData="M48,48m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="96.0"
android:viewportWidth="96.0"
android:width="24dp">
<path
android:fillAlpha="0.33"
android:fillColor="@color/trackbook_blue"
android:pathData="M48,48m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
<path
android:fillColor="@color/trackbook_blue"
android:pathData="M48,48m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="96.0"
android:viewportWidth="96.0"
android:width="24dp">
<path
android:fillAlpha="0.33"
android:fillColor="@color/trackbook_blue"
android:pathData="M48,48m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
<path
android:fillColor="@color/trackbook_grey_light"
android:pathData="M48,48m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
</vector>

View File

@ -9,4 +9,8 @@
<color name="trackbook_white">#FFFFFFFF</color> <color name="trackbook_white">#FFFFFFFF</color>
<color name="trackbook_grey_light">#FF607d8b</color>
<color name="trackbook_grey">#FF455a64</color>
</resources> </resources>

View File

@ -14,6 +14,7 @@
<string name="toast_message_permissions_granted">Permissions granted.</string> <string name="toast_message_permissions_granted">Permissions granted.</string>
<string name="toast_message_unable_to_start_app">Unable to start Trackbook.</string> <string name="toast_message_unable_to_start_app">Unable to start Trackbook.</string>
<string name="toast_message_location_offline">Location is turned off.</string> <string name="toast_message_location_offline">Location is turned off.</string>
<string name="toast_message_acquiring_location">Acquiring current location.</string>
<string name="toast_message_my_location">My Location.</string> <string name="toast_message_my_location">My Location.</string>
<!-- map markers --> <!-- map markers -->