From 360d59d3de98ded39bb09229a076df83801b81ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n?= Date: Mon, 11 May 2020 08:06:36 +0200 Subject: [PATCH] Split detail and record to simplify the code. Fixes #171. --- src/main/AndroidManifest.xml | 6 +- .../opentracks/AbstractListActivity.java | 2 +- .../opentracks/SearchListActivity.java | 6 +- .../TrackActivityDataHubInterface.java | 10 + .../opentracks/TrackListActivity.java | 19 +- .../opentracks/TrackRecordedActivity.java | 272 +++++++++++++++ ...ivity.java => TrackRecordingActivity.java} | 160 +++------ .../opentracks/fragments/ChartFragment.java | 4 +- .../fragments/StatisticsRecordedFragment.java | 310 ++++++++++++++++++ ....java => StatisticsRecordingFragment.java} | 42 +-- .../services/TrackRecordingService.java | 8 +- src/main/res/layout/statistics_recorded.xml | 177 ++++++++++ .../{stats.xml => statistics_recording.xml} | 16 +- src/main/res/layout/track_detail.xml | 2 - src/main/res/layout/track_record.xml | 23 ++ src/main/res/menu/track_detail.xml | 6 - src/main/res/menu/track_record.xml | 45 +++ src/main/res/values/strings.xml | 2 + 18 files changed, 922 insertions(+), 188 deletions(-) create mode 100644 src/main/java/de/dennisguse/opentracks/TrackActivityDataHubInterface.java create mode 100644 src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java rename src/main/java/de/dennisguse/opentracks/{TrackDetailActivity.java => TrackRecordingActivity.java} (70%) create mode 100644 src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java rename src/main/java/de/dennisguse/opentracks/fragments/{StatsFragment.java => StatisticsRecordingFragment.java} (94%) create mode 100644 src/main/res/layout/statistics_recorded.xml rename src/main/res/layout/{stats.xml => statistics_recording.xml} (94%) create mode 100644 src/main/res/layout/track_record.xml create mode 100644 src/main/res/menu/track_record.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 026854e4f..15d669c6a 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -79,7 +79,11 @@ limitations under the License. + + diff --git a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java index 27d064836..b81a42e7f 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java @@ -26,7 +26,7 @@ import de.dennisguse.opentracks.util.PreferencesUtils; /** * An abstract class for the following common tasks across - * {@link TrackListActivity}, {@link TrackDetailActivity}, and + * {@link TrackListActivity}, {@link TrackRecordedActivity}, and * {@link SearchListActivity}: *

* - share track
diff --git a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java index 6dc35c35c..71679be72 100644 --- a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java @@ -214,11 +214,11 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa Map item = arrayAdapter.getItem(position); Long trackId = (Long) item.get(TRACK_ID_FIELD); Long markerId = (Long) item.get(MARKER_ID_FIELD); - Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackDetailActivity.class); + Intent intent = IntentUtils.newIntent(SearchListActivity.this, TrackRecordedActivity.class); if (markerId != null) { - intent = intent.putExtra(TrackDetailActivity.EXTRA_MARKER_ID, markerId); + intent = intent.putExtra(TrackRecordedActivity.EXTRA_MARKER_ID, markerId); } else { - intent = intent.putExtra(TrackDetailActivity.EXTRA_TRACK_ID, trackId); + intent = intent.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); } startActivity(intent); } diff --git a/src/main/java/de/dennisguse/opentracks/TrackActivityDataHubInterface.java b/src/main/java/de/dennisguse/opentracks/TrackActivityDataHubInterface.java new file mode 100644 index 000000000..d5de39eed --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/TrackActivityDataHubInterface.java @@ -0,0 +1,10 @@ +package de.dennisguse.opentracks; + +import de.dennisguse.opentracks.content.TrackDataHub; + +/** + * Interface for communication between activities that use {@link de.dennisguse.opentracks.content.TrackDataHub} and their fragments that need thi data hub. + */ +public interface TrackActivityDataHubInterface { + TrackDataHub getTrackDataHub(); +} diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 6db013db6..1c5352291 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -205,8 +205,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe if (!PreferencesUtils.isRecording(recordingTrackId)) { // Not recording -> Recording updateMenuItems(false, true); - Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class) - .putExtra(TrackDetailActivity.EXTRA_RECORDING_REQUEST, true); + Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class); startActivity(newIntent); } else if (recordingTrackPaused) { // Paused -> Resume @@ -251,10 +250,18 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe listView.setEmptyView(findViewById(R.id.track_list_empty_view)); listView.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackDetailActivity.class) - .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, id); - startActivity(newIntent); + public void onItemClick(AdapterView parent, View view, int position, long trackId) { + if (trackId == recordingTrackId) { + // Is recording -> open record activity. + Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class) + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); + startActivity(newIntent); + } else { + // Not recording -> open detail activity. + Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordedActivity.class) + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); + startActivity(newIntent); + } } }); diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java new file mode 100644 index 000000000..281f4336f --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordedActivity.java @@ -0,0 +1,272 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package de.dennisguse.opentracks; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.tabs.TabLayout; + +import de.dennisguse.opentracks.content.TrackDataHub; +import de.dennisguse.opentracks.content.data.Track; +import de.dennisguse.opentracks.content.data.Waypoint; +import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.fragments.ChartFragment; +import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; +import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; +import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment; +import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; +import de.dennisguse.opentracks.settings.SettingsActivity; +import de.dennisguse.opentracks.util.IntentUtils; +import de.dennisguse.opentracks.util.TrackIconUtils; +import de.dennisguse.opentracks.util.TrackUtils; + +/** + * An activity to show the track detail, record a new track or resumes an existing one. + * + * @author Leif Hendrik Wilden + * @author Rodrigo Damazio + */ +public class TrackRecordedActivity extends AbstractListActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackActivityDataHubInterface { + + public static final String EXTRA_TRACK_ID = "track_id"; + public static final String EXTRA_MARKER_ID = "marker_id"; + + private static final String TAG = TrackRecordedActivity.class.getSimpleName(); + + private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key"; + + // The following are set in onCreate. + private ContentProviderUtils contentProviderUtils; + private TrackDataHub trackDataHub; + private ViewPager pager; + + // From intent. + private long trackId; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + contentProviderUtils = new ContentProviderUtils(this); + handleIntent(getIntent()); + + trackDataHub = new TrackDataHub(this); + + FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager(), 1) { + @Override + public int getCount() { + return 3; + } + + @NonNull + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: + return new StatisticsRecordedFragment(); + case 1: + return ChartFragment.newInstance(false); + case 2: + return ChartFragment.newInstance(true); + default: + throw new RuntimeException("There isn't Fragment associated with the position: " + position); + } + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return getString(R.string.track_detail_stats_tab); + case 1: + return getString(R.string.settings_chart_by_time); + case 2: + return getString(R.string.settings_chart_by_distance); + } + return "Unknown Tab"; + } + }; + pager = findViewById(R.id.track_detail_activity_view_pager); + pager.setAdapter(adapter); + TabLayout tabs = findViewById(R.id.track_detail_activity_tablayout); + tabs.setupWithViewPager(pager); + if (savedInstanceState != null) { + pager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY)); + } + } + + @Override + protected void onStart() { + super.onStart(); + trackDataHub.start(); + } + + @Override + protected void onResume() { + super.onResume(); + + // Update UI + this.invalidateOptionsMenu(); + + if (trackId != -1L) { + trackDataHub.loadTrack(trackId); + } + } + + @Override + protected void onStop() { + super.onStop(); + trackDataHub.stop(); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem()); + } + + @Override + protected int getLayoutResId() { + return R.layout.track_detail; + } + + @Override + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + handleIntent(intent); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.track_detail, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + menu.findItem(R.id.track_detail_markers).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + Track track = contentProviderUtils.getTrack(trackId); + setTitle(track != null ? track.getName() : ""); + return super.onPrepareOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + Intent intent; + switch (item.getItemId()) { + case R.id.track_detail_share: + intent = IntentUtils.newShareFileIntent(this, new long[]{trackId}); + intent = Intent.createChooser(intent, null); + startActivity(intent); + return true; + case R.id.track_detail_menu_show_on_map: + IntentUtils.showTrackOnMap(this, new long[]{trackId}); + return true; + case R.id.track_detail_markers: + intent = IntentUtils.newIntent(this, MarkerListActivity.class) + .putExtra(MarkerListActivity.EXTRA_TRACK_ID, trackId); + startActivity(intent); + return true; + case R.id.track_detail_edit: + intent = IntentUtils.newIntent(this, TrackEditActivity.class) + .putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId); + startActivity(intent); + return true; + case R.id.track_detail_delete: + deleteTracks(new long[]{trackId}); + return true; + case R.id.track_detail_resume_track: + Intent newIntent = IntentUtils.newIntent(TrackRecordedActivity.this, TrackRecordingActivity.class) + .putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, trackId); + startActivity(newIntent); + finish(); + return true; + case R.id.track_detail_settings: + intent = IntentUtils.newIntent(this, SettingsActivity.class); + startActivity(intent); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + @Override + protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() { + // Not needed. + return null; + } + + @Override + protected void onDeleted() { + runOnUiThread(new Runnable() { + @Override + public void run() { + finish(); + } + }); + } + + /** + * Gets the {@link TrackDataHub}. + */ + @Override + public TrackDataHub getTrackDataHub() { + return trackDataHub; + } + + private void handleIntent(Intent intent) { + trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); + + long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); + if (markerId != -1L) { + // Use the trackId from the marker + Waypoint waypoint = contentProviderUtils.getWaypoint(markerId); + if (waypoint == null) { + finish(); + return; + } + trackId = waypoint.getTrackId(); + } + + if (trackId == -1L) { + Log.e(TAG, "TrackDetailActivity needs EXTRA_TRACK_ID."); + finish(); + return; + } + } + + public void chooseActivityType(String category) { + ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), category); + } + + @Override + public void onChooseActivityTypeDone(String iconValue) { + Track track = contentProviderUtils.getTrack(trackId); + String category = getString(TrackIconUtils.getIconActivityType(iconValue)); + TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils); + } +} \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java similarity index 70% rename from src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java rename to src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java index 836e42b06..a7e4d9dfe 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java @@ -1,19 +1,3 @@ -/* - * Copyright 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - package de.dennisguse.opentracks; import android.content.Intent; @@ -38,12 +22,10 @@ import com.google.android.material.tabs.TabLayout; import de.dennisguse.opentracks.content.TrackDataHub; import de.dennisguse.opentracks.content.data.Track; -import de.dennisguse.opentracks.content.data.Waypoint; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.fragments.ChartFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; -import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; -import de.dennisguse.opentracks.fragments.StatsFragment; +import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceInterface; import de.dennisguse.opentracks.settings.SettingsActivity; @@ -58,13 +40,11 @@ import de.dennisguse.opentracks.util.TrackUtils; * @author Leif Hendrik Wilden * @author Rodrigo Damazio */ -public class TrackDetailActivity extends AbstractListActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller { +public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface { public static final String EXTRA_TRACK_ID = "track_id"; - public static final String EXTRA_MARKER_ID = "marker_id"; - public static final String EXTRA_RECORDING_REQUEST = "request_recording"; - private static final String TAG = TrackDetailActivity.class.getSimpleName(); + private static final String TAG = TrackRecordingActivity.class.getSimpleName(); private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key"; @@ -79,8 +59,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA // From intent private long trackId; - private boolean isRecordingRequest = false; - // Preferences private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT; private boolean recordingTrackPaused; @@ -92,7 +70,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA runOnUiThread(new Runnable() { @Override public void run() { - trackController.update(isRecording(), recordingTrackPaused); + trackController.update(true, recordingTrackPaused); } }); @@ -102,9 +80,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA Log.d(TAG, "could not get TrackRecordingService"); return; } - if (!isRecordingRequest) { - return; - } // Starts or resumes a track. int msg; @@ -121,12 +96,10 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA } // A recording track is on. - Toast.makeText(TrackDetailActivity.this, msg, Toast.LENGTH_SHORT).show(); + Toast.makeText(TrackRecordingActivity.this, msg, Toast.LENGTH_SHORT).show(); trackDataHub.loadTrack(trackId); trackController.update(true, false); trackController.onResume(true, recordingTrackPaused); - - isRecordingRequest = false; } } }; @@ -134,23 +107,23 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_id_key, key)) { - recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackDetailActivity.this); + if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.recording_track_id_key, key)) { + recordingTrackId = PreferencesUtils.getRecordingTrackId(TrackRecordingActivity.this); setLockscreenPolicy(); setScreenOnPolicy(); } - if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.recording_track_paused_key, key)) { - recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackDetailActivity.this); + if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.recording_track_paused_key, key)) { + recordingTrackPaused = PreferencesUtils.isRecordingTrackPaused(TrackRecordingActivity.this); setLockscreenPolicy(); setScreenOnPolicy(); } - if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.stats_show_on_lockscreen_while_recording_key, key)) { + if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_show_on_lockscreen_while_recording_key, key)) { setLockscreenPolicy(); } - if (PreferencesUtils.isKey(TrackDetailActivity.this, R.string.stats_keep_screen_on_while_recording_key, key)) { + if (PreferencesUtils.isKey(TrackRecordingActivity.this, R.string.stats_keep_screen_on_while_recording_key, key)) { setScreenOnPolicy(); } @@ -159,9 +132,8 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA runOnUiThread(new Runnable() { @Override public void run() { - TrackDetailActivity.this.invalidateOptionsMenu(); - boolean isRecording = isRecording(); - trackController.update(isRecording, recordingTrackPaused); + TrackRecordingActivity.this.invalidateOptionsMenu(); + trackController.update(true, recordingTrackPaused); } }); } @@ -169,8 +141,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA private MenuItem insertMarkerMenuItem; private MenuItem markerListMenuItem; - private MenuItem shareMenuItem; - private MenuItem resumeMenuItem; private final OnClickListener recordListener = new OnClickListener() { @Override @@ -192,8 +162,12 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA private final OnClickListener stopListener = new OnClickListener() { @Override public void onClick(View v) { - trackRecordingServiceConnection.stopRecording(TrackDetailActivity.this, true); + trackRecordingServiceConnection.stopRecording(TrackRecordingActivity.this, true); + Intent newIntent = IntentUtils.newIntent(TrackRecordingActivity.this, TrackRecordedActivity.class) + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId); + startActivity(newIntent); updateMenuItems(true); + finish(); } }; @@ -220,12 +194,14 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA @Override public Fragment getItem(int position) { switch (position) { + case 0: + return new StatisticsRecordingFragment(); case 1: return ChartFragment.newInstance(false); case 2: return ChartFragment.newInstance(true); - default: //0 - return new StatsFragment(); + default: + throw new RuntimeException("There isn't Fragment associated with the position: " + position); } } @@ -261,7 +237,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA } private void setLockscreenPolicy() { - boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackDetailActivity.this) + boolean showOnLockScreen = PreferencesUtils.shouldShowStatsOnLockscreen(TrackRecordingActivity.this) && PreferencesUtils.isRecording(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { @@ -274,7 +250,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA } private void setScreenOnPolicy() { - boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackDetailActivity.this) + boolean keepScreenOn = PreferencesUtils.shouldKeepScreenOn(TrackRecordingActivity.this) && PreferencesUtils.isRecording(this); if (keepScreenOn) { @@ -304,10 +280,10 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA if (trackId != -1L) { trackDataHub.loadTrack(trackId); - trackController.onResume(isRecording(), recordingTrackPaused); - } else { - startRecording(); + trackController.onResume(true, recordingTrackPaused); } + + startRecording(); } @Override @@ -332,7 +308,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA @Override protected int getLayoutResId() { - return R.layout.track_detail; + return R.layout.track_record; } @Override @@ -344,12 +320,10 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.track_detail, menu); + getMenuInflater().inflate(R.menu.track_record, menu); insertMarkerMenuItem = menu.findItem(R.id.track_detail_insert_marker); - shareMenuItem = menu.findItem(R.id.track_detail_share); markerListMenuItem = menu.findItem(R.id.track_detail_markers); - resumeMenuItem = menu.findItem(R.id.track_detail_resume_track); return super.onCreateOptionsMenu(menu); } @@ -370,11 +344,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA .putExtra(MarkerEditActivity.EXTRA_TRACK_ID, trackId); startActivity(intent); return true; - case R.id.track_detail_share: - intent = IntentUtils.newShareFileIntent(this, new long[]{trackId}); - intent = Intent.createChooser(intent, null); - startActivity(intent); - return true; case R.id.track_detail_menu_show_on_map: IntentUtils.showTrackOnMap(this, new long[]{trackId}); return true; @@ -388,13 +357,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA .putExtra(TrackEditActivity.EXTRA_TRACK_ID, trackId); startActivity(intent); return true; - case R.id.track_detail_delete: - deleteTracks(new long[]{trackId}); - return true; - case R.id.track_detail_resume_track: - isRecordingRequest = true; - startRecording(); - return true; case R.id.track_detail_settings: intent = IntentUtils.newIntent(this, SettingsActivity.class); startActivity(intent); @@ -404,58 +366,25 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA } } - @Override - protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() { - return trackRecordingServiceConnection; - } - - @Override - protected void onDeleted() { - runOnUiThread(new Runnable() { - @Override - public void run() { - finish(); - } - }); - } - /** * Gets the {@link TrackDataHub}. */ + @Override public TrackDataHub getTrackDataHub() { return trackDataHub; } private void handleIntent(Intent intent) { trackId = intent.getLongExtra(EXTRA_TRACK_ID, -1L); - isRecordingRequest = intent.getBooleanExtra(EXTRA_RECORDING_REQUEST, false); - long markerId = intent.getLongExtra(EXTRA_MARKER_ID, -1L); - if (markerId != -1L) { - // Use the trackId from the marker - Waypoint waypoint = contentProviderUtils.getWaypoint(markerId); - if (waypoint == null) { - finish(); - return; - } - trackId = waypoint.getTrackId(); - if (trackId == -1L) { - finish(); - return; - } - } - if (trackId == -1L) { return; } Track track = contentProviderUtils.getTrack(trackId); if (track == null) { - // Use the last track if markerId is not set - if (markerId == -1L) { - track = contentProviderUtils.getLastTrack(); - if (track != null) { - trackId = track.getId(); - return; - } + track = contentProviderUtils.getLastTrack(); + if (track != null) { + trackId = track.getId(); + return; } finish(); } @@ -465,20 +394,9 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA * Updates the menu items. */ private void updateMenuItems(boolean isPaused) { - insertMarkerMenuItem.setVisible(isRecording() && !isPaused); - shareMenuItem.setVisible(!isRecording()); - markerListMenuItem.setShowAsAction(isRecording() ? MenuItem.SHOW_AS_ACTION_NEVER : MenuItem.SHOW_AS_ACTION_IF_ROOM); - String title; - if (isRecording()) { - title = getString(isPaused ? R.string.generic_paused : R.string.generic_recording); - resumeMenuItem.setVisible(false); - } else { - Track track = contentProviderUtils.getTrack(trackId); - title = track != null ? track.getName() : ""; - // Only visible if there aren't other tracks that is recording. - resumeMenuItem.setVisible(recordingTrackId == -1L); - } - setTitle(title); + insertMarkerMenuItem.setVisible(!isPaused); + markerListMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); + setTitle(getString(isPaused ? R.string.generic_paused : R.string.generic_recording)); } public void chooseActivityType(String category) { @@ -492,10 +410,6 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA TrackUtils.updateTrack(this, track, null, category, null, contentProviderUtils); } - private boolean isRecording() { - return trackId == recordingTrackId; - } - private void startRecording() { trackRecordingServiceConnection.startAndBind(this); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java index 4a54b3382..03af17e78 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java @@ -32,7 +32,7 @@ import java.util.ArrayList; import java.util.List; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.TrackDetailActivity; +import de.dennisguse.opentracks.TrackActivityDataHubInterface; import de.dennisguse.opentracks.chart.ChartPoint; import de.dennisguse.opentracks.chart.ChartView; import de.dennisguse.opentracks.content.TrackDataHub; @@ -286,7 +286,7 @@ public class ChartFragment extends Fragment implements TrackDataListener { * Needs to be synchronized because trackDataHub can be accessed by multiple threads. */ private synchronized void resumeTrackDataHub() { - trackDataHub = ((TrackDetailActivity) getActivity()).getTrackDataHub(); + trackDataHub = ((TrackActivityDataHubInterface) getActivity()).getTrackDataHub(); trackDataHub.registerTrackDataListener(this, true, true, true, true); } diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java new file mode 100644 index 000000000..0f50feed0 --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java @@ -0,0 +1,310 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package de.dennisguse.opentracks.fragments; + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Pair; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Spinner; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.TrackRecordedActivity; +import de.dennisguse.opentracks.content.TrackDataHub; +import de.dennisguse.opentracks.content.TrackDataListener; +import de.dennisguse.opentracks.content.data.Track; +import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.content.data.Waypoint; +import de.dennisguse.opentracks.stats.TrackStatistics; +import de.dennisguse.opentracks.util.PreferencesUtils; +import de.dennisguse.opentracks.util.StringUtils; +import de.dennisguse.opentracks.util.TrackIconUtils; + +/** + * A fragment to display track statistics to the user. + * + * @author Sandor Dornbush + * @author Rodrigo Damazio + */ +public class StatisticsRecordedFragment extends Fragment implements TrackDataListener { + + private TrackStatistics trackStatistics = null; + private String category = ""; + + private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { + if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) { + if (isResumed()) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (isResumed()) { + updateUI(); + } + } + }); + } + } + } + }; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.statistics_recorded, container, false); + } + + /* Views */ + private TextView totalTimeValueView; + private TextView distanceValue; + private TextView distanceUnit; + private View activityLabel; + private Spinner activitySpinner; + private TextView movingTimeValue; + private TextView speedAvgLabel; + private TextView speedAvgValue; + private TextView speedAvgUnit; + private TextView speedMaxLabel; + private TextView speedMaxValue; + private TextView speedMaxUnit; + private TextView speedMovingLabel; + private TextView speedMovingValue; + private TextView speedMovingUnit; + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + totalTimeValueView = view.findViewById(R.id.stats_total_time_value); + + distanceValue = view.findViewById(R.id.stats_distance_value); + distanceUnit = view.findViewById(R.id.stats_distance_unit); + + activityLabel = view.findViewById(R.id.stats_activity_type_label); + activitySpinner = view.findViewById(R.id.stats_activity_type_icon); + + movingTimeValue = view.findViewById(R.id.stats_moving_time_value); + + speedAvgLabel = view.findViewById(R.id.stats_average_speed_label); + speedAvgValue = view.findViewById(R.id.stats_average_speed_value); + speedAvgUnit = view.findViewById(R.id.stats_average_speed_unit); + + speedMaxLabel = view.findViewById(R.id.stats_max_speed_label); + speedMaxValue = view.findViewById(R.id.stats_max_speed_value); + speedMaxUnit = view.findViewById(R.id.stats_max_speed_unit); + + speedMovingLabel = view.findViewById(R.id.stats_moving_speed_label); + speedMovingValue = view.findViewById(R.id.stats_moving_speed_value); + speedMovingUnit = view.findViewById(R.id.stats_moving_speed_unit); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + Spinner activityTypeIcon = getView().findViewById(R.id.stats_activity_type_icon); + activityTypeIcon.setAdapter(TrackIconUtils.getIconSpinnerAdapter(getActivity(), "")); + activityTypeIcon.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + ((TrackRecordedActivity) getActivity()).chooseActivityType(category); + } + return true; + } + }); + activityTypeIcon.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { + ((TrackRecordedActivity) getActivity()).chooseActivityType(category); + } + return true; + } + }); + } + + @Override + public void onResume() { + super.onResume(); + PreferencesUtils.register(getContext(), sharedPreferenceChangeListener); + + TrackDataHub trackDataHub = ((TrackRecordedActivity) getActivity()).getTrackDataHub(); + trackDataHub.registerTrackDataListener(this, true, false, true, true); + } + + @Override + public void onPause() { + super.onPause(); + PreferencesUtils.unregister(getContext(), sharedPreferenceChangeListener); + + TrackDataHub trackDataHub = ((TrackRecordedActivity) getActivity()).getTrackDataHub(); + trackDataHub.unregisterTrackDataListener(this); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + totalTimeValueView = null; + + distanceValue = null; + distanceUnit = null; + + activityLabel = null; + activitySpinner = null; + + movingTimeValue = null; + + speedAvgLabel = null; + speedAvgValue = null; + speedAvgUnit = null; + + speedMaxLabel = null; + speedMaxValue = null; + speedMaxUnit = null; + + speedMovingLabel = null; + speedMovingValue = null; + speedMovingUnit = null; + } + + @Override + public void onTrackUpdated(final Track track) { + if (isResumed()) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + if (isResumed()) { + trackStatistics = track != null ? track.getTrackStatistics() : null; + category = track != null ? track.getCategory() : ""; + updateUI(); + } + } + }); + } + } + + @Override + public void clearTrackPoints() { + // We don't care. + } + + @Override + public void onSampledInTrackPoint(TrackPoint trackPoint) { + // We don't care. + } + + @Override + public void onSampledOutTrackPoint(TrackPoint trackPoint) { + // We don't care. + } + + @Override + public void onNewTrackPointsDone() { + // We don't care. + } + + @Override + public void clearWaypoints() { + // We don't care. + } + + @Override + public void onNewWaypoint(Waypoint wpt) { + // We don't care. + } + + @Override + public void onNewWaypointsDone() { + // We don't care. + } + + private void updateUI() { + String trackIconValue = TrackIconUtils.getIconValue(getContext(), category); + + boolean metricUnits = PreferencesUtils.isMetricUnits(getContext()); + boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext(), category); + + // Set total distance + { + double totalDistance = trackStatistics == null ? Double.NaN : trackStatistics.getTotalDistance(); + Pair parts = StringUtils.getDistanceParts(getContext(), totalDistance, metricUnits); + + distanceValue.setText(parts.first); + distanceUnit.setText(parts.second); + } + + // Set activity type + { + activityLabel.setVisibility(trackIconValue != null ? View.VISIBLE : View.GONE); + + activitySpinner.setVisibility(trackIconValue != null ? View.VISIBLE : View.GONE); + activitySpinner.setEnabled(false); + if (trackIconValue != null) { + TrackIconUtils.setIconSpinner(activitySpinner, trackIconValue); + } + } + + // Set time and start datetime + if (trackStatistics != null) { + movingTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getMovingTime())); + totalTimeValueView.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime())); + } + + // Set average speed/pace + { + double speed = trackStatistics != null ? trackStatistics.getAverageSpeed() : Double.NaN; + speedAvgLabel.setText(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); + + Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); + speedAvgValue.setText(parts.first); + speedAvgUnit.setText(parts.second); + } + + // Set max speed/pace + { + double speed = trackStatistics == null ? Double.NaN : trackStatistics.getMaxSpeed(); + + speedMaxLabel.setText(reportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); + + Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); + speedMaxValue.setText(parts.first); + speedMaxUnit.setText(parts.second); + } + + // Set moving speed/pace + { + double speed = trackStatistics != null ? trackStatistics.getAverageMovingSpeed() : Double.NaN; + + speedMovingLabel.setText(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); + + Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); + speedMovingValue.setText(parts.first); + speedMovingUnit.setText(parts.second); + } + } +} diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java similarity index 94% rename from src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java rename to src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java index 8b9c3452f..8f523ee8f 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatsFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java @@ -1,19 +1,3 @@ -/* - * Copyright 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - package de.dennisguse.opentracks.fragments; import android.content.SharedPreferences; @@ -34,7 +18,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.TrackDetailActivity; +import de.dennisguse.opentracks.TrackRecordingActivity; import de.dennisguse.opentracks.content.TrackDataHub; import de.dennisguse.opentracks.content.TrackDataListener; import de.dennisguse.opentracks.content.data.Track; @@ -59,16 +43,17 @@ import de.dennisguse.opentracks.util.UnitConversions; * @author Sandor Dornbush * @author Rodrigo Damazio */ -public class StatsFragment extends Fragment implements TrackDataListener { +public class StatisticsRecordingFragment extends Fragment implements TrackDataListener { - private static final String TAG = StatsFragment.class.getSimpleName(); + private static final String TAG = StatisticsRecordingFragment.class.getSimpleName(); private static final long UI_UPDATE_INTERVAL = UnitConversions.ONE_SECOND_MS; private TrackDataHub trackDataHub; private Handler handlerUpdateUI; - private final TrackRecordingServiceConnection trackRecordingServiceConnection = new TrackRecordingServiceConnection(); + //TODO Initialize immediately and remove in onDestroy() + private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackPoint lastTrackPoint = null; private TrackStatistics lastTrackStatistics = null; @@ -97,6 +82,9 @@ public class StatsFragment extends Fragment implements TrackDataListener { if (PreferencesUtils.getRecordingTrackId(getContext()) != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) { // A recording track id has been set -> Resumes track and starts timer. resumeTrackDataHub(); + if (trackRecordingServiceConnection == null) { + trackRecordingServiceConnection = new TrackRecordingServiceConnection(null); + } trackRecordingServiceConnection.startConnection(getContext()); handlerUpdateUI.post(updateUIeachSecond); @@ -107,7 +95,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.stats, container, false); + return inflater.inflate(R.layout.statistics_recording, container, false); } /* Views */ @@ -224,7 +212,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { - ((TrackDetailActivity) getActivity()).chooseActivityType(category); + ((TrackRecordingActivity) getActivity()).chooseActivityType(category); } return true; } @@ -233,7 +221,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { - ((TrackDetailActivity) getActivity()).chooseActivityType(category); + ((TrackRecordingActivity) getActivity()).chooseActivityType(category); } return true; } @@ -246,6 +234,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { resumeTrackDataHub(); PreferencesUtils.register(getContext(), sharedPreferenceChangeListener); + trackRecordingServiceConnection = new TrackRecordingServiceConnection(null); trackRecordingServiceConnection.startConnection(getContext()); handlerUpdateUI.post(updateUIeachSecond); @@ -263,7 +252,10 @@ public class StatsFragment extends Fragment implements TrackDataListener { @Override public void onStop() { super.onStop(); - trackRecordingServiceConnection.unbind(getContext()); + if (trackRecordingServiceConnection != null) { + trackRecordingServiceConnection.unbind(getContext()); + } + trackRecordingServiceConnection = null; } @Override @@ -393,7 +385,7 @@ public class StatsFragment extends Fragment implements TrackDataListener { * Needs to be synchronized because trackDataHub can be accessed by multiple threads. */ private synchronized void resumeTrackDataHub() { - trackDataHub = ((TrackDetailActivity) getActivity()).getTrackDataHub(); + trackDataHub = ((TrackRecordingActivity) getActivity()).getTrackDataHub(); trackDataHub.registerTrackDataListener(this, true, false, true, true); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 0085fcd03..1ef508f6b 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -41,8 +41,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.TrackDetailActivity; import de.dennisguse.opentracks.TrackListActivity; +import de.dennisguse.opentracks.TrackRecordedActivity; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.data.Waypoint; @@ -743,10 +743,10 @@ public class TrackRecordingService extends Service { private void showNotification(boolean isGpsStarted) { if (isRecording()) { - Intent intent = IntentUtils.newIntent(this, TrackDetailActivity.class) - .putExtra(TrackDetailActivity.EXTRA_TRACK_ID, recordingTrackId); + Intent intent = IntentUtils.newIntent(this, TrackRecordedActivity.class) + .putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, recordingTrackId); PendingIntent pendingIntent = TaskStackBuilder.create(this) - .addParentStack(TrackDetailActivity.class) + .addParentStack(TrackRecordedActivity.class) .addNextIntent(intent) .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/src/main/res/layout/statistics_recorded.xml b/src/main/res/layout/statistics_recorded.xml new file mode 100644 index 000000000..e0762af3b --- /dev/null +++ b/src/main/res/layout/statistics_recorded.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/layout/stats.xml b/src/main/res/layout/statistics_recording.xml similarity index 94% rename from src/main/res/layout/stats.xml rename to src/main/res/layout/statistics_recording.xml index dcd753d99..2c764fdb0 100644 --- a/src/main/res/layout/stats.xml +++ b/src/main/res/layout/statistics_recording.xml @@ -1,18 +1,4 @@ - + diff --git a/src/main/res/layout/track_detail.xml b/src/main/res/layout/track_detail.xml index da16e02b7..1490bfdf0 100644 --- a/src/main/res/layout/track_detail.xml +++ b/src/main/res/layout/track_detail.xml @@ -32,6 +32,4 @@ limitations under the License. android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> - - \ No newline at end of file diff --git a/src/main/res/layout/track_record.xml b/src/main/res/layout/track_record.xml new file mode 100644 index 000000000..1715d9bff --- /dev/null +++ b/src/main/res/layout/track_record.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/res/menu/track_detail.xml b/src/main/res/menu/track_detail.xml index 3fd5d24a1..0f88e6fb2 100644 --- a/src/main/res/menu/track_detail.xml +++ b/src/main/res/menu/track_detail.xml @@ -15,12 +15,6 @@ limitations under the License. -->

- + + + + + + + \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 52cea5f71..86bafac9a 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -236,6 +236,8 @@ limitations under the License. Success Tracks Yes + Today + Yesterday ‘Location access’ GPS not enabled. Tap here to go to %1$s. Press the back button to return.