Trackbook got a notification. Double tracking while showing the map removed. While recording the track is now red. Bug fixes.
This commit is contained in:
parent
f83c651970
commit
3e543444d5
17 changed files with 538 additions and 116 deletions
|
@ -18,13 +18,18 @@ package org.y20k.trackbook;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.location.Location;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
|
@ -55,8 +60,10 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
private boolean mTracking;
|
private boolean mTracking;
|
||||||
private boolean mPermissionsGranted;
|
private boolean mPermissionsGranted;
|
||||||
private List<String> mMissingPermissions;
|
private List<String> mMissingPermissions;
|
||||||
|
private View mRootView;
|
||||||
private FloatingActionButton mFloatingActionButton;
|
private FloatingActionButton mFloatingActionButton;
|
||||||
private MainActivityFragment mMainActivityFragment;
|
private MainActivityFragment mMainActivityFragment;
|
||||||
|
private BroadcastReceiver mTrackingStoppedReceiver;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,7 +73,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
// set state of tracking
|
// set state of tracking
|
||||||
mTracking = false;
|
mTracking = false;
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mTracking = savedInstanceState.getBoolean(INSTANCE_TRACKING_STARTED, false);
|
mTracking = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check permissions on Android 6 and higher
|
// check permissions on Android 6 and higher
|
||||||
|
@ -85,6 +92,11 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
// set up main layout
|
// set up main layout
|
||||||
setupLayout();
|
setupLayout();
|
||||||
|
|
||||||
|
// register broadcast receiver for stopped tracking
|
||||||
|
mTrackingStoppedReceiver = createTrackingStoppedReceiver();
|
||||||
|
IntentFilter trackingStoppedIntentFilter = new IntentFilter(ACTION_TRACKING_STOPPED);
|
||||||
|
LocalBroadcastManager.getInstance(this).registerReceiver(mTrackingStoppedReceiver, trackingStoppedIntentFilter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,9 +114,9 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
// handle action bar options menu selection
|
// handle action bar options menu selection
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
|
||||||
// CASE SETTINGS
|
// CASE ABOUT
|
||||||
case R.id.action_settings:
|
case R.id.action_bar_about:
|
||||||
LogHelper.v(LOG_TAG, "Settings was selected");
|
LogHelper.v(LOG_TAG, "About was selected"); // TODO remove
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// CASE DEFAULT
|
// CASE DEFAULT
|
||||||
|
@ -116,7 +128,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
outState.putBoolean(INSTANCE_TRACKING_STARTED, mTracking);
|
outState.putBoolean(INSTANCE_TRACKING_STATE, mTracking);
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +144,15 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
// disable broadcast receiver
|
||||||
|
LocalBroadcastManager.getInstance(this).unregisterReceiver(mTrackingStoppedReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
|
@ -213,31 +234,33 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
/* Handles tap on the record button */
|
/* Handles tap on the record button */
|
||||||
private void handleFloatingActionButtonClick(View view) {
|
private void handleFloatingActionButtonClick(View view) {
|
||||||
if (mTracking) {
|
if (mTracking) {
|
||||||
|
// show snackbar
|
||||||
Snackbar.make(view, R.string.snackbar_message_tracking_stopped, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
Snackbar.make(view, R.string.snackbar_message_tracking_stopped, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
||||||
|
|
||||||
// change state
|
// change state
|
||||||
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
|
// --> is handled by broadcast receiver
|
||||||
mTracking = false;
|
|
||||||
|
|
||||||
// stop tracker service
|
// stop tracker service
|
||||||
Intent intent = new Intent(this, TrackerService.class);
|
Intent intent = new Intent(this, TrackerService.class);
|
||||||
intent.setAction(ACTION_STOP);
|
intent.setAction(ACTION_STOP);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
LogHelper.v(LOG_TAG, "Stopping tracker service.");
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// show snackbar
|
||||||
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();
|
||||||
|
|
||||||
// change state
|
// change state
|
||||||
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp);
|
|
||||||
mTracking = true;
|
mTracking = true;
|
||||||
|
setFloatingActionButtonState();
|
||||||
|
|
||||||
|
// get last location from MainActivity Fragment
|
||||||
|
Location lastLocation = mMainActivityFragment.getCurrentBestLocation();
|
||||||
|
|
||||||
// start tracker service
|
// start tracker service
|
||||||
Intent intent = new Intent(this, TrackerService.class);
|
Intent intent = new Intent(this, TrackerService.class);
|
||||||
intent.setAction(ACTION_START);
|
intent.setAction(ACTION_START);
|
||||||
|
intent.putExtra(EXTRA_LAST_LOCATION, lastLocation);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
LogHelper.v(LOG_TAG, "Starting tracker service.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update tracking state in MainActivityFragment
|
// update tracking state in MainActivityFragment
|
||||||
|
@ -274,4 +297,20 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Creates receiver for stopped tracking */
|
||||||
|
private BroadcastReceiver createTrackingStoppedReceiver() {
|
||||||
|
return new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
// change state
|
||||||
|
mTracking = false;
|
||||||
|
setFloatingActionButtonState();
|
||||||
|
|
||||||
|
// pass tracking state to MainActivityFragment
|
||||||
|
mMainActivityFragment.setTrackingState(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
private ItemizedIconOverlay mMyLocationOverlay;
|
private ItemizedIconOverlay mMyLocationOverlay;
|
||||||
private ItemizedIconOverlay mTrackOverlay;
|
private ItemizedIconOverlay mTrackOverlay;
|
||||||
private Location mCurrentBestLocation;
|
private Location mCurrentBestLocation;
|
||||||
private boolean mTacking;
|
private boolean mTrackerServiceRunning;
|
||||||
|
private boolean mLocalTrackerRunning;
|
||||||
|
|
||||||
|
|
||||||
/* Constructor (default) */
|
/* Constructor (default) */
|
||||||
|
@ -99,16 +100,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore tracking state
|
// restore tracking state
|
||||||
mTacking = false;
|
mTrackerServiceRunning = false;
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mTacking = savedInstanceState.getBoolean(INSTANCE_TRACKING_STARTED, false);
|
mTrackerServiceRunning = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register broadcast receiver for new WayPoints
|
|
||||||
mTrackUpdatedReceiver = createTrackUpdatedReceiver();
|
|
||||||
IntentFilter trackUpdatedIntentFilter = new IntentFilter(ACTION_TRACK_UPDATED);
|
|
||||||
LocalBroadcastManager.getInstance(mActivity).registerReceiver(mTrackUpdatedReceiver, trackUpdatedIntentFilter);
|
|
||||||
|
|
||||||
// acquire reference to Location Manager
|
// acquire reference to Location Manager
|
||||||
mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
|
mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
|
||||||
|
@ -134,6 +130,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register broadcast receiver for new WayPoints
|
||||||
|
mTrackUpdatedReceiver = createTrackUpdatedReceiver();
|
||||||
|
IntentFilter trackUpdatedIntentFilter = new IntentFilter(ACTION_TRACK_UPDATED);
|
||||||
|
LocalBroadcastManager.getInstance(mActivity).registerReceiver(mTrackUpdatedReceiver, trackUpdatedIntentFilter);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,7 +166,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
mCurrentBestLocation = savedInstanceState.getParcelable(INSTANCE_CURRENT_LOCATION);
|
mCurrentBestLocation = savedInstanceState.getParcelable(INSTANCE_CURRENT_LOCATION);
|
||||||
} else if (mCurrentBestLocation != null) {
|
} else if (mCurrentBestLocation != null) {
|
||||||
// fallback or first run: set map to current position
|
// fallback or first run: set map to current position
|
||||||
GeoPoint position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
GeoPoint position = convertToGeoPoint(mCurrentBestLocation);
|
||||||
mController.setCenter(position);
|
mController.setCenter(position);
|
||||||
mController.setZoom(16);
|
mController.setZoom(16);
|
||||||
}
|
}
|
||||||
|
@ -184,8 +185,8 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
mMapView.getOverlays().add(compassOverlay);
|
mMapView.getOverlays().add(compassOverlay);
|
||||||
|
|
||||||
// mark user's location on map
|
// mark user's location on map
|
||||||
if (mCurrentBestLocation != null) {
|
if (mCurrentBestLocation != null && !mTrackerServiceRunning) {
|
||||||
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation), mTacking);
|
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation));
|
||||||
mMapView.getOverlays().add(mMyLocationOverlay);
|
mMapView.getOverlays().add(mMyLocationOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +198,21 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
// start tracking position
|
// start preliminary tracking - if no TrackerService is running
|
||||||
startFindingLocation();
|
if (!mTrackerServiceRunning) {
|
||||||
|
startPreliminaryTracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
// center map on current position - if TrackerService is running
|
||||||
|
if (mTrackerServiceRunning) {
|
||||||
|
mController.setCenter(convertToGeoPoint(mCurrentBestLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw track on map - if available
|
||||||
|
if (mTrack != null) {
|
||||||
|
drawTrackOverlay(mTrack);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,8 +220,8 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
||||||
// disable location listeners
|
// disable preliminary location listeners
|
||||||
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
|
stopPreliminaryTracking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,9 +229,6 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
public void onDestroyView(){
|
public void onDestroyView(){
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
|
||||||
// unregister broadcast receiver
|
|
||||||
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mTrackUpdatedReceiver);
|
|
||||||
|
|
||||||
// deactivate map
|
// deactivate map
|
||||||
mMapView.onDetach();
|
mMapView.onDetach();
|
||||||
}
|
}
|
||||||
|
@ -228,6 +239,9 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
// reset first start state
|
// reset first start state
|
||||||
mFirstStart = true;
|
mFirstStart = true;
|
||||||
|
|
||||||
|
// disable broadcast receivers
|
||||||
|
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mTrackUpdatedReceiver);
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +253,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
|
||||||
// CASE MY LOCATION
|
// CASE MY LOCATION
|
||||||
case R.id.action_my_location:
|
case R.id.action_bar_my_location:
|
||||||
|
|
||||||
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_my_location), Toast.LENGTH_LONG).show();
|
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_my_location), Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
@ -253,12 +267,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
GeoPoint position;
|
GeoPoint position;
|
||||||
if (mCurrentBestLocation != null) {
|
if (mCurrentBestLocation != null) {
|
||||||
// app has a current best estimate location
|
// app has a current best estimate location
|
||||||
position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
|
||||||
} else {
|
} else {
|
||||||
// app does not have any location fix
|
// app does not have any location fix
|
||||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||||
position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
|
||||||
}
|
}
|
||||||
|
position = convertToGeoPoint(mCurrentBestLocation);
|
||||||
|
|
||||||
// center map on current position
|
// center map on current position
|
||||||
mController.setCenter(position);
|
mController.setCenter(position);
|
||||||
|
@ -284,26 +297,45 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
outState.putInt(INSTANCE_ZOOM_LEVEL, mMapView.getZoomLevel());
|
outState.putInt(INSTANCE_ZOOM_LEVEL, mMapView.getZoomLevel());
|
||||||
outState.putParcelable(INSTANCE_CURRENT_LOCATION, mCurrentBestLocation);
|
outState.putParcelable(INSTANCE_CURRENT_LOCATION, mCurrentBestLocation);
|
||||||
outState.putParcelable(INSTANCE_TRACK, mTrack);
|
outState.putParcelable(INSTANCE_TRACK, mTrack);
|
||||||
outState.putBoolean(INSTANCE_TRACKING_STARTED, mTacking);
|
outState.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Sets tracking state */
|
/* Setter for tracking state */
|
||||||
public void setTrackingState (boolean trackingStarted) {
|
public void setTrackingState (boolean trackingState) {
|
||||||
mTacking = trackingStarted;
|
mTrackerServiceRunning = trackingState;
|
||||||
|
|
||||||
|
// turn on/off tracking for MainActivity Fragment - prevent double tracking
|
||||||
|
if (mTrackerServiceRunning) {
|
||||||
|
stopPreliminaryTracking();
|
||||||
|
} else if (!mLocalTrackerRunning){
|
||||||
|
startPreliminaryTracking();
|
||||||
|
if (mTrack != null) {
|
||||||
|
drawTrackOverlay(mTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update marker
|
||||||
updateMyLocationMarker();
|
updateMyLocationMarker();
|
||||||
|
LogHelper.v(LOG_TAG, "TrackingState: " + trackingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Start finding location for map */
|
/* Getter for current best location */
|
||||||
private void startFindingLocation() {
|
public Location getCurrentBestLocation() {
|
||||||
|
return mCurrentBestLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Start preliminary tracking for map */
|
||||||
|
private void startPreliminaryTracking() {
|
||||||
|
mLocalTrackerRunning = true;
|
||||||
// create location listeners
|
// create location listeners
|
||||||
List locationProviders = mLocationManager.getProviders(true);
|
List locationProviders = mLocationManager.getProviders(true);
|
||||||
if (locationProviders.contains(LocationManager.GPS_PROVIDER)) {
|
if (locationProviders.contains(LocationManager.GPS_PROVIDER)) {
|
||||||
mGPSListener = createLocationListener();
|
mGPSListener = createLocationListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locationProviders.contains(LocationManager.NETWORK_PROVIDER)) {
|
if (locationProviders.contains(LocationManager.NETWORK_PROVIDER)) {
|
||||||
mNetworkListener = createLocationListener();
|
mNetworkListener = createLocationListener();
|
||||||
}
|
}
|
||||||
|
@ -313,6 +345,14 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Removes gps and network location listeners */
|
||||||
|
private void stopPreliminaryTracking() {
|
||||||
|
mLocalTrackerRunning = false;
|
||||||
|
// remove listeners
|
||||||
|
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Creates listener for changes in location status */
|
/* Creates listener for changes in location status */
|
||||||
private LocationListener createLocationListener() {
|
private LocationListener createLocationListener() {
|
||||||
return new LocationListener() {
|
return new LocationListener() {
|
||||||
|
@ -321,7 +361,6 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
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
|
||||||
updateMyLocationMarker();
|
updateMyLocationMarker();
|
||||||
}
|
}
|
||||||
|
@ -345,15 +384,18 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
/* Updates marker for current user location */
|
/* Updates marker for current user location */
|
||||||
private void updateMyLocationMarker() {
|
private void updateMyLocationMarker() {
|
||||||
mMapView.getOverlays().remove(mMyLocationOverlay);
|
mMapView.getOverlays().remove(mMyLocationOverlay);
|
||||||
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation),mTacking);
|
// only update while not tracking
|
||||||
mMapView.getOverlays().add(mMyLocationOverlay);
|
if (!mTrackerServiceRunning) {
|
||||||
|
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation));
|
||||||
|
mMapView.getOverlays().add(mMyLocationOverlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Draws track onto overlay */
|
/* Draws track onto overlay */
|
||||||
private void drawTrackOverlay(Track track) {
|
private void drawTrackOverlay(Track track) {
|
||||||
mMapView.getOverlays().remove(mTrackOverlay);
|
mMapView.getOverlays().remove(mTrackOverlay);
|
||||||
mTrackOverlay = MapHelper.createTrackOverlay(mActivity, track);
|
mTrackOverlay = MapHelper.createTrackOverlay(mActivity, track, mTrackerServiceRunning);
|
||||||
mMapView.getOverlays().add(mTrackOverlay);
|
mMapView.getOverlays().add(mTrackOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,16 +412,29 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||||
return new BroadcastReceiver() {
|
return new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.hasExtra(EXTRA_TRACK)) {
|
if (intent.hasExtra(EXTRA_TRACK) && intent.hasExtra(EXTRA_LAST_LOCATION)) {
|
||||||
|
// draw track on map
|
||||||
mTrack = intent.getParcelableExtra(EXTRA_TRACK);
|
mTrack = intent.getParcelableExtra(EXTRA_TRACK);
|
||||||
drawTrackOverlay(mTrack);
|
drawTrackOverlay(mTrack);
|
||||||
Toast.makeText(mActivity, "New WayPoint.", Toast.LENGTH_LONG).show(); // TODO Remove
|
Toast.makeText(mActivity, "New WayPoint.", Toast.LENGTH_LONG).show(); // TODO Remove
|
||||||
|
// center map over last location
|
||||||
|
mCurrentBestLocation = intent.getParcelableExtra(EXTRA_LAST_LOCATION);
|
||||||
|
mController.setCenter(convertToGeoPoint(mCurrentBestLocation));
|
||||||
|
// clear intent
|
||||||
|
intent.removeExtra(EXTRA_TRACK);
|
||||||
|
intent.removeExtra(EXTRA_LAST_LOCATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Converts Location to GeoPoint */
|
||||||
|
private GeoPoint convertToGeoPoint (Location location) {
|
||||||
|
return new GeoPoint(location.getLatitude(), location.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Saves state of map */
|
/* Saves state of map */
|
||||||
private void saveMaoState(Context context) {
|
private void saveMaoState(Context context) {
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.y20k.trackbook.core.Track;
|
||||||
import org.y20k.trackbook.core.WayPoint;
|
import org.y20k.trackbook.core.WayPoint;
|
||||||
import org.y20k.trackbook.helpers.LocationHelper;
|
import org.y20k.trackbook.helpers.LocationHelper;
|
||||||
import org.y20k.trackbook.helpers.LogHelper;
|
import org.y20k.trackbook.helpers.LogHelper;
|
||||||
|
import org.y20k.trackbook.helpers.NotificationHelper;
|
||||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -73,27 +74,40 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
// create a new track
|
// create a new track
|
||||||
mTrack = new Track();
|
mTrack = new Track();
|
||||||
|
|
||||||
// add first location to track
|
// get last location
|
||||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
if (intent.hasExtra(EXTRA_LAST_LOCATION)) {
|
||||||
|
mCurrentBestLocation = intent.getParcelableExtra(EXTRA_LAST_LOCATION);
|
||||||
|
}
|
||||||
|
// get last location - fallback
|
||||||
|
if (mCurrentBestLocation == null) {
|
||||||
|
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add last location as waypoint to track
|
||||||
addWayPointToTrack();
|
addWayPointToTrack();
|
||||||
|
|
||||||
// set timer to retrieve new locations and to prevent endless tracking
|
// set timer to retrieve new locations and to prevent endless tracking
|
||||||
mTimer = new CountDownTimer(CONSTANT_MAXIMAL_DURATION, CONSTANT_TRACKING_INTERVAL) {
|
mTimer = new CountDownTimer(EIGHT_HOURS_IN_MILLISECONDS, FIFTEEN_SECONDS_IN_MILLISECONDS) {
|
||||||
@Override
|
@Override
|
||||||
public void onTick(long l) {
|
public void onTick(long millisUntilFinished) {
|
||||||
|
// update track duration
|
||||||
|
mTrack.setTrackDuration(EIGHT_HOURS_IN_MILLISECONDS - millisUntilFinished);
|
||||||
|
// try to add WayPoint to Track
|
||||||
addWayPointToTrack();
|
addWayPointToTrack();
|
||||||
|
// update notification
|
||||||
|
NotificationHelper.update(mTrack, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
// TODO
|
// remove listeners
|
||||||
|
stopFindingLocation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mTimer.start();
|
mTimer.start();
|
||||||
|
|
||||||
// create gps and network location listeners
|
// create gps and network location listeners
|
||||||
startFindingLocation();
|
startFindingLocation();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACTION STOP
|
// ACTION STOP
|
||||||
|
@ -104,7 +118,7 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
mTimer.cancel();
|
mTimer.cancel();
|
||||||
|
|
||||||
// remove listeners
|
// remove listeners
|
||||||
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
|
stopFindingLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -124,7 +138,7 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
LogHelper.v(LOG_TAG, "onDestroy called.");
|
LogHelper.v(LOG_TAG, "onDestroy called.");
|
||||||
|
|
||||||
// remove listeners
|
// remove listeners
|
||||||
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
|
stopFindingLocation();
|
||||||
|
|
||||||
// cancel notification
|
// cancel notification
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
@ -162,6 +176,7 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setAction(ACTION_TRACK_UPDATED);
|
i.setAction(ACTION_TRACK_UPDATED);
|
||||||
i.putExtra(EXTRA_TRACK, mTrack);
|
i.putExtra(EXTRA_TRACK, mTrack);
|
||||||
|
i.putExtra(EXTRA_LAST_LOCATION, mCurrentBestLocation);
|
||||||
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,11 +200,11 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onProviderEnabled(String provider) {
|
public void onProviderEnabled(String provider) {
|
||||||
// TODO do something
|
LogHelper.v(LOG_TAG, "Location provider enabled: " + provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onProviderDisabled(String provider) {
|
public void onProviderDisabled(String provider) {
|
||||||
// TODO do something
|
LogHelper.v(LOG_TAG, "Location provider disabled: " + provider);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -197,7 +212,9 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
|
|
||||||
/* Creates gps and network location listeners */
|
/* Creates gps and network location listeners */
|
||||||
private void startFindingLocation() {
|
private void startFindingLocation() {
|
||||||
LogHelper.v(LOG_TAG, "Setting up location listeners.");
|
LogHelper.v(LOG_TAG, "startFindingLocation"); // TODO remove
|
||||||
|
// put up notification
|
||||||
|
NotificationHelper.show(this,mTrack);
|
||||||
|
|
||||||
// register location listeners and request updates
|
// register location listeners and request updates
|
||||||
List locationProviders = mLocationManager.getProviders(true);
|
List locationProviders = mLocationManager.getProviders(true);
|
||||||
|
@ -210,4 +227,24 @@ public class TrackerService extends Service implements TrackbookKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Removes gps and network location listeners */
|
||||||
|
private void stopFindingLocation() {
|
||||||
|
LogHelper.v(LOG_TAG, "stopFindingLocation"); // TODO remove
|
||||||
|
// remove listeners
|
||||||
|
LocationHelper.removeLocationListeners(mLocationManager, mGPSListener, mNetworkListener);
|
||||||
|
|
||||||
|
// notify MainActivityFragment
|
||||||
|
Intent i = new Intent();
|
||||||
|
i.setAction(ACTION_TRACKING_STOPPED);
|
||||||
|
i.putExtra(EXTRA_TRACK, mTrack);
|
||||||
|
i.putExtra(EXTRA_LAST_LOCATION, mCurrentBestLocation);
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
|
||||||
|
|
||||||
|
// // cancel notification
|
||||||
|
// NotificationHelper.stop();
|
||||||
|
// change notification
|
||||||
|
NotificationHelper.update(mTrack, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package org.y20k.trackbook.core;
|
package org.y20k.trackbook.core;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
@ -27,6 +26,7 @@ import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,9 +39,9 @@ public class Track implements TrackbookKeys, Parcelable {
|
||||||
|
|
||||||
|
|
||||||
/* Main class variables */
|
/* Main class variables */
|
||||||
private Context mContext;
|
|
||||||
private List<WayPoint> mWayPoints;
|
private List<WayPoint> mWayPoints;
|
||||||
private float mTrackLength;
|
private float mTrackLength;
|
||||||
|
private long mTrackDuration;
|
||||||
|
|
||||||
|
|
||||||
/* Constructor */
|
/* Constructor */
|
||||||
|
@ -72,12 +72,6 @@ public class Track implements TrackbookKeys, Parcelable {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Set mContext needed by */
|
|
||||||
public void setContext(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adds new waypoint */
|
/* Adds new waypoint */
|
||||||
public WayPoint addWayPoint(Location location) {
|
public WayPoint addWayPoint(Location location) {
|
||||||
// add up distance
|
// add up distance
|
||||||
|
@ -105,6 +99,12 @@ public class Track implements TrackbookKeys, Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Setter for duration of track */
|
||||||
|
public void setTrackDuration(long trackDuration) {
|
||||||
|
mTrackDuration = trackDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Getter for mWayPoints */
|
/* Getter for mWayPoints */
|
||||||
public List<WayPoint> getWayPoints() {
|
public List<WayPoint> getWayPoints() {
|
||||||
return mWayPoints;
|
return mWayPoints;
|
||||||
|
@ -117,12 +117,25 @@ public class Track implements TrackbookKeys, Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Getter for duration of track */
|
||||||
|
public String getTrackDuration() {
|
||||||
|
return convertToReadableTime(mTrackDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Getter for distance of track */
|
||||||
|
public String getTrackDistance() {
|
||||||
|
float trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint();
|
||||||
|
|
||||||
|
return String.format ("%.0f", trackDistance) + "m";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Getter for location of specific WayPoint */
|
/* Getter for location of specific WayPoint */
|
||||||
public Location getWayPointLocation(int index) {
|
public Location getWayPointLocation(int index) {
|
||||||
return mWayPoints.get(index).getLocation();
|
return mWayPoints.get(index).getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Adds distance to given location to length of track */
|
/* Adds distance to given location to length of track */
|
||||||
private float addDistanceToTrack(Location location) {
|
private float addDistanceToTrack(Location location) {
|
||||||
// get number of previously recorded waypoints
|
// get number of previously recorded waypoints
|
||||||
|
@ -139,6 +152,14 @@ public class Track implements TrackbookKeys, Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Converts milliseconds to hh:mm:ss */
|
||||||
|
private String convertToReadableTime(long milliseconds) {
|
||||||
|
return String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(milliseconds),
|
||||||
|
TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1),
|
||||||
|
TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -27,19 +27,12 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
* LocationHelper class
|
* LocationHelper class
|
||||||
*/
|
*/
|
||||||
public final class LocationHelper {
|
public final class LocationHelper implements TrackbookKeys {
|
||||||
|
|
||||||
/* Define log tag */
|
/* Define log tag */
|
||||||
private static final String LOG_TAG = LocationHelper.class.getSimpleName();
|
private static final String LOG_TAG = LocationHelper.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
/* Main class variables */
|
|
||||||
// private static final int TWO_MINUTES = 1000 * 1000 * 60 * 2;
|
|
||||||
private static final long FIVE_MINUTES = 5L * 60000000000L; // 2 minutes
|
|
||||||
private static final long TWO_MINUTES = 2L * 60000000000L; // 2 minutes
|
|
||||||
private static final long TWENTY_SECONDS = 20000000000L; // 20 seconds
|
|
||||||
|
|
||||||
|
|
||||||
/* Determines last known location */
|
/* Determines last known location */
|
||||||
public static Location determineLastKnownLocation(LocationManager locationManager) {
|
public static Location determineLastKnownLocation(LocationManager locationManager) {
|
||||||
// define variables
|
// define variables
|
||||||
|
@ -72,13 +65,14 @@ public final class LocationHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return best estimate location
|
if (gpsLocation == null) {
|
||||||
if (isBetterLocation(networkLocation, gpsLocation)) {
|
|
||||||
LogHelper.v(LOG_TAG, "Best last known location came from: " + networkLocation.getProvider()); // TODO remove
|
|
||||||
return networkLocation;
|
return networkLocation;
|
||||||
} else {
|
} else if (networkLocation == null) {
|
||||||
LogHelper.v(LOG_TAG, "Best last known location came from: " + gpsLocation.getProvider()); // TODO remove
|
|
||||||
return gpsLocation;
|
return gpsLocation;
|
||||||
|
} else if (isBetterLocation(gpsLocation, networkLocation)) {
|
||||||
|
return gpsLocation;
|
||||||
|
} else {
|
||||||
|
return networkLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +88,8 @@ 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.getElapsedRealtimeNanos() - currentBestLocation.getElapsedRealtimeNanos();
|
long timeDelta = location.getElapsedRealtimeNanos() - currentBestLocation.getElapsedRealtimeNanos();
|
||||||
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
|
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES_IN_NANOSECONDS;
|
||||||
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
|
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES_IN_NANOSECONDS;
|
||||||
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
|
||||||
|
@ -118,16 +112,12 @@ public final class LocationHelper {
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +128,7 @@ public final class LocationHelper {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
long locationTime = SystemClock.elapsedRealtimeNanos() - location.getElapsedRealtimeNanos();
|
long locationTime = SystemClock.elapsedRealtimeNanos() - location.getElapsedRealtimeNanos();
|
||||||
return locationTime < TWO_MINUTES;
|
return locationTime < TWO_MINUTES_IN_NANOSECONDS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,15 +138,15 @@ public final class LocationHelper {
|
||||||
float distance = newLocation.distanceTo(lastLocation);
|
float distance = newLocation.distanceTo(lastLocation);
|
||||||
long timeDifference = newLocation.getElapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos();
|
long timeDifference = newLocation.getElapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos();
|
||||||
|
|
||||||
// distance is bigger than 10 meters and time difference bigger than 20 seconds
|
// distance is bigger than 10 meters and time difference bigger than 12 seconds
|
||||||
return distance > 10 && timeDifference >= TWENTY_SECONDS;
|
return distance > 10 && timeDifference >= TWELVE_SECONDS_IN_NANOSECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Checks if given location is a stop over */
|
/* Checks if given location is a stop over */
|
||||||
public static boolean isStopOver(Location lastLocation, Location newLocation) {
|
public static boolean isStopOver(Location lastLocation, Location newLocation) {
|
||||||
long timeDifference = newLocation.getElapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos();
|
long timeDifference = newLocation.getElapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos();
|
||||||
return timeDifference >= FIVE_MINUTES;
|
return timeDifference >= FIVE_MINUTES_IN_NANOSECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.support.v7.widget.AppCompatDrawableManager;
|
import android.support.v7.widget.AppCompatDrawableManager;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
||||||
|
@ -42,17 +43,14 @@ public final class MapHelper {
|
||||||
private static final String LOG_TAG = MapHelper.class.getSimpleName();
|
private static final String LOG_TAG = MapHelper.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
/* Creates icon overlay for current position */
|
/* Creates icon overlay for current position (used in MainActivity Fragment) */
|
||||||
public static ItemizedIconOverlay createMyLocationOverlay(Context context, Location currentBestLocation, boolean locationIsNew, boolean trackingStarted) {
|
public static ItemizedIconOverlay createMyLocationOverlay(Context context, Location currentBestLocation, boolean locationIsNew) {
|
||||||
|
|
||||||
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;
|
Drawable newMarker;
|
||||||
if (trackingStarted) {
|
if (locationIsNew) {
|
||||||
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_red_24dp);
|
|
||||||
} else if (locationIsNew) {
|
|
||||||
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_blue_24dp);
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_blue_24dp);
|
||||||
} else {
|
} else {
|
||||||
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp);
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp);
|
||||||
|
@ -83,20 +81,62 @@ public final class MapHelper {
|
||||||
|
|
||||||
|
|
||||||
/* Creates icon overlay for track */
|
/* Creates icon overlay for track */
|
||||||
public static ItemizedIconOverlay createTrackOverlay(Context context, Track track){
|
public static ItemizedIconOverlay createTrackOverlay(final Context context, Track track, boolean trackingActive){
|
||||||
|
|
||||||
|
WayPoint wayPoint;
|
||||||
|
boolean currentPosition;
|
||||||
|
final int trackSize = track.getSize();
|
||||||
final List<WayPoint> wayPoints = track.getWayPoints();
|
final List<WayPoint> wayPoints = track.getWayPoints();
|
||||||
final ArrayList<OverlayItem> overlayItems = new ArrayList<>();
|
final ArrayList<OverlayItem> overlayItems = new ArrayList<>();
|
||||||
|
|
||||||
for (WayPoint wayPoint : wayPoints) {
|
for (int i = 0 ; i < track.getSize() ; i++) {
|
||||||
|
// get waypoint and check if it is current position
|
||||||
|
wayPoint = wayPoints.get(i);
|
||||||
|
currentPosition = i == trackSize - 1;
|
||||||
|
|
||||||
// create marker
|
// create marker
|
||||||
Drawable newMarker;
|
Drawable newMarker;
|
||||||
if (wayPoint.getIsStopOver()) {
|
|
||||||
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_grey_24dp);
|
// CASE 1: Tracking active and waypoint is not current position
|
||||||
} else {
|
if (trackingActive && !currentPosition) {
|
||||||
|
if (wayPoint.getIsStopOver()) {
|
||||||
|
// stop over marker
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_grey_24dp);
|
||||||
|
} else {
|
||||||
|
// default marker for this case
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_red_24dp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE 2: Tracking active and waypoint is current position
|
||||||
|
else if (trackingActive && currentPosition) {
|
||||||
|
if (wayPoint.getIsStopOver()) {
|
||||||
|
// stop over marker
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp);
|
||||||
|
} else {
|
||||||
|
// default marker for this case
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_dot_red_24dp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE 3: Tracking not active and waypoint is not current position
|
||||||
|
else if (!trackingActive && !currentPosition) {
|
||||||
|
if (wayPoint.getIsStopOver()) {
|
||||||
|
// stop over marker
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_grey_24dp);
|
||||||
|
} else {
|
||||||
|
// default marker for this case
|
||||||
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_blue_24dp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE 4: Tracking not active and waypoint is current position
|
||||||
|
else {
|
||||||
|
// default marker
|
||||||
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_blue_24dp);
|
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_blue_24dp);
|
||||||
}
|
}
|
||||||
final String title = Float.toString(wayPoint.getDistanceToStartingPoint());
|
|
||||||
|
final String title = Float.toString(wayPoint.getDistanceToStartingPoint()) + " (" + wayPoint.getLocation().getProvider() + ")";
|
||||||
final String description = DateFormat.getDateFormat(context).format(wayPoint.getLocation().getTime());
|
final String description = DateFormat.getDateFormat(context).format(wayPoint.getLocation().getTime());
|
||||||
final GeoPoint position = new GeoPoint(wayPoint.getLocation().getLatitude(), wayPoint.getLocation().getLongitude());
|
final GeoPoint position = new GeoPoint(wayPoint.getLocation().getLatitude(), wayPoint.getLocation().getLongitude());
|
||||||
OverlayItem overlayItem = new OverlayItem(title, description, position);
|
OverlayItem overlayItem = new OverlayItem(title, description, position);
|
||||||
|
@ -111,6 +151,7 @@ public final class MapHelper {
|
||||||
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
|
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
|
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
|
||||||
|
Toast.makeText(context, "Measured distance: " + item.getTitle(), Toast.LENGTH_LONG).show(); // TODO make string
|
||||||
LogHelper.v(LOG_TAG, "Tap on a track crumb icon detected. Measured distance: " + item.getTitle());
|
LogHelper.v(LOG_TAG, "Tap on a track crumb icon detected. Measured distance: " + item.getTitle());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +166,4 @@ public final class MapHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,177 @@
|
||||||
|
/**
|
||||||
|
* NotificationHelper.java
|
||||||
|
* Implements the NotificationHelper class
|
||||||
|
* A NotificationHelper creates and configures a notification
|
||||||
|
*
|
||||||
|
* This file is part of
|
||||||
|
* TRACKBOOK - Movement Recorder for Android
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 - Y20K.org
|
||||||
|
* Licensed under the MIT-License
|
||||||
|
* http://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
|
||||||
|
* https://github.com/osmdroid/osmdroid
|
||||||
|
*/
|
||||||
|
|
||||||
package org.y20k.trackbook.helpers;
|
package org.y20k.trackbook.helpers;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.support.graphics.drawable.VectorDrawableCompat;
|
||||||
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
|
import android.support.v7.app.NotificationCompat;
|
||||||
|
|
||||||
|
import org.y20k.trackbook.MainActivity;
|
||||||
|
import org.y20k.trackbook.R;
|
||||||
|
import org.y20k.trackbook.TrackerService;
|
||||||
|
import org.y20k.trackbook.core.Track;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by solaris on 29/07/16.
|
* NotificationHelper class
|
||||||
*/
|
*/
|
||||||
public class NotificationHelper {
|
public class NotificationHelper implements TrackbookKeys {
|
||||||
|
|
||||||
|
/* Define log tag */
|
||||||
|
private static final String LOG_TAG = NotificationHelper.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
|
/* Main class variables */
|
||||||
|
private static Notification mNotification;
|
||||||
|
private static Service mService;
|
||||||
|
|
||||||
|
/* Create and put up notification */
|
||||||
|
public static void show(final Service service, Track track) {
|
||||||
|
// save service
|
||||||
|
mService = service;
|
||||||
|
|
||||||
|
// build notification
|
||||||
|
mNotification = getNotificationBuilder(track, true).build();
|
||||||
|
|
||||||
|
// display notification
|
||||||
|
mService.startForeground(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Updates the notification */
|
||||||
|
public static void update(Track track, boolean tracking) {
|
||||||
|
|
||||||
|
// build notification
|
||||||
|
mNotification = getNotificationBuilder(track, tracking).build();
|
||||||
|
|
||||||
|
// display updated notification
|
||||||
|
NotificationManager notificationManager = (NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.notify(TRACKER_SERVICE_NOTIFICATION_ID, mNotification);
|
||||||
|
|
||||||
|
if (!tracking) {
|
||||||
|
// make notification swipe-able
|
||||||
|
mService.stopForeground(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Stop displaying notification */
|
||||||
|
public static void stop() {
|
||||||
|
if (mService != null) {
|
||||||
|
mService.stopForeground(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Creates a notification builder */
|
||||||
|
private static NotificationCompat.Builder getNotificationBuilder(Track track, boolean tracking) {
|
||||||
|
|
||||||
|
String contentText = mService.getString(R.string.notification_content_distance) + ": " + track.getTrackDistance() + " | " +
|
||||||
|
mService.getString(R.string.notification_content_duration) + " : " + track.getTrackDuration();
|
||||||
|
|
||||||
|
// explicit intent for notification tap
|
||||||
|
Intent tapActionIntent = new Intent(mService, MainActivity.class);
|
||||||
|
|
||||||
|
// explicit intent for stopping playback
|
||||||
|
Intent stopActionIntent = new Intent(mService, TrackerService.class);
|
||||||
|
stopActionIntent.setAction(ACTION_STOP);
|
||||||
|
|
||||||
|
// artificial back stack for started Activity.
|
||||||
|
// -> navigating backward from the Activity leads to Home screen.
|
||||||
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mService);
|
||||||
|
// // backstack: adds back stack for Intent (but not the Intent itself)
|
||||||
|
// stackBuilder.addParentStack(MainActivity.class);
|
||||||
|
// backstack: add explicit intent for notification tap
|
||||||
|
stackBuilder.addNextIntent(tapActionIntent);
|
||||||
|
|
||||||
|
// pending intent wrapper for notification tap
|
||||||
|
PendingIntent tapActionPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
// pending intent wrapper for notification stop action
|
||||||
|
PendingIntent stopActionPendingIntent = PendingIntent.getService(mService, 0, stopActionIntent, 0);
|
||||||
|
|
||||||
|
// construct notification in builder
|
||||||
|
NotificationCompat.Builder builder;
|
||||||
|
builder = new NotificationCompat.Builder(mService);
|
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
||||||
|
builder.setShowWhen(false);
|
||||||
|
builder.setContentIntent(tapActionPendingIntent);
|
||||||
|
builder.setSmallIcon(R.drawable.ic_notification_small_24dp);
|
||||||
|
builder.setLargeIcon(getNotificationIconLarge(tracking));
|
||||||
|
if (tracking) {
|
||||||
|
builder.addAction(R.drawable.ic_stop_white_36dp, mService.getString(R.string.notification_stop), stopActionPendingIntent);
|
||||||
|
builder.setContentTitle(mService.getString(R.string.notification_title_trackbook_running));
|
||||||
|
builder.setContentText(contentText);
|
||||||
|
// third line of text - only appears in expanded view
|
||||||
|
// builder.setSubText();
|
||||||
|
} else {
|
||||||
|
builder.setContentTitle(mService.getString(R.string.notification_title_trackbook_not_running));
|
||||||
|
builder.setContentText(contentText);
|
||||||
|
// third line of text - only appears in expanded view
|
||||||
|
// builder.setSubText();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get station image for notification's large icon */
|
||||||
|
private static Bitmap getNotificationIconLarge(boolean tracking) {
|
||||||
|
|
||||||
|
// get dimensions
|
||||||
|
Resources resources = mService.getResources();
|
||||||
|
int height = (int) resources.getDimension(android.R.dimen.notification_large_icon_height);
|
||||||
|
int width = (int) resources.getDimension(android.R.dimen.notification_large_icon_width);
|
||||||
|
|
||||||
|
Bitmap bitmap;
|
||||||
|
if (tracking) {
|
||||||
|
bitmap = getBitmap(R.drawable.ic_notification_large_tracking_48dp);
|
||||||
|
} else {
|
||||||
|
bitmap = getBitmap(R.drawable.ic_notification_large_not_tracking_48dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bitmap.createScaledBitmap(bitmap, width, height, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a bitmap for a given resource id of a vector drawable */
|
||||||
|
private static Bitmap getBitmap(int resource) {
|
||||||
|
VectorDrawableCompat drawable = VectorDrawableCompat.create(mService.getResources(), resource, null);
|
||||||
|
if (drawable != null) {
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
return bitmap;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,11 @@ public interface TrackbookKeys {
|
||||||
public static final String ACTION_START = "org.y20k.transistor.action.START";
|
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_STOP = "org.y20k.transistor.action.STOP";
|
||||||
public static final String ACTION_TRACK_UPDATED = "TRACK_UPDATED";
|
public static final String ACTION_TRACK_UPDATED = "TRACK_UPDATED";
|
||||||
|
public static final String ACTION_TRACKING_STOPPED = "TRACKING_STOPPED";
|
||||||
|
|
||||||
/* EXTRAS */
|
/* EXTRAS */
|
||||||
public static final String EXTRA_TRACK = "TRACK";
|
public static final String EXTRA_TRACK = "TRACK";
|
||||||
|
public static final String EXTRA_LAST_LOCATION = "LAST_LOCATION";
|
||||||
|
|
||||||
/* ARGS */
|
/* ARGS */
|
||||||
public static final String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";
|
public static final String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";
|
||||||
|
@ -48,21 +50,21 @@ public interface TrackbookKeys {
|
||||||
public static final String INSTANCE_LONGITUDE = "longitude";
|
public static final String INSTANCE_LONGITUDE = "longitude";
|
||||||
public static final String INSTANCE_ZOOM_LEVEL = "zoomLevel";
|
public static final String INSTANCE_ZOOM_LEVEL = "zoomLevel";
|
||||||
public static final String INSTANCE_CURRENT_LOCATION = "currentLocation";
|
public static final String INSTANCE_CURRENT_LOCATION = "currentLocation";
|
||||||
public static final String INSTANCE_TRACKING_STARTED = "trackingStarted";
|
public static final String INSTANCE_TRACKING_STATE = "trackingState";
|
||||||
public static final String INSTANCE_TRACK = "track";
|
public static final String INSTANCE_TRACK = "track";
|
||||||
|
|
||||||
/* RESULTS */
|
/* RESULTS */
|
||||||
|
|
||||||
/* CONSTANTS */
|
/* CONSTANTS */
|
||||||
public static final int CONSTANT_MINIMAL_STOP_TIME = 300000; // equals 5 minutes
|
public static final long EIGHT_HOURS_IN_MILLISECONDS = 43200000; // maximum tracking duration
|
||||||
public static final long CONSTANT_MAXIMAL_DURATION = 43200000; // equals 8 hours
|
public static final long FIFTEEN_SECONDS_IN_MILLISECONDS = 15000; // timer interval for tracking
|
||||||
public static final long CONSTANT_TRACKING_INTERVAL = 15000; // equals 15 seconds
|
public static final long FIVE_MINUTES_IN_NANOSECONDS = 5L * 60000000000L; // determines a stop over
|
||||||
|
public static final long TWO_MINUTES_IN_NANOSECONDS = 2L * 60000000000L; // defines an old location
|
||||||
|
public static final long TWELVE_SECONDS_IN_NANOSECONDS = 12000000000L; // defines a new location
|
||||||
|
|
||||||
|
|
||||||
/* MISC */
|
/* MISC */
|
||||||
public static final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
public static final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
||||||
public static final int LOCATION_STATUS_OFFLINE = 0;
|
public static final int TRACKER_SERVICE_NOTIFICATION_ID = 1;
|
||||||
public static final int LOCATION_STATUS_OK = 1;
|
|
||||||
public static final int LOCATION_STATUS_GPS_ONLY = 2;
|
|
||||||
public static final int LOCATION_STATUS_NETWORK_ONLY = 3;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
10
app/src/main/res/drawable/ic_my_location_crumb_red_24dp.xml
Normal file
10
app/src/main/res/drawable/ic_my_location_crumb_red_24dp.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<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:fillColor="@color/trackbook_red"
|
||||||
|
android:pathData="M48,48m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:alpha="0.01" android:height="24dp"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M6,6h12v12H6z"/>
|
||||||
|
</vector>
|
|
@ -4,6 +4,6 @@
|
||||||
android:viewportWidth="24.0"
|
android:viewportWidth="24.0"
|
||||||
android:viewportHeight="24.0">
|
android:viewportHeight="24.0">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFFFF"
|
android:fillColor="@color/trackbook_white"
|
||||||
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
|
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportHeight="192.0"
|
||||||
|
android:viewportWidth="192.0"
|
||||||
|
android:width="48dp" >
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_blue"
|
||||||
|
android:pathData="M96,96m-96,0a96,96 0,1 1,192 0a96,96 0,1 1,-192 0"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_white"
|
||||||
|
android:pathData="M48,96a48,46.5 0,1 0,96 0a48,46.5 0,1 0,-96 0z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportHeight="192.0"
|
||||||
|
android:viewportWidth="192.0"
|
||||||
|
android:width="48dp" >
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_blue"
|
||||||
|
android:pathData="M96,96m-96,0a96,96 0,1 1,192 0a96,96 0,1 1,-192 0"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_red_dark"
|
||||||
|
android:pathData="M48,96a48,46.5 0,1 0,96 0a48,46.5 0,1 0,-96 0z"/>
|
||||||
|
</vector>
|
12
app/src/main/res/drawable/ic_notification_small_24dp.xml
Normal file
12
app/src/main/res/drawable/ic_notification_small_24dp.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:viewportHeight="96.0"
|
||||||
|
android:viewportWidth="96.0"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_white"
|
||||||
|
android:pathData="M44,12.99L20.69,8.74L5.12,5.89C2.29,5.38 0,7.44 0,10.49v67.38c0,3.06 2.29,5.96 5.12,6.47l15.57,2.85l22.19,4.05L44,91.46V12.99z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_white"
|
||||||
|
android:pathData="M90.88,5.89L75.31,8.74L53.12,12.79L52,12.99v78.46l23.31,-4.26l15.57,-2.85c2.83,-0.52 5.12,-3.41 5.12,-6.47V10.49C96,7.44 93.71,5.38 90.88,5.89z"/>
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_stop_white_36dp.xml
Normal file
10
app/src/main/res/drawable/ic_stop_white_36dp.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="36dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:width="36dp">
|
||||||
|
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/trackbook_white"
|
||||||
|
android:pathData="M6,6h12v12H6z"/>
|
||||||
|
</vector>
|
|
@ -4,16 +4,16 @@
|
||||||
tools:context="org.y20k.trackbook.MainActivity">
|
tools:context="org.y20k.trackbook.MainActivity">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_my_location"
|
android:id="@+id/action_bar_my_location"
|
||||||
android:icon="@drawable/ic_my_location_white_24dp"
|
android:icon="@drawable/ic_my_location_white_24dp"
|
||||||
android:title="@string/menu_my_location"
|
android:title="@string/menu_my_location"
|
||||||
android:visible="true"
|
android:visible="true"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_bar_about"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
android:title="@string/menu_settings"
|
android:title="@string/menu_about"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
<string name="app_name">Trackbook</string>
|
<string name="app_name">Trackbook</string>
|
||||||
|
|
||||||
<!-- menu entries -->
|
<!-- menu entries -->
|
||||||
<string name="menu_settings">Settings</string>
|
|
||||||
<string name="menu_my_location">My Location</string>
|
<string name="menu_my_location">My Location</string>
|
||||||
|
<string name="menu_about">About</string>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- notification -->
|
||||||
|
<string name="notification_title_trackbook_running">Trackbook running</string>
|
||||||
|
<string name="notification_title_trackbook_not_running">Trackbook not running</string>
|
||||||
|
<string name="notification_stop">Stop</string>
|
||||||
|
<string name="notification_content_duration">Duration</string>
|
||||||
|
<string name="notification_content_distance">Distance</string>
|
||||||
|
|
||||||
<!-- snackbar messages -->
|
<!-- snackbar messages -->
|
||||||
<string name="snackbar_message_tracking_stopped">Tracking stopped</string>
|
<string name="snackbar_message_tracking_stopped">Tracking stopped</string>
|
||||||
|
|
Loading…
Reference in a new issue