Compare commits

...

16 Commits

Author SHA1 Message Date
Dennis Guse 9bd4ba489c Release: v3.2.2 2019-10-21 23:00:13 +02:00
Dennis Guse dd55b50dad Re-added actionbar (actually toolbar) to SettingsActivity. 2019-10-21 22:54:23 +02:00
Dennis Guse 1719d21a5b Bugfix: export now really includes sensor data (as double) and import is done as float. 2019-10-21 22:34:33 +02:00
Dennis Guse 75ef8d99d4 SensorDataSet: data unavailable is now NaN. 2019-10-21 22:34:28 +02:00
Dennis Guse ae06fd1680 Bugfix: export sensor data if available and allowed. 2019-10-20 18:39:31 +02:00
Dennis Guse 2b03f7dea8 Use LinearLayout for SearchActivity (show toolbar correctly). 2019-10-20 17:05:09 +02:00
Dennis Guse 7591b012b4 Extracted ShareActionProvider setup code into a separate class. 2019-10-20 16:55:28 +02:00
Dennis Guse 0e089f49f3 Re-added application logo to material design toolbar. 2019-10-19 12:27:11 +02:00
Dennis Guse 5ad1856b13 Removed context menu from ListActivities. 2019-10-17 21:32:55 +02:00
Dennis Guse 965dbbe829 Removed custom action bar style. 2019-10-17 21:26:31 +02:00
Dennis Guse 262c9886df Removed aggregated stats activity. 2019-10-17 21:22:07 +02:00
Dennis Guse ac5a9ea65d Use Androidx compat's toolbar instead of actionbars.
ListView's multiselect still uses actionbar.
2019-10-17 21:19:14 +02:00
Dennis Guse ed9b4c8f3d Add workaround for Compat's ShareActionProvider, which is not available when inflating in a AbsListView.MultiChoiceModeListener. 2019-10-17 18:33:45 +02:00
Dennis Guse 209aa6a8a5 Hide share action from SearchActivity as it is not (yet) functional. 2019-10-17 07:58:11 +02:00
Dennis Guse 81ee6ac1fa Do not use custom style for AlertDialogs, so PreferenceDialogs and AlertDialogs look the same. 2019-10-17 06:38:05 +02:00
Dennis Guse 024dd603cb Migration to Androidx PreferenceCompat. 2019-10-17 06:00:47 +02:00
42 changed files with 418 additions and 451 deletions
+2 -2
View File
@@ -8,5 +8,5 @@
4. Create changelog (`_version code_.txt`)
5. Create commit with all changes
6. Push commits
7. Tag newly create commit with _version name_
8. Push the tagged to public repository
7. Tag newly create commit with _version name_ (e.g., v3.2.1)
8. Push the tagged commit to public repository
@@ -0,0 +1,13 @@
v3.2.2: OpenTracks
Changes:
- Removed aggregated stats
- Migrated to Material Design
Bugfix:
- Fixed export of sensor data
- Fixed import of incomplete sensor data
Developer:
- Replaced actionbar with toolbar
- Migrated to androidx appcompat (incl. Material Design)
+2 -6
View File
@@ -16,8 +16,8 @@ limitations under the License.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.dennisguse.opentracks"
android:installLocation="auto"
android:versionCode="3063"
android:versionName="v3.2.1"> <!-- For FDroid. -->
android:versionCode="3079"
android:versionName="v3.2.2"> <!-- For FDroid. -->
<!-- Permission to initialize services -->
<application
android:name=".Startup"
@@ -30,10 +30,6 @@ limitations under the License.
<!-- Activities -->
<activity android:name=".AboutActivity" />
<activity
android:name=".AggregatedStatsActivity"
android:label="@string/menu_aggregated_statistics" />
<activity android:name=".DeleteActivity" />
<activity
@@ -19,12 +19,13 @@ package de.dennisguse.opentracks;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import androidx.fragment.app.FragmentActivity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/**
* @author Jimmy Shih
*/
public abstract class AbstractActivity extends FragmentActivity {
public abstract class AbstractActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -34,6 +35,9 @@ public abstract class AbstractActivity extends FragmentActivity {
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
setContentView(getLayoutResId());
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
/**
@@ -16,24 +16,7 @@
package de.dennisguse.opentracks;
import android.app.Activity;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.SearchView;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller;
@@ -58,115 +41,6 @@ public abstract class AbstractListActivity extends AbstractActivity implements C
protected static final int GPS_REQUEST_CODE = 6;
private static final int DELETE_REQUEST_CODE = 3;
public static void configureListViewContextualMenu(final ListView listView, final ContextualActionModeCallback contextualActionModeCallback) {
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.list_context_menu, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
contextualActionModeCallback.onPrepare(menu, getCheckedPositions(listView), listView.getCheckedItemIds(), true);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// Do nothing
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
mode.invalidate();
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (contextualActionModeCallback.onClick(item.getItemId(), getCheckedPositions(listView), listView.getCheckedItemIds())) {
mode.finish();
}
return true;
}
/**
* Gets the checked positions in a list view.
*
* @param list the list view
*/
private int[] getCheckedPositions(ListView list) {
SparseBooleanArray positions = list.getCheckedItemPositions();
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < positions.size(); i++) {
int key = positions.keyAt(i);
if (positions.valueAt(i)) {
arrayList.add(key);
}
}
int[] result = new int[arrayList.size()];
for (int i = 0; i < arrayList.size(); i++) {
result[i] = arrayList.get(i);
}
return result;
}
});
}
public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) {
final SearchView searchView = (SearchView) menuItem.getActionView();
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null) {
//NOTE: for some reason activity.getComponentName() did not trigger the SearchListActivity
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(activity, SearchListActivity.class)));
} else {
Log.w(TAG, "Could not retrieve SearchManager.");
}
searchView.setQueryRefinementEnabled(true);
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// Hide and show trackController when searchable widget has focus/no focus
if (trackController != null) {
if (hasFocus) {
trackController.hide();
} else {
trackController.show();
}
}
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
menuItem.collapseActionView();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
@Override
public boolean onSuggestionSelect(int position) {
return false;
}
@Override
public boolean onSuggestionClick(int position) {
menuItem.collapseActionView();
return false;
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DELETE_REQUEST_CODE) {
@@ -208,10 +82,9 @@ public abstract class AbstractListActivity extends AbstractActivity implements C
}
/**
* Gets the track recording service connection. For stopping the current
* recording if need to delete the current recording track.
* Gets the track recording service connection.
* For stopping the current recording if need to delete the current recording track.
*/
@NonNull
abstract protected TrackRecordingServiceConnection getTrackRecordingServiceConnection();
/**
@@ -1,62 +0,0 @@
/*
* Copyright 2012 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.os.Bundle;
import java.util.List;
import de.dennisguse.opentracks.content.ContentProviderUtils;
import de.dennisguse.opentracks.content.Track;
import de.dennisguse.opentracks.stats.TripStatistics;
import de.dennisguse.opentracks.util.StatsUtils;
/**
* An activity to view aggregated stats from all recorded tracks.
*
* @author Fergus Nelson
*/
public class AggregatedStatsActivity extends AbstractActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatsUtils.setTripStatisticsValues(this, getTripStatistics(), null);
StatsUtils.setLocationValues(this, null, false);
}
@Override
protected int getLayoutResId() {
return R.layout.stats;
}
/**
* Gets the aggregated trip statistics for all the recorded tracks or null if
* there is no track.
*/
private TripStatistics getTripStatistics() {
List<Track> tracks = ContentProviderUtils.Factory.get(this).getAllTracks();
TripStatistics tripStatistics = null;
if (!tracks.isEmpty()) {
tripStatistics = new TripStatistics(tracks.iterator().next().getTripStatistics());
for (int i = 1; i < tracks.size(); i++) {
tripStatistics.merge(tracks.get(i).getTripStatistics());
}
}
return tripStatistics;
}
}
@@ -22,14 +22,11 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
@@ -46,6 +43,7 @@ import de.dennisguse.opentracks.content.Waypoint.WaypointType;
import de.dennisguse.opentracks.content.WaypointsColumns;
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment;
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -175,7 +173,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
}
};
listView.setAdapter(resourceCursorAdapter);
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback);
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
LoaderManager.getInstance(this).initLoader(0, null, new LoaderCallbacks<Cursor>() {
@NonNull
@@ -234,7 +232,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker);
searchMenuItem = menu.findItem(R.id.marker_list_search);
AbstractListActivity.configureSearchWidget(this, searchMenuItem, null);
ActivityUtils.configureSearchWidget(this, searchMenuItem, null);
return super.onCreateOptionsMenu(menu);
}
@@ -256,24 +254,6 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_context_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
contextualActionModeCallback.onPrepare(menu, new int[]{info.position}, new long[]{info.id}, false);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
if (handleContextItem(item.getItemId(), new long[]{info.id})) {
return true;
}
return super.onContextItemSelected(item);
}
/**
* Handles a context item selection.
*
@@ -22,14 +22,11 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -55,10 +52,12 @@ import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment;
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.stats.TripStatistics;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils;
/**
@@ -111,26 +110,31 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
boolean isSingleSelection = positions.length == 1;
boolean isSingleSelectionTrack;
if (isSingleSelection) {
Map<String, Object> item = arrayAdapter.getItem(positions[0]);
Long trackId = (Long) item.get(TRACK_ID_FIELD);
Track track = contentProviderUtils.getTrack(trackId);
isSingleSelectionTrack = item.get(MARKER_ID_FIELD) == null;
} else {
isSingleSelectionTrack = false;
}
// Not recording, one item, item is a track
menu.findItem(R.id.list_context_menu_share).setVisible(!isRecording && isSingleSelection && isSingleSelectionTrack);
//TODO Setup shareIntent.
MenuItem shareMenuItem = menu.findItem(R.id.list_context_menu_share);
if (isSingleSelectionTrack) {
shareMenuItem.setVisible(!isRecording);
Map<String, Object> item = arrayAdapter.getItem(positions[0]);
Long trackId = (Long) item.get(TRACK_ID_FIELD);
ToolbarUtils.setupShareActionProvider(SearchListActivity.this, shareMenuItem, new long[]{trackId});
}
// One item, item is a marker
menu.findItem(R.id.list_context_menu_show_on_map).setVisible(isSingleSelection && !isSingleSelectionTrack);
// One item, can be a track or a marker
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
// One item. If track, no restriction.
menu.findItem(R.id.list_context_menu_delete).setVisible(isSingleSelection && (isSingleSelectionTrack));
menu.findItem(R.id.list_context_menu_delete).setVisible(isSingleSelection && isSingleSelectionTrack);
// Disable select all, no action is available for multiple selection
menu.findItem(R.id.list_context_menu_select_all).setVisible(false);
}
@@ -222,7 +226,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
startActivity(intent);
}
});
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback);
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
handleIntent(getIntent());
}
@@ -259,24 +263,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
handleIntent(intent);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_context_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
contextualActionModeCallback.onPrepare(menu, new int[]{info.position}, new long[]{info.id}, false);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
if (handleContextItem(item.getItemId(), new int[]{info.position})) {
return true;
}
return super.onContextItemSelected(item);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
@@ -301,10 +287,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
Long markerId = (Long) item.get(MARKER_ID_FIELD);
Intent intent;
switch (itemId) {
case R.id.list_context_menu_share:
//TODO
Log.e(TAG, "Not implemented");
return true;
case R.id.list_context_menu_show_on_map:
IntentUtils.showCoordinateOnMap(this, (double) item.get(MARKER_LATITUDE_FIELD), (double) item.get(MARKER_LONGITUDE_FIELD), item.get(NAME_FIELD) + "");
return true;
@@ -130,11 +130,11 @@ public class TrackController {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
}
void hide() {
public void hide() {
containerView.setVisibility(View.GONE);
}
void show() {
public void show() {
containerView.setVisibility(View.VISIBLE);
}
@@ -31,7 +31,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ShareActionProvider;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.Toast;
@@ -56,6 +55,7 @@ import de.dennisguse.opentracks.settings.SettingsActivity;
import de.dennisguse.opentracks.util.FileUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils;
@@ -318,8 +318,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
insertPhotoMenuItem.setVisible(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(getPackageManager()) != null);
shareMenuItem = menu.findItem(R.id.track_detail_share);
ShareActionProvider shareActionProvider = (ShareActionProvider) shareMenuItem.getActionProvider();
shareActionProvider.setShareIntent(IntentUtils.newShareFileIntent(this, new long[]{trackId}));
ToolbarUtils.setupShareActionProviderCompat(this, shareMenuItem, new long[]{trackId});
voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency);
splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency);
@@ -392,6 +391,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@@ -28,8 +28,6 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
@@ -37,14 +35,12 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.ShareActionProvider;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.core.app.ActivityCompat;
import androidx.cursoradapter.widget.ResourceCursorAdapter;
import androidx.loader.app.LoaderManager;
@@ -60,10 +56,12 @@ import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.services.ITrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.settings.SettingsActivity;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils;
@@ -118,8 +116,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
boolean isSingleSelection = trackIds.length == 1;
MenuItem shareMenuItem = menu.findItem(R.id.list_context_menu_share);
ShareActionProvider shareActionProvider = (ShareActionProvider) shareMenuItem.getActionProvider();
shareActionProvider.setShareIntent(trackIds.length == 0 ? null : IntentUtils.newShareFileIntent(TrackListActivity.this, trackIds));
ToolbarUtils.setupShareActionProvider(TrackListActivity.this, shareMenuItem, trackIds);
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
menu.findItem(R.id.list_context_menu_select_all).setVisible(showSelectAll);
@@ -175,7 +172,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
// Menu items
private MenuItem searchMenuItem;
private MenuItem startGpsMenuItem;
private MenuItem aggregatedStatisticsMenuItem;
private MenuItem deleteAllMenuItem;
private final OnClickListener stopListener = new OnClickListener() {
@@ -317,7 +313,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
}
};
listView.setAdapter(resourceCursorAdapter);
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback);
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks);
showStartupDialogs();
@@ -379,10 +376,9 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
getMenuInflater().inflate(R.menu.track_list, menu);
searchMenuItem = menu.findItem(R.id.track_list_search);
AbstractListActivity.configureSearchWidget(this, searchMenuItem, trackController);
ActivityUtils.configureSearchWidget(this, searchMenuItem, trackController);
startGpsMenuItem = menu.findItem(R.id.track_list_start_gps);
aggregatedStatisticsMenuItem = menu.findItem(R.id.track_list_aggregated_statistics);
deleteAllMenuItem = menu.findItem(R.id.track_list_delete_all);
return super.onCreateOptionsMenu(menu);
@@ -394,10 +390,9 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
updateMenuItems(isGpsStarted, isRecording);
View searchView = searchMenuItem.getActionView();
if (searchView instanceof SearchView) {
((SearchView) searchView).setQuery("", false);
}
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setQuery("", false);
return super.onPrepareOptionsMenu(menu);
}
@@ -438,10 +433,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
intent = IntentUtils.newIntent(this, MarkerListActivity.class);
startActivity(intent);
return true;
case R.id.track_list_aggregated_statistics:
intent = IntentUtils.newIntent(this, AggregatedStatsActivity.class);
startActivity(intent);
return true;
case R.id.track_list_delete_all:
deleteTracks(new long[]{-1L});
return true;
@@ -453,24 +444,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.list_context_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
contextualActionModeCallback.onPrepare(menu, new int[]{info.position}, new long[]{info.id}, false);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
if (handleContextItem(item.getItemId(), new long[]{info.id})) {
return true;
}
return super.onContextItemSelected(item);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH && searchMenuItem != null) {
@@ -530,9 +503,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
startGpsMenuItem.setIcon(isGpsStarted ? R.drawable.ic_gps_fixed_24dp : R.drawable.ic_gps_off_24dp);
}
}
if (aggregatedStatisticsMenuItem != null) {
aggregatedStatisticsMenuItem.setVisible(hasTrack);
}
if (deleteAllMenuItem != null) {
deleteAllMenuItem.setVisible(hasTrack && !isRecording);
}
@@ -2,7 +2,7 @@ package de.dennisguse.opentracks.content.sensor;
public final class SensorDataSet {
public static final float DATA_UNAVAILABLE = Integer.MAX_VALUE;
public static final float DATA_UNAVAILABLE = Float.NaN;
//TODO It might be necessary to consider: sensor if sensor was connected as well.
public String sensorName;
@@ -40,7 +40,7 @@ public final class SensorDataSet {
}
public boolean hasHeartRate() {
return heartRate != DATA_UNAVAILABLE;
return !Float.isNaN(heartRate);
}
public float getHeartRate() {
@@ -48,7 +48,7 @@ public final class SensorDataSet {
}
public boolean hasCadence() {
return cadence != DATA_UNAVAILABLE;
return !Float.isNaN(cadence);
}
public float getCadence() {
@@ -56,7 +56,7 @@ public final class SensorDataSet {
}
public boolean hasPower() {
return power != DATA_UNAVAILABLE;
return !Float.isNaN(power);
}
public float getPower() {
@@ -77,7 +77,7 @@ public final class SensorDataSet {
}
public boolean hasBatteryLevel() {
return batteryLevel != DATA_UNAVAILABLE;
return !Float.isNaN(batteryLevel);
}
public float getBatteryLevel() {
@@ -49,9 +49,10 @@ public class KmlTrackWriter implements TrackWriter {
private static final String END_STYLE = "end";
private static final String TRACK_STYLE = "track";
private static final String SCHEMA_ID = "schema";
private static final String CADENCE = "cadence";
private static final String HEART_RATE = "heart_rate";
private static final String POWER = "power";
private static final String SENSOR_TYPE_CADENCE = "cadence";
private static final String SENSOR_TYPE_HEART_RATE = "heart_rate";
private static final String SENSOR_TYPE_POWER = "power";
private static final String WAYPOINT_ICON = "http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png";
private static final String STATISTICS_ICON = "http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png";
@@ -71,9 +72,6 @@ public class KmlTrackWriter implements TrackWriter {
private List<Float> powerList = new ArrayList<>();
private List<Float> cadenceList = new ArrayList<>();
private List<Float> heartRateList = new ArrayList<>();
private boolean hasPower;
private boolean hasCadence;
private boolean hasHeartRate;
private Location startLocation;
@@ -132,9 +130,9 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<Schema id=\"" + SCHEMA_ID + "\">");
if (exportSensorData) {
writeSensorStyle(POWER, context.getString(R.string.description_sensor_power));
writeSensorStyle(CADENCE, context.getString(R.string.description_sensor_cadence));
writeSensorStyle(HEART_RATE, context.getString(R.string.description_sensor_heart_rate));
writeSensorStyle(SENSOR_TYPE_POWER, context.getString(R.string.description_sensor_power));
writeSensorStyle(SENSOR_TYPE_CADENCE, context.getString(R.string.description_sensor_cadence));
writeSensorStyle(SENSOR_TYPE_HEART_RATE, context.getString(R.string.description_sensor_heart_rate));
}
printWriter.println("</Schema>");
}
@@ -235,9 +233,6 @@ public class KmlTrackWriter implements TrackWriter {
public void writeOpenSegment() {
if (printWriter != null) {
printWriter.println("<gx:Track>");
hasPower = false;
hasCadence = false;
hasHeartRate = false;
powerList.clear();
cadenceList.clear();
heartRateList.clear();
@@ -250,14 +245,14 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<ExtendedData>");
printWriter.println("<SchemaData schemaUrl=\"#" + SCHEMA_ID + "\">");
if (exportSensorData) {
if (hasPower) {
writeSensorData(powerList, POWER);
if (powerList.size() > 0) {
writeSensorData(powerList, SENSOR_TYPE_POWER);
}
if (hasCadence) {
writeSensorData(cadenceList, CADENCE);
if (cadenceList.size() > 0) {
writeSensorData(cadenceList, SENSOR_TYPE_CADENCE);
}
if (hasHeartRate) {
writeSensorData(heartRateList, HEART_RATE);
if (heartRateList.size() > 0) {
writeSensorData(heartRateList, SENSOR_TYPE_HEART_RATE);
}
}
printWriter.println("</SchemaData>");
@@ -466,11 +461,11 @@ public class KmlTrackWriter implements TrackWriter {
* Writes a sensor style.
*
* @param name the name of the sesnor
* @param displayName the sensor display name
* @param sensorType the sensor display name
*/
private void writeSensorStyle(String name, String displayName) {
printWriter.println("<gx:SimpleArrayField name=\"" + name + "\" type=\"int\">");
printWriter.println("<displayName>" + StringUtils.formatCData(displayName) + "</displayName>");
private void writeSensorStyle(String name, String sensorType) {
printWriter.println("<gx:SimpleArrayField name=\"" + name + "\" type=\"float\">");
printWriter.println("<displayName>" + StringUtils.formatCData(sensorType) + "</displayName>");
printWriter.println("</gx:SimpleArrayField>");
}
}
@@ -384,8 +384,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
* @param message the message
*/
protected String createErrorMessage(String message) {
return String.format(Locale.US, "Parsing error at line: %d column: %d. %s",
locator.getLineNumber(), locator.getColumnNumber(), message);
return String.format(Locale.US, "Parsing error at line: %d column: %d. %s", locator.getLineNumber(), locator.getColumnNumber(), message);
}
/**
@@ -19,6 +19,7 @@ package de.dennisguse.opentracks.io.file.importer;
import android.content.Context;
import android.location.Location;
import android.net.Uri;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -39,6 +40,8 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet;
*/
public class KmlFileTrackImporter extends AbstractFileTrackImporter {
private static final String TAG = KmlFileTrackImporter.class.getSimpleName();
private static final String CADENCE = "cadence";
private static final String HEART_RATE = "heart_rate";
private static final String POWER = "power";
@@ -65,11 +68,11 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
private static final String ATTRIBUTE_NAME = "name";
private boolean trackStarted = false;
private String sensorName;
private String sensorType;
private ArrayList<Location> locationList;
private ArrayList<Integer> cadenceList;
private ArrayList<Integer> heartRateList;
private ArrayList<Integer> powerList;
private ArrayList<Float> cadenceList;
private ArrayList<Float> heartRateList;
private ArrayList<Float> powerList;
/**
* Constructor.
@@ -229,20 +232,30 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
*/
private void onTrackSegmentEnd() {
// Close a track segment by inserting the segment locations
boolean hasHeartRate = heartRateList.size() == locationList.size();
boolean hasCadence = cadenceList.size() == locationList.size();
boolean hasPower = powerList.size() == locationList.size();
for (int i = 0; i < locationList.size(); i++) {
Location location = locationList.get(i);
if (!hasPower && !hasCadence && !hasHeartRate) {
boolean hasSensorData = false;
float heartrate = SensorDataSet.DATA_UNAVAILABLE;
float cadence = SensorDataSet.DATA_UNAVAILABLE;
float power = SensorDataSet.DATA_UNAVAILABLE;
if (i < heartRateList.size()) {
heartrate = heartRateList.get(i);
hasSensorData = true;
}
if (i < cadenceList.size()) {
cadence = cadenceList.get(i);
hasSensorData = true;
}
if (i < powerList.size()) {
power = powerList.get(i);
hasSensorData = true;
}
if (!hasSensorData) {
insertTrackPoint(location);
} else {
float heartrate = hasHeartRate ? heartRateList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
float cadence = hasHeartRate ? cadenceList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
float power = hasHeartRate ? powerList.get(i) : SensorDataSet.DATA_UNAVAILABLE;
SensorDataSetLocation sensorDataSetLocation = new SensorDataSetLocation(location, new SensorDataSet(heartrate, cadence, power, SensorDataSet.DATA_UNAVAILABLE, location.getTime()));
insertTrackPoint(sensorDataSetLocation);
}
@@ -277,7 +290,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
* On sensor data start. gx:SimpleArrayData start tag.
*/
private void onSensorDataStart(Attributes attributes) {
sensorName = attributes.getValue(ATTRIBUTE_NAME);
sensorType = attributes.getValue(ATTRIBUTE_NAME);
}
/**
@@ -291,18 +304,24 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
if (content.equals("")) {
return;
}
int value;
float value;
try {
value = Integer.parseInt(content);
value = Float.valueOf(content);
} catch (NumberFormatException e) {
throw new SAXException(createErrorMessage("Unable to parse gx:value:" + content), e);
}
if (POWER.equals(sensorName)) {
powerList.add(value);
} else if (HEART_RATE.equals(sensorName)) {
heartRateList.add(value);
} else if (CADENCE.equals(sensorName)) {
cadenceList.add(value);
switch (sensorType) {
case POWER:
powerList.add(value);
break;
case HEART_RATE:
heartRateList.add(value);
break;
case CADENCE:
cadenceList.add(value);
break;
default:
Log.w(TAG, "Data from sensor " + sensorType + " is not (yet) supported.");
}
}
}
@@ -853,7 +853,7 @@ public class TrackRecordingService extends Service {
*/
private void insertLocation(Track track, Location location, Location lastValidTrackPoint) {
if (location == null) {
Log.w(TAG, "Ignore insertLocation. loation is null.");
Log.w(TAG, "Ignore insertLocation. location is null.");
return;
}
// Do not insert if inserted already
@@ -27,9 +27,8 @@ import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Spinner;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragment;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
@@ -67,7 +66,7 @@ public class ActivityTypePreference extends DialogPreference {
return R.layout.preference_activity_type;
}
public static class ActivityPreferenceDialog extends PreferenceDialogFragment {
public static class ActivityPreferenceDialog extends PreferenceDialogFragmentCompat {
private AutoCompleteTextView textView;
private Spinner spinner;
@@ -75,7 +74,7 @@ public class ActivityTypePreference extends DialogPreference {
static ActivityPreferenceDialog newInstance(String preferenceKey) {
ActivityTypePreference.ActivityPreferenceDialog dialog = new ActivityTypePreference.ActivityPreferenceDialog();
final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey);
bundle.putString(PreferenceDialogFragmentCompat.ARG_KEY, preferenceKey);
dialog.setArguments(bundle);
return dialog;
@@ -134,10 +133,7 @@ public class ActivityTypePreference extends DialogPreference {
private void showIconSelectDialog() {
String category = PreferencesUtils.getString(getActivity(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
// TODO Remove casting when upgrading to new Androidx compat.
FragmentActivity fragmentActivity = (androidx.fragment.app.FragmentActivity) getActivity();
ChooseActivityTypeDialogFragment.showDialog(fragmentActivity.getSupportFragmentManager(), category);
ChooseActivityTypeDialogFragment.showDialog(getActivity().getSupportFragmentManager(), category);
}
@Override
@@ -6,7 +6,7 @@ import android.util.AttributeSet;
import android.widget.Toast;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragment;
import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -17,12 +17,12 @@ public class ResetDialogPreference extends DialogPreference {
super(context, attrs);
}
public static class ResetPreferenceDialog extends PreferenceDialogFragment {
public static class ResetPreferenceDialog extends PreferenceDialogFragmentCompat {
static PreferenceDialogFragment newInstance(String preferenceKey) {
static PreferenceDialogFragmentCompat newInstance(String preferenceKey) {
ResetPreferenceDialog dialog = new ResetPreferenceDialog();
final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey);
bundle.putString(PreferenceDialogFragmentCompat.ARG_KEY, preferenceKey);
dialog.setArguments(bundle);
return dialog;
@@ -1,20 +1,21 @@
package de.dennisguse.opentracks.settings;
import android.app.DialogFragment;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceFragmentCompat;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
public class SettingsActivity extends FragmentActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
public class SettingsActivity extends AppCompatActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
private PrefsFragment prefsFragment = new PrefsFragment();
@@ -22,7 +23,13 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, prefsFragment).commit();
setContentView(R.layout.settings);
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle(R.string.menu_settings);
setSupportActionBar(toolbar);
getSupportFragmentManager().beginTransaction().replace(R.id.settings_fragment, prefsFragment).commit();
}
@Override
@@ -30,7 +37,7 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
prefsFragment.setDefaultActivity(iconValue);
}
public static class PrefsFragment extends PreferenceFragment {
public static class PrefsFragment extends PreferenceFragmentCompat {
/*
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
@@ -62,7 +69,7 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.settings);
setPreferencesFromResource(R.xml.settings, rootKey);
updateUnits();
}
@@ -0,0 +1,137 @@
package de.dennisguse.opentracks.util;
import android.app.Activity;
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import androidx.appcompat.widget.SearchView;
import java.util.ArrayList;
import de.dennisguse.opentracks.ContextualActionModeCallback;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.SearchListActivity;
import de.dennisguse.opentracks.TrackController;
public class ActivityUtils {
private static final String TAG = ActivityUtils.class.getSimpleName();
public static void configureListViewContextualMenu(final ListView listView, final ContextualActionModeCallback contextualActionModeCallback) {
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.list_context_menu, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
contextualActionModeCallback.onPrepare(menu, getCheckedPositions(listView), listView.getCheckedItemIds(), true);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// Do nothing
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
mode.invalidate();
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (contextualActionModeCallback.onClick(item.getItemId(), getCheckedPositions(listView), listView.getCheckedItemIds())) {
mode.finish();
}
return true;
}
/**
* Gets the checked positions in a list view.
*
* @param list the list view
*/
private int[] getCheckedPositions(ListView list) {
SparseBooleanArray positions = list.getCheckedItemPositions();
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < positions.size(); i++) {
int key = positions.keyAt(i);
if (positions.valueAt(i)) {
arrayList.add(key);
}
}
int[] result = new int[arrayList.size()];
for (int i = 0; i < arrayList.size(); i++) {
result[i] = arrayList.get(i);
}
return result;
}
});
}
public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) {
final SearchView searchView = (SearchView) menuItem.getActionView();
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
if (searchManager != null) {
//NOTE: for some reason activity.getComponentName() did not trigger the SearchListActivity
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(activity, SearchListActivity.class)));
} else {
Log.w(TAG, "Could not retrieve SearchManager.");
}
searchView.setQueryRefinementEnabled(true);
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// Hide and show trackController when searchable widget has focus/no focus
if (trackController != null) {
if (hasFocus) {
trackController.hide();
} else {
trackController.show();
}
}
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
menuItem.collapseActionView();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
@Override
public boolean onSuggestionSelect(int position) {
return false;
}
@Override
public boolean onSuggestionClick(int position) {
menuItem.collapseActionView();
return false;
}
});
}
}
@@ -0,0 +1,32 @@
package de.dennisguse.opentracks.util;
import android.content.Context;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.ShareActionProvider;
import androidx.core.internal.view.SupportMenuItem;
import androidx.core.view.MenuItemCompat;
public class ToolbarUtils {
private ToolbarUtils() {
}
//TODO Compat is not working as the AbsListView.MultiChoiceModeListener; instantiating it manually using the non-compat is a workaround.
@Deprecated
public static void setupShareActionProvider(@NonNull Context context, @NonNull MenuItem shareMenuItem, @NonNull long[] trackIds) {
android.widget.ShareActionProvider shareActionProvider = new android.widget.ShareActionProvider(context);
shareActionProvider.setShareIntent(trackIds.length == 0 ? null : IntentUtils.newShareFileIntent(context, trackIds));
shareMenuItem.setActionProvider(shareActionProvider);
}
/**
* @param shareMenuItem Should be a {@link SupportMenuItem}.
*/
public static void setupShareActionProviderCompat(@NonNull Context context, @NonNull MenuItem shareMenuItem, @NonNull long[] trackIds) {
ShareActionProvider shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem);
shareActionProvider.setShareIntent(trackIds.length == 0 ? null : IntentUtils.newShareFileIntent(context, trackIds));
MenuItemCompat.setActionProvider(shareMenuItem, shareActionProvider);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

+4 -1
View File
@@ -16,7 +16,10 @@ limitations under the License.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false">
android:baselineAligned="false"
android:orientation="horizontal">
<include layout="@layout/toolbar" />
<include layout="@layout/track_controller" />
+2
View File
@@ -4,6 +4,8 @@
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
@@ -17,6 +17,8 @@ limitations under the License.
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar" />
<androidx.viewpager.widget.ViewPager
android:id="@+id/maker_detail_activity_view_pager"
android:layout_width="match_parent"
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ScrollView style="@style/ScrollView.WithBottomButtons">
<LinearLayout
+6 -3
View File
@@ -13,9 +13,12 @@ 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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView
android:id="@+id/marker_list"
@@ -26,4 +29,4 @@ limitations under the License.
android:id="@+id/marker_list_empty"
style="@style/ListEmptyTextView"
android:text="@string/marker_list_empty_message" />
</merge>
</LinearLayout>
+6 -3
View File
@@ -13,9 +13,12 @@ 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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView
android:id="@+id/search_list"
@@ -26,4 +29,4 @@ limitations under the License.
android:id="@+id/search_list_empty"
style="@style/ListEmptyTextView"
android:text="@string/search_list_empty_message" />
</merge>
</LinearLayout>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<FrameLayout
android:id="@+id/settings_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_logo_color_24dp" />
</merge>
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<TabHost
android:id="@+id/tackdetail_tabhost"
android:layout_width="match_parent"
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ScrollView style="@style/ScrollView.WithBottomButtons">
<LinearLayout
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView
android:id="@+id/track_list"
android:layout_width="match_parent"
+13 -12
View File
@@ -13,30 +13,31 @@ 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/list_context_menu_share"
android:actionProviderClass="android.widget.ShareActionProvider"
android:showAsAction="ifRoom"
android:title="@string/menu_share" />
android:title="@string/menu_share"
app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider"
app:showAsAction="ifRoom" />
<item
android:id="@+id/list_context_menu_show_on_map"
android:icon="@drawable/ic_map_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_show_on_map" />
android:title="@string/menu_show_on_map"
app:showAsAction="ifRoom" />
<item
android:id="@+id/list_context_menu_edit"
android:icon="@drawable/ic_edit_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_edit" />
android:title="@string/menu_edit"
app:showAsAction="ifRoom" />
<item
android:id="@+id/list_context_menu_delete"
android:icon="@drawable/ic_delete_forever_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_delete" />
android:title="@string/menu_delete"
app:showAsAction="ifRoom" />
<item
android:id="@+id/list_context_menu_select_all"
android:icon="@drawable/ic_select_all_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_select_all" />
android:title="@string/menu_select_all"
app:showAsAction="ifRoom" />
</menu>
+8 -7
View File
@@ -13,20 +13,21 @@ 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/marker_detail_show_on_map"
android:icon="@drawable/ic_map_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_show_on_map" />
android:title="@string/menu_show_on_map"
app:showAsAction="ifRoom" />
<item
android:id="@+id/marker_detail_edit"
android:icon="@drawable/ic_edit_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_edit" />
android:title="@string/menu_edit"
app:showAsAction="ifRoom" />
<item
android:id="@+id/marker_detail_delete"
android:icon="@drawable/ic_delete_forever_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_delete" />
android:title="@string/menu_delete"
app:showAsAction="ifRoom" />
</menu>
+7 -6
View File
@@ -13,15 +13,16 @@ 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/marker_list_insert_marker"
android:icon="@drawable/ic_marker_show_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_insert_marker" />
android:title="@string/menu_insert_marker"
app:showAsAction="ifRoom" />
<item
android:id="@+id/marker_list_search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="ifRoom"
android:title="@string/menu_search" />
android:title="@string/menu_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom" />
</menu>
+7 -6
View File
@@ -13,29 +13,30 @@ 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/track_detail_insert_marker"
android:icon="@drawable/ic_marker_add_24dp"
android:orderInCategory="1"
android:showAsAction="ifRoom"
app:showAsAction="ifRoom"
android:title="@string/menu_insert_marker" />
<item
android:id="@+id/track_detail_insert_photo"
android:icon="@drawable/ic_camera_24dp"
android:orderInCategory="2"
android:showAsAction="ifRoom"
app:showAsAction="ifRoom"
android:title="@string/menu_insert_photo" />
<item
android:id="@+id/track_detail_menu_show_on_map"
android:icon="@drawable/ic_map_24dp"
android:showAsAction="ifRoom"
app:showAsAction="ifRoom"
android:title="@string/menu_show_on_map" />
<item
android:id="@+id/track_detail_share"
android:actionProviderClass="android.widget.ShareActionProvider"
app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider"
android:orderInCategory="4"
android:showAsAction="ifRoom"
app:showAsAction="ifRoom"
android:title="@string/menu_share" />
<item
android:id="@+id/track_detail_markers"
+9 -12
View File
@@ -13,27 +13,24 @@ 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/track_list_search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="ifRoom"
android:title="@string/menu_search" />
android:title="@string/menu_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom" />
<!-- Icon and title is overwritten by TrackListActivity -->
<item
android:id="@+id/track_list_start_gps"
android:icon="@drawable/ic_gps_off_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_start_gps" />
android:title="@string/menu_start_gps"
app:showAsAction="ifRoom" />
<item
android:id="@+id/track_list_markers"
android:icon="@drawable/ic_marker_show_24dp"
android:showAsAction="ifRoom"
android:title="@string/menu_markers" />
<item
android:id="@+id/track_list_aggregated_statistics"
android:icon="@drawable/ic_statistics_24dp"
android:title="@string/menu_aggregated_statistics" />
android:title="@string/menu_markers"
app:showAsAction="ifRoom" />
<item
android:id="@+id/track_list_delete_all"
android:icon="@drawable/ic_delete_forever_24dp"
-5
View File
@@ -15,11 +15,6 @@ limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="ActionBarStyleCustom" parent="@android:style/Widget.Holo.ActionBar">
<!-- Same image as the source except using a grey line instead of a blue line -->
<item name="android:background">@drawable/ab_transparent_dark_holo</item>
</style>
<style name="BottomButton" parent="@android:style/Widget.Holo.Button.Borderless">
<!-- Same as BottomButton in values/styles.xml except inheriting from Widget.Holo.Button.Borderles. -->
<item name="android:layout_height">wrap_content</item>
+7 -24
View File
@@ -15,7 +15,8 @@ limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="ThemeCustom" parent="android:Theme.Holo">
<style name="ThemeCustom" parent="Theme.AppCompat.NoActionBar">
<!-- TODO Cleanup necessary due to change to appcompat -->
<!-- Auto generated -->
<item name="android:activatedBackgroundIndicator">@drawable/activated_background_holo_dark
</item>
@@ -26,11 +27,12 @@ limitations under the License.
<item name="android:listChoiceIndicatorMultiple">@drawable/btn_check_holo_dark</item>
<item name="android:listChoiceIndicatorSingle">@drawable/btn_radio_holo_dark</item>
<item name="android:progressBarStyleHorizontal">@style/ProgressBarCustom</item>
<!-- Manually added -->
<item name="android:actionBarStyle">@style/ActionBarStyleCustom</item>
<item name="android:actionModeBackground">@drawable/custom_action_mode_background</item>
<item name="android:alertDialogTheme">@style/CustomAlertDialogTheme</item>
<!-- <item name="colorPrimary">TODO</item>-->
<!-- <item name="colorPrimaryDark">TODO</item>-->
<item name="android:colorAccent">@color/holo_orange_dark</item>
<item name="windowActionModeOverlay">true</item>
</style>
<style name="ThemeCustomTransparent" parent="ThemeCustom">
@@ -42,23 +44,4 @@ limitations under the License.
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="CustomAlertDialogTheme" parent="@android:style/Theme.Holo.Dialog">
<!-- From auto generated -->
<item name="android:activatedBackgroundIndicator">@drawable/activated_background_holo_dark
</item>
<item name="android:autoCompleteTextViewStyle">@style/AutoCompleteTextViewCustom</item>
<item name="android:dropDownSpinnerStyle">@style/SpinnerCustom</item>
<item name="android:editTextBackground">@drawable/edit_text_holo_dark</item>
<item name="android:listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
<item name="android:listChoiceIndicatorMultiple">@drawable/btn_check_holo_dark</item>
<item name="android:listChoiceIndicatorSingle">@drawable/btn_radio_holo_dark</item>
<item name="android:progressBarStyleHorizontal">@style/ProgressBarCustom</item>
<!-- From Theme.Holo.Dialog.Alert -->
<item name="android:textColor">@color/holo_orange_dark</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
</style>
</resources>