diff --git a/app/build.gradle b/app/build.gradle index c291f01..c8f1a64 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,9 @@ apply plugin: 'com.android.application' android { + compileSdkVersion project.ext.compileSdkVersion - buildToolsVersion project.ext.buildToolsVersion + // buildToolsVersion is optional because the plugin uses a recommended version by default defaultConfig { applicationId project.ext.applicationId @@ -14,26 +15,29 @@ android { vectorDrawables.useSupportLibrary = true resConfigs "en", "de", "id", "it", "ja", "nb-rNO", "nl" } + buildTypes { + release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } - debug { -// minifyEnabled true -// shrinkResources true -// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } + } } dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.android.support:appcompat-v7:' + supportLibraryVersion - implementation 'com.android.support:design:' + supportLibraryVersion - implementation 'com.android.support:cardview-v7:' + supportLibraryVersion - implementation 'com.android.support.constraint:constraint-layout:' + constraintLayoutVersion - implementation 'org.osmdroid:osmdroid-android:' + osmdroidVersion - implementation 'com.google.code.gson:gson:' + gsonVersion + + implementation "androidx.appcompat:appcompat:$appcompatVersion" + implementation "androidx.constraintlayout:constraintlayout:$constraintlayoutVersion" + implementation "androidx.cardview:cardview:$cardviewVersion" + + implementation "com.google.android.material:material:$materialVersion" + + implementation "org.osmdroid:osmdroid-android:$osmdroidVersion" + implementation "com.google.code.gson:gson:$gsonVersion" + } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index aea1a6a..fa3abe6 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -15,3 +15,7 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +# this was a test +# https://github.com/y20k/trackbook/commit/a3457db5462d9b4ab50b3c38c5621eb992768b7c +# -dontshrink \ No newline at end of file diff --git a/app/src/main/java/org/y20k/trackbook/MainActivity.java b/app/src/main/java/org/y20k/trackbook/MainActivity.java index 675914c..e75c892 100755 --- a/app/src/main/java/org/y20k/trackbook/MainActivity.java +++ b/app/src/main/java/org/y20k/trackbook/MainActivity.java @@ -34,19 +34,6 @@ import android.os.Environment; import android.os.IBinder; import android.os.Vibrator; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.BottomNavigationView; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.CardView; import android.util.SparseArray; import android.view.MenuItem; import android.view.View; @@ -54,6 +41,10 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast; +import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; + import org.osmdroid.config.Configuration; import org.y20k.trackbook.helpers.DialogHelper; import org.y20k.trackbook.helpers.ExportHelper; @@ -68,6 +59,17 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.cardview.widget.CardView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + /** * MainActivity class @@ -264,9 +266,20 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys { if (resultCode == Activity.RESULT_OK) { // user chose CLEAR handleStateAfterClear(); - LogHelper.v(LOG_TAG, "Save dialog result: CLEAR"); + LogHelper.v(LOG_TAG, "Clear map dialog result: CLEAR"); } else if (resultCode == Activity.RESULT_CANCELED){ - LogHelper.v(LOG_TAG, "Clear map: User chose CANCEL."); + LogHelper.v(LOG_TAG, "Clear map dialog result: User chose CANCEL."); + } + break; + case RESULT_EMPTY_RECORDING_DIALOG: + if (resultCode == Activity.RESULT_OK) { + // User chose RESUME RECORDING + handleResumeButtonClick((View)mFloatingActionButtonMain); + LogHelper.v(LOG_TAG, "Empty recording dialog result: RESUME"); + } else if (resultCode == Activity.RESULT_CANCELED){ + // User chose CANCEL - do nothing just hide the sub menu + showFloatingActionButtonMenu(false); + LogHelper.v(LOG_TAG, "Empty recording dialog result: CANCEL"); } break; } @@ -339,9 +352,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys { /* Handles the visual state after a save action */ private void handleStateAfterClear() { - // notify user - Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show(); - // dismiss notification dismissNotification(); @@ -584,16 +594,24 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys { switch (mFloatingActionButtonState) { case FAB_STATE_DEFAULT: + mFloatingActionButtonMain.hide(); // workaround todo remove asap mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp); + if (mSelectedTab == FRAGMENT_ID_MAP) mFloatingActionButtonMain.show(); // workaround todo remove asap break; case FAB_STATE_RECORDING: + mFloatingActionButtonMain.hide(); // workaround todo remove asap mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp); + if (mSelectedTab == FRAGMENT_ID_MAP) mFloatingActionButtonMain.show(); // workaround todo remove asap break; case FAB_STATE_SAVE: + mFloatingActionButtonMain.hide(); // workaround todo remove asap mFloatingActionButtonMain.setImageResource(R.drawable.ic_save_white_24dp); + if (mSelectedTab == FRAGMENT_ID_MAP) mFloatingActionButtonMain.show(); // workaround todo remove asap break; default: + mFloatingActionButtonMain.hide(); // workaround todo remove asap mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp); + if (mSelectedTab == FRAGMENT_ID_MAP) mFloatingActionButtonMain.show(); // workaround todo remove asap break; } } @@ -602,20 +620,20 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys { /* Shows (and hides) the sub menu of the floating action button */ private void showFloatingActionButtonMenu(boolean visible) { if (visible) { - mFloatingActionButtonSubResume.setVisibility(View.VISIBLE); + mFloatingActionButtonSubResume.show(); mFloatingActionButtonSubResumeLabel.setVisibility(View.VISIBLE); - mFloatingActionButtonSubClear.setVisibility(View.VISIBLE); + mFloatingActionButtonSubClear.show(); mFloatingActionButtonSubClearLabel.setVisibility(View.VISIBLE); - mFloatingActionButtonSubSave.setVisibility(View.VISIBLE); + mFloatingActionButtonSubSave.show(); mFloatingActionButtonSubSaveLabel.setVisibility(View.VISIBLE); mFloatingActionButtonSubMenuVisible = true; } else { - mFloatingActionButtonSubResume.setVisibility(View.INVISIBLE); + mFloatingActionButtonSubResume.hide(); mFloatingActionButtonSubResumeLabel.setVisibility(View.INVISIBLE); - mFloatingActionButtonSubClear.setVisibility(View.INVISIBLE); + mFloatingActionButtonSubClear.hide(); mFloatingActionButtonSubClearLabel.setVisibility(View.INVISIBLE); + mFloatingActionButtonSubSave.hide(); mFloatingActionButtonSubSaveLabel.setVisibility(View.INVISIBLE); - mFloatingActionButtonSubSave.setVisibility(View.INVISIBLE); mFloatingActionButtonSubMenuVisible = false; } } diff --git a/app/src/main/java/org/y20k/trackbook/MainActivityMapFragment.java b/app/src/main/java/org/y20k/trackbook/MainActivityMapFragment.java index f728141..5649b5f 100755 --- a/app/src/main/java/org/y20k/trackbook/MainActivityMapFragment.java +++ b/app/src/main/java/org/y20k/trackbook/MainActivityMapFragment.java @@ -31,15 +31,13 @@ import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.design.widget.Snackbar; -import android.support.v4.app.Fragment; -import android.support.v4.content.LocalBroadcastManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; +import com.google.android.material.snackbar.Snackbar; + import org.osmdroid.api.IMapController; import org.osmdroid.tileprovider.tilesource.TileSourceFactory; import org.osmdroid.util.GeoPoint; @@ -48,6 +46,7 @@ import org.osmdroid.views.overlay.ItemizedIconOverlay; import org.osmdroid.views.overlay.compass.CompassOverlay; import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider; import org.y20k.trackbook.core.Track; +import org.y20k.trackbook.helpers.DialogHelper; import org.y20k.trackbook.helpers.LocationHelper; import org.y20k.trackbook.helpers.LogHelper; import org.y20k.trackbook.helpers.MapHelper; @@ -56,6 +55,12 @@ import org.y20k.trackbook.helpers.TrackbookKeys; import java.util.List; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + /** * MainActivityMapFragment class @@ -124,7 +129,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { if (savedInstanceState != null) { Location savedLocation = savedInstanceState.getParcelable(INSTANCE_CURRENT_LOCATION); // check if saved location is still current - if (LocationHelper.isNewLocation(savedLocation)) { + if (LocationHelper.isCurrent(savedLocation)) { mCurrentBestLocation = savedLocation; } else { mCurrentBestLocation = null; @@ -207,7 +212,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { // mark user's location on map if (mCurrentBestLocation != null && !mTrackerServiceRunning) { - mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation)); + mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isCurrent(mCurrentBestLocation), false); mMapView.getOverlays().add(mMyLocationOverlay); } @@ -307,18 +312,29 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { switch(requestCode) { case RESULT_SAVE_DIALOG: if (resultCode == Activity.RESULT_OK) { - // user chose SAVE - clear map AND save track - clearMap(true); - // FloatingActionButton state is already being handled in MainActivity - ((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode); - LogHelper.v(LOG_TAG, "Save dialog result: SAVE"); + // user chose SAVE + if (mTrack.getSize() > 0) { + // Track is not empty - clear map AND save track + clearMap(true); + // FloatingActionButton state is already being handled in MainActivity + ((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode); + LogHelper.v(LOG_TAG, "Save dialog result: SAVE"); + } else { + // track is empty + handleEmptyRecordingSaveRequest(); + } } else if (resultCode == Activity.RESULT_CANCELED){ LogHelper.v(LOG_TAG, "Save dialog result: CANCEL"); } break; case RESULT_CLEAR_DIALOG: if (resultCode == Activity.RESULT_OK) { - // User chose CLEAR - clear map, DO NOT save track + // User chose CLEAR + if (mTrack.getSize() > 0) { + // Track is not empty - notify user + Toast.makeText(mActivity, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show(); + } + // clear map, DO NOT save track clearMap(false); // handle FloatingActionButton state in MainActivity ((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode); @@ -326,6 +342,10 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { LogHelper.v(LOG_TAG, "Clear dialog result: CANCEL"); } break; + case RESULT_EMPTY_RECORDING_DIALOG: + // handle FloatingActionButton state and possible Resume-Action in MainActivity + ((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode); + break; } } @@ -444,6 +464,21 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { } + /* Handles case when user chose to save recording with zero waypoints */ // todo implement + private void handleEmptyRecordingSaveRequest() { + // prepare empty recording dialog ("Unable to save") + int dialogTitle = R.string.dialog_error_empty_recording_title; + String dialogMessage = getString(R.string.dialog_error_empty_recording_content); + int dialogPositiveButton = R.string.dialog_error_empty_recording_action_resume; + int dialogNegativeButton = R.string.dialog_default_action_cancel; + // show empty recording dialog + DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton); + dialogFragment.setTargetFragment(this, RESULT_EMPTY_RECORDING_DIALOG); + dialogFragment.show(((AppCompatActivity)mActivity).getSupportFragmentManager(), "EmptyRecordingDialog"); + // results of dialog are handled by onActivityResult + } + + /* Start preliminary tracking for map */ private void startPreliminaryTracking() { if (mLocationSystemSetting && !mLocalTrackerRunning) { @@ -508,7 +543,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { mMapView.getOverlays().remove(mMyLocationOverlay); // only update while not tracking if (!mTrackerServiceRunning) { - mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isNewLocation(mCurrentBestLocation)); + mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, LocationHelper.isCurrent(mCurrentBestLocation), false); mMapView.getOverlays().add(mMyLocationOverlay); } } @@ -518,11 +553,16 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys { private void drawTrackOverlay(Track track) { mMapView.getOverlays().remove(mTrackOverlay); mTrackOverlay = null; - if (track != null) { + if (track == null || track.getSize() == 0) { + LogHelper.i(LOG_TAG, "Waiting for a track. Showing preliminary location."); + mTrackOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation, false, mTrackerServiceRunning); + Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_acquiring_location), Toast.LENGTH_LONG).show(); + } else { LogHelper.v(LOG_TAG, "Drawing track overlay."); mTrackOverlay = MapHelper.createTrackOverlay(mActivity, track, mTrackerServiceRunning); - mMapView.getOverlays().add(mTrackOverlay); } + mMapView.getOverlays().add(mTrackOverlay); + } diff --git a/app/src/main/java/org/y20k/trackbook/MainActivityTrackFragment.java b/app/src/main/java/org/y20k/trackbook/MainActivityTrackFragment.java index babed61..6d13f83 100755 --- a/app/src/main/java/org/y20k/trackbook/MainActivityTrackFragment.java +++ b/app/src/main/java/org/y20k/trackbook/MainActivityTrackFragment.java @@ -24,16 +24,6 @@ import android.content.IntentFilter; import android.location.Location; import android.os.AsyncTask; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.constraint.ConstraintLayout; -import android.support.constraint.Group; -import android.support.design.widget.BottomSheetBehavior; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.content.ContextCompat; -import android.support.v4.content.LocalBroadcastManager; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -45,6 +35,8 @@ import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; +import com.google.android.material.bottomsheet.BottomSheetBehavior; + import org.osmdroid.api.IMapController; import org.osmdroid.tileprovider.tilesource.TileSourceFactory; import org.osmdroid.util.GeoPoint; @@ -67,6 +59,16 @@ import java.io.File; import java.text.DateFormat; import java.util.Locale; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Group; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + /** * MainActivityTrackFragment class diff --git a/app/src/main/java/org/y20k/trackbook/Trackbook.java b/app/src/main/java/org/y20k/trackbook/Trackbook.java index 5bfb1d2..34eed22 100755 --- a/app/src/main/java/org/y20k/trackbook/Trackbook.java +++ b/app/src/main/java/org/y20k/trackbook/Trackbook.java @@ -18,11 +18,12 @@ package org.y20k.trackbook; import android.app.Application; import android.os.Build; -import android.support.v7.app.AppCompatDelegate; import org.y20k.trackbook.helpers.LogHelper; import org.y20k.trackbook.helpers.NightModeHelper; +import androidx.appcompat.app.AppCompatDelegate; + /** * Trackbook.class diff --git a/app/src/main/java/org/y20k/trackbook/TrackerService.java b/app/src/main/java/org/y20k/trackbook/TrackerService.java index 5e2ac62..1351397 100755 --- a/app/src/main/java/org/y20k/trackbook/TrackerService.java +++ b/app/src/main/java/org/y20k/trackbook/TrackerService.java @@ -37,8 +37,6 @@ import android.os.CountDownTimer; import android.os.Handler; import android.os.IBinder; import android.preference.PreferenceManager; -import android.support.v4.app.NotificationCompat; -import android.support.v4.content.LocalBroadcastManager; import android.widget.Toast; import org.y20k.trackbook.core.Track; @@ -50,6 +48,9 @@ import org.y20k.trackbook.helpers.TrackbookKeys; import java.util.List; +import androidx.core.app.NotificationCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import static android.hardware.Sensor.TYPE_STEP_COUNTER; @@ -233,7 +234,7 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven // load temp track file mTrack = storageHelper.loadTrack(FILE_TEMP_TRACK); // try to mark last waypoint as stopover - int lastWayPoint = mTrack.getWayPoints().size() - 1; + int lastWayPoint = mTrack.getSize() - 1; if (lastWayPoint >= 0) { mTrack.getWayPoints().get(lastWayPoint).setIsStopOver(true); } @@ -394,12 +395,17 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven boolean success = false; Location previousLocation = null; - int trackSize = mTrack.getWayPoints().size(); + int trackSize = mTrack.getSize(); if (trackSize == 0) { - // add first location to track - success = mTrack.addWayPoint(previousLocation, mCurrentBestLocation); - + // if accurate AND current + if (LocationHelper.isAccurate(mCurrentBestLocation) && LocationHelper.isCurrent(mCurrentBestLocation)) { + // add first location to track + success = mTrack.addWayPoint(previousLocation, mCurrentBestLocation); + } else { + // just send a broadcast indicating that current location fix not not suited + broadcastTrackUpdate(); + } } else { // get location of previous WayPoint previousLocation = mTrack.getWayPointLocation(trackSize - 1); @@ -415,17 +421,20 @@ public class TrackerService extends Service implements TrackbookKeys, SensorEven averageSpeed = distance / ((float) timeDifference / ONE_SECOND_IN_NANOSECOND); } - if (LocationHelper.isNewWayPoint(previousLocation, mCurrentBestLocation, averageSpeed)) { - // if new, add current best location to track + // if accurate AND new + if (LocationHelper.isAccurate(mCurrentBestLocation) && LocationHelper.isNewWayPoint(previousLocation, mCurrentBestLocation, averageSpeed)) { + // add current best location to track success = mTrack.addWayPoint(previousLocation, mCurrentBestLocation); } } if (success) { if (mResumedFlag) { - // mark last location as stop over - int lastWayPoint = mTrack.getWayPoints().size() - 2; - mTrack.getWayPoints().get(lastWayPoint).setIsStopOver(true); + int lastWayPoint = mTrack.getSize() - 2; + if (lastWayPoint >= 0) { + // mark last location as stop over + mTrack.getWayPoints().get(lastWayPoint).setIsStopOver(true); + } mResumedFlag = false; } else { // update distance, if not resumed 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 2f48aea..e2f7158 100755 --- a/app/src/main/java/org/y20k/trackbook/core/Track.java +++ b/app/src/main/java/org/y20k/trackbook/core/Track.java @@ -19,7 +19,6 @@ package org.y20k.trackbook.core; import android.location.Location; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; import org.y20k.trackbook.helpers.LocationHelper; import org.y20k.trackbook.helpers.TrackbookKeys; @@ -29,6 +28,8 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import androidx.annotation.Nullable; + /** * Track class @@ -275,7 +276,12 @@ public class Track implements TrackbookKeys, Parcelable { /* Getter recorded distance */ public Double getTrackDistance() { - return (double) mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint(); + int size = mWayPoints.size(); + if (size > 0) { + return (double)mWayPoints.get(size - 1).getDistanceToStartingPoint(); + } else { + return (double)0f; + } } diff --git a/app/src/main/java/org/y20k/trackbook/helpers/DialogHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/DialogHelper.java index cbdcb02..95f7955 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/DialogHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/DialogHelper.java @@ -21,8 +21,9 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; + +import androidx.annotation.NonNull; +import androidx.fragment.app.DialogFragment; /** diff --git a/app/src/main/java/org/y20k/trackbook/helpers/DropdownAdapter.java b/app/src/main/java/org/y20k/trackbook/helpers/DropdownAdapter.java index 0fae97a..b3ee9c1 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/DropdownAdapter.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/DropdownAdapter.java @@ -20,8 +20,6 @@ package org.y20k.trackbook.helpers; import android.app.Activity; import android.content.res.Resources; import android.database.DataSetObserver; -import android.support.annotation.Nullable; -import android.support.v7.widget.ThemedSpinnerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -35,6 +33,9 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.ThemedSpinnerAdapter; + /** * DropdownHelper class @@ -175,7 +176,9 @@ public class DropdownAdapter extends BaseAdapter implements ThemedSpinnerAdapter // fill list with track bundles mTrackBundleList = new ArrayList<>(); for (File file : files) { - mTrackBundleList.add(new TrackBundle(file)); + if (file.getName().endsWith(FILE_TYPE_TRACKBOOK_EXTENSION)) { + mTrackBundleList.add(new TrackBundle(file)); + } } } diff --git a/app/src/main/java/org/y20k/trackbook/helpers/ExportHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/ExportHelper.java index 8b1ab15..5816d16 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/ExportHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/ExportHelper.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.Intent; import android.location.Location; import android.os.Environment; -import android.support.v4.content.FileProvider; import android.widget.Toast; import org.y20k.trackbook.R; @@ -37,6 +36,8 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; +import androidx.core.content.FileProvider; + /** * ExportHelper 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 5f0041f..1b44300 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/LocationHelper.java @@ -22,12 +22,13 @@ import android.location.LocationListener; import android.location.LocationManager; import android.os.SystemClock; import android.provider.Settings; -import android.support.annotation.Nullable; import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; +import androidx.annotation.Nullable; + /** * LocationHelper class @@ -93,8 +94,8 @@ public final class LocationHelper implements TrackbookKeys { // check whether the new location fix is newer or older long timeDelta = location.getElapsedRealtimeNanos() - currentBestLocation.getElapsedRealtimeNanos(); - boolean isSignificantlyNewer = timeDelta > TWO_MINUTES_IN_NANOSECONDS; - boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES_IN_NANOSECONDS; + boolean isSignificantlyNewer = timeDelta > ONE_MINUTE_IN_NANOSECONDS; + boolean isSignificantlyOlder = timeDelta < -ONE_MINUTE_IN_NANOSECONDS; 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 @@ -125,13 +126,19 @@ public final class LocationHelper implements TrackbookKeys { } + /* Checks accuracy of given location */ + public static boolean isAccurate(Location location) { + return location.getAccuracy() < FIFTY_METER_RADIUS; + } + + /* Checks if given location is newer than two minutes */ - public static boolean isNewLocation(Location location) { + public static boolean isCurrent(Location location) { if (location == null) { return false; } else { long locationAge = SystemClock.elapsedRealtimeNanos() - location.getElapsedRealtimeNanos(); - return locationAge < TWO_MINUTES_IN_NANOSECONDS; + return locationAge < ONE_MINUTE_IN_NANOSECONDS; } } diff --git a/app/src/main/java/org/y20k/trackbook/helpers/MapHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/MapHelper.java index f2d1b4c..e9759ee 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/MapHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/MapHelper.java @@ -19,7 +19,6 @@ package org.y20k.trackbook.helpers; import android.content.Context; import android.graphics.drawable.Drawable; import android.location.Location; -import android.support.v4.content.ContextCompat; import android.widget.Toast; import org.osmdroid.util.GeoPoint; @@ -34,6 +33,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import androidx.core.content.ContextCompat; + /** * MapHelper class */ @@ -44,17 +45,20 @@ public final class MapHelper { /* Creates icon overlay for current position (used in MainActivity Fragment) */ - public static ItemizedIconOverlay createMyLocationOverlay(final Context context, Location currentBestLocation, boolean locationIsNew) { + public static ItemizedIconOverlay createMyLocationOverlay(final Context context, Location currentBestLocation, boolean locationIsNew, boolean trackingActive) { final ArrayList overlayItems = new ArrayList<>(); // create marker Drawable newMarker; - if (locationIsNew) { + if (locationIsNew && !trackingActive) { newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_blue_24dp); + } else if (!locationIsNew && trackingActive) { + newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_red_grey_24dp); } else { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp); + newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_blue_grey_24dp); } + OverlayItem overlayItem = createOverlayItem(context, currentBestLocation); overlayItem.setMarker(newMarker); @@ -83,13 +87,14 @@ public final class MapHelper { /* Creates icon overlay for track */ public static ItemizedIconOverlay createTrackOverlay(final Context context, Track track, boolean trackingActive){ - WayPoint wayPoint; + final ArrayList overlayItems = new ArrayList<>(); boolean currentPosition; final int trackSize = track.getSize(); final List wayPoints = track.getWayPoints(); - final ArrayList overlayItems = new ArrayList<>(); + WayPoint wayPoint; + + for (int i = 0; i < track.getSize(); i++) { - 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; @@ -112,7 +117,7 @@ public final class MapHelper { else if (trackingActive && currentPosition) { if (wayPoint.getIsStopOver()) { // stop over marker - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_grey_24dp); + newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_blue_grey_24dp); } else { // default marker for this case newMarker = ContextCompat.getDrawable(context, R.drawable.ic_my_location_dot_red_24dp); diff --git a/app/src/main/java/org/y20k/trackbook/helpers/NightModeHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/NightModeHelper.java index fb5b754..2e1b9b8 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/NightModeHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/NightModeHelper.java @@ -22,9 +22,10 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Build; import android.preference.PreferenceManager; -import android.support.v7.app.AppCompatDelegate; import android.view.View; +import androidx.appcompat.app.AppCompatDelegate; + /** * NightModeHelper class diff --git a/app/src/main/java/org/y20k/trackbook/helpers/NotificationHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/NotificationHelper.java index de771a5..f3cc70d 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/NotificationHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/NotificationHelper.java @@ -26,15 +26,16 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.os.Build; -import android.support.graphics.drawable.VectorDrawableCompat; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.TaskStackBuilder; import org.y20k.trackbook.MainActivity; import org.y20k.trackbook.R; import org.y20k.trackbook.TrackerService; import org.y20k.trackbook.core.Track; +import androidx.core.app.NotificationCompat; +import androidx.core.app.TaskStackBuilder; +import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; + /** * NotificationHelper class diff --git a/app/src/main/java/org/y20k/trackbook/helpers/StorageHelper.java b/app/src/main/java/org/y20k/trackbook/helpers/StorageHelper.java index 8b4e742..f063b86 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/StorageHelper.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/StorageHelper.java @@ -18,8 +18,6 @@ package org.y20k.trackbook.helpers; import android.content.Context; import android.os.Environment; -import android.support.annotation.Nullable; -import android.support.v4.os.EnvironmentCompat; import android.widget.Toast; import com.google.gson.Gson; @@ -42,6 +40,9 @@ import java.util.Comparator; import java.util.Date; import java.util.Locale; +import androidx.annotation.Nullable; +import androidx.core.os.EnvironmentCompat; + /** * StorageHelper class 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 b474058..c1a5f59 100755 --- a/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java +++ b/app/src/main/java/org/y20k/trackbook/helpers/TrackbookKeys.java @@ -75,23 +75,21 @@ public interface TrackbookKeys { int FRAGMENT_ID_MAP = 0; int FRAGMENT_ID_TRACKS = 1; - String FRAGMENT_TAG_MAP = "fragmentTagMap"; - String FRAGMENT_TAG_TRACKS = "fragmentTagTracks"; - - /* RESULTS */ int RESULT_SAVE_DIALOG = 1; int RESULT_CLEAR_DIALOG = 2; int RESULT_DELETE_DIALOG = 3; int RESULT_EXPORT_DIALOG = 4; + int RESULT_EMPTY_RECORDING_DIALOG = 5; /* CONSTANTS */ long ONE_SECOND_IN_NANOSECOND = 1000000000L; long EIGHT_HOURS_IN_MILLISECONDS = 43200000; // maximum tracking duration long FIFTEEN_SECONDS_IN_MILLISECONDS = 15000; // timer interval for tracking long FIVE_MINUTES_IN_NANOSECONDS = 5L * 60000000000L; // determines a stop over - long TWO_MINUTES_IN_NANOSECONDS = 2L * 60000000000L; // defines an old location + long ONE_MINUTE_IN_NANOSECONDS = 1L * 60000000000L; // defines an old location int MAXIMUM_TRACK_FILES = 25; + int FIFTY_METER_RADIUS = 50; /* FILE */ String FILE_TYPE_GPX_EXTENSION = ".gpx"; diff --git a/app/src/main/java/org/y20k/trackbook/layout/DodgeAbleLayoutBehavior.java b/app/src/main/java/org/y20k/trackbook/layout/DodgeAbleLayoutBehavior.java index 4befaac..e1969b8 100755 --- a/app/src/main/java/org/y20k/trackbook/layout/DodgeAbleLayoutBehavior.java +++ b/app/src/main/java/org/y20k/trackbook/layout/DodgeAbleLayoutBehavior.java @@ -18,11 +18,13 @@ package org.y20k.trackbook.layout; import android.content.Context; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.Snackbar; import android.util.AttributeSet; import android.view.View; +import com.google.android.material.snackbar.Snackbar; + +import androidx.coordinatorlayout.widget.CoordinatorLayout; + /** * DodgeAbleLayoutBehavior class diff --git a/app/src/main/java/org/y20k/trackbook/layout/NonSwipeableViewPager.java b/app/src/main/java/org/y20k/trackbook/layout/NonSwipeableViewPager.java index 7a17970..ab5e337 100755 --- a/app/src/main/java/org/y20k/trackbook/layout/NonSwipeableViewPager.java +++ b/app/src/main/java/org/y20k/trackbook/layout/NonSwipeableViewPager.java @@ -22,7 +22,6 @@ package org.y20k.trackbook.layout; */ import android.content.Context; -import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; @@ -32,6 +31,8 @@ import org.y20k.trackbook.helpers.LogHelper; import java.lang.reflect.Field; +import androidx.viewpager.widget.ViewPager; + public class NonSwipeableViewPager extends ViewPager { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 28073d8..c86dec0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - - - - - + - - - + - - - + - - - + - + diff --git a/app/src/main/res/layout/fragment_main_track.xml b/app/src/main/res/layout/fragment_main_track.xml index cc0d944..9da09f3 100644 --- a/app/src/main/res/layout/fragment_main_track.xml +++ b/app/src/main/res/layout/fragment_main_track.xml @@ -1,5 +1,5 @@ - - + app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/track_management.xml b/app/src/main/res/layout/track_management.xml index 74928b1..56ce27b 100644 --- a/app/src/main/res/layout/track_management.xml +++ b/app/src/main/res/layout/track_management.xml @@ -1,5 +1,5 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/track_statistics.xml b/app/src/main/res/layout/track_statistics.xml index 121f18f..98cd521 100644 --- a/app/src/main/res/layout/track_statistics.xml +++ b/app/src/main/res/layout/track_statistics.xml @@ -1,5 +1,5 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7ee2c80..e1dd41c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -45,6 +45,9 @@ Datei existiert bereits. Exportieren und überschreiben Sie diese Aufzeichnung als GPX-Strecke. Exportieren und überschreiben GPX-Datei öffnen mit + Speichern nicht möglich + Trackbook hat noch keine Wegpunkte aufgezeichnet. + Aufzeichnung fortsetzen Berechtigungen erteilt. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index d8e146e..0b3394b 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -45,6 +45,9 @@ File already exists. Export and overwrite this recording as GPX track. Export and Overwrite Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording Permissions granted. diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 59736fb..361eada 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -45,6 +45,9 @@ Il file esiste già. Esportare e sovrascrivere questa registrazione come traccia GPX. Esporta e sovrascrivi Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording Permessi acquisiti. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index f8e7d0d..5acf9e6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -45,6 +45,9 @@ ファイルは既に存在します。エクスポートし、GPX トラックとしてこの記録を上書きします。 エクスポートして上書き Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording アクセス許可を付与しました。 diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 7c717a5..aaca830 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -45,6 +45,9 @@ Fila finnes allerede. Eksporter og overskriv dette opptaket som en GPX-tur. Eksporter og overskriv Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording Tilgang gitt. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 9dce0c1..c953cae 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -45,6 +45,9 @@ File already exists. Export and overwrite this recording as GPX track. Export and Overwrite Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording Rechten verleend. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3f6578..3922ab3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,6 +45,9 @@ File already exists. Export and overwrite this recording as GPX track. Export and Overwrite Share GPX file with + Unable to save + Trackbook did not record any waypoints so far. + Resume Recording Permissions granted. diff --git a/build.gradle b/build.gradle index e253631..8daa0e5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,35 +1,42 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + repositories { jcenter() google() } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } + } allprojects { + repositories { google() jcenter() } + project.ext { applicationId = 'org.y20k.trackbook' - versionCode = 28 - versionName = '1.1.12' - minSdkVersion = 22 - compileSdkVersion = 27 - targetSdkVersion = 27 - buildToolsVersion = '27.0.3' - supportLibraryVersion = '27.1.1' - constraintLayoutVersion = '1.1.0-beta6' + versionCode = 29 + versionName = '1.1.13' - osmdroidVersion = '6.0.1' + compileSdkVersion = 28 + targetSdkVersion = 27 + minSdkVersion = 22 + + constraintlayoutVersion = '1.1.3' + materialVersion = "1.0.0" + appcompatVersion = '1.0.0' + cardviewVersion = '1.0.0' + + osmdroidVersion = '6.0.2' gsonVersion = '2.8.5' } } diff --git a/gradle.properties b/gradle.properties index 1d3591c..915f0e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,6 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.enableJetifier=true +android.useAndroidX=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 53e5bb2..1952c96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 04 15:52:45 CEST 2018 +#Thu Oct 04 08:52:03 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip