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`) 4. Create changelog (`_version code_.txt`)
5. Create commit with all changes 5. Create commit with all changes
6. Push commits 6. Push commits
7. Tag newly create commit with _version name_ 7. Tag newly create commit with _version name_ (e.g., v3.2.1)
8. Push the tagged to public repository 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" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.dennisguse.opentracks" package="de.dennisguse.opentracks"
android:installLocation="auto" android:installLocation="auto"
android:versionCode="3063" android:versionCode="3079"
android:versionName="v3.2.1"> <!-- For FDroid. --> android:versionName="v3.2.2"> <!-- For FDroid. -->
<!-- Permission to initialize services --> <!-- Permission to initialize services -->
<application <application
android:name=".Startup" android:name=".Startup"
@@ -30,10 +30,6 @@ limitations under the License.
<!-- Activities --> <!-- Activities -->
<activity android:name=".AboutActivity" /> <activity android:name=".AboutActivity" />
<activity
android:name=".AggregatedStatsActivity"
android:label="@string/menu_aggregated_statistics" />
<activity android:name=".DeleteActivity" /> <activity android:name=".DeleteActivity" />
<activity <activity
@@ -19,12 +19,13 @@ package de.dennisguse.opentracks;
import android.os.Bundle; import android.os.Bundle;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import androidx.fragment.app.FragmentActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
/** /**
* @author Jimmy Shih * @author Jimmy Shih
*/ */
public abstract class AbstractActivity extends FragmentActivity { public abstract class AbstractActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -34,6 +35,9 @@ public abstract class AbstractActivity extends FragmentActivity {
setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM); setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
setContentView(getLayoutResId()); setContentView(getLayoutResId());
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
} }
/** /**
@@ -16,24 +16,7 @@
package de.dennisguse.opentracks; 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.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;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller; 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; protected static final int GPS_REQUEST_CODE = 6;
private static final int DELETE_REQUEST_CODE = 3; 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 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DELETE_REQUEST_CODE) { 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 * Gets the track recording service connection.
* recording if need to delete the current recording track. * For stopping the current recording if need to delete the current recording track.
*/ */
@NonNull
abstract protected TrackRecordingServiceConnection getTrackRecordingServiceConnection(); 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.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor; import android.database.Cursor;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView; 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.content.WaypointsColumns;
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment;
import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -175,7 +173,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
} }
}; };
listView.setAdapter(resourceCursorAdapter); listView.setAdapter(resourceCursorAdapter);
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback); ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
LoaderManager.getInstance(this).initLoader(0, null, new LoaderCallbacks<Cursor>() { LoaderManager.getInstance(this).initLoader(0, null, new LoaderCallbacks<Cursor>() {
@NonNull @NonNull
@@ -234,7 +232,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker); insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker);
searchMenuItem = menu.findItem(R.id.marker_list_search); searchMenuItem = menu.findItem(R.id.marker_list_search);
AbstractListActivity.configureSearchWidget(this, searchMenuItem, null); ActivityUtils.configureSearchWidget(this, searchMenuItem, null);
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
} }
@@ -256,24 +254,6 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
return super.onOptionsItemSelected(item); 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. * Handles a context item selection.
* *
@@ -22,14 +22,11 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; 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.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.stats.TripStatistics; import de.dennisguse.opentracks.stats.TripStatistics;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils; 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) { public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId); boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
boolean isSingleSelection = positions.length == 1; boolean isSingleSelection = positions.length == 1;
boolean isSingleSelectionTrack; boolean isSingleSelectionTrack;
if (isSingleSelection) { if (isSingleSelection) {
Map<String, Object> item = arrayAdapter.getItem(positions[0]); 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; isSingleSelectionTrack = item.get(MARKER_ID_FIELD) == null;
} else { } else {
isSingleSelectionTrack = false; isSingleSelectionTrack = false;
} }
// Not recording, one item, item is a track // Not recording, one item, item is a track
menu.findItem(R.id.list_context_menu_share).setVisible(!isRecording && isSingleSelection && isSingleSelectionTrack); MenuItem shareMenuItem = menu.findItem(R.id.list_context_menu_share);
//TODO Setup shareIntent. 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 // One item, item is a marker
menu.findItem(R.id.list_context_menu_show_on_map).setVisible(isSingleSelection && !isSingleSelectionTrack); menu.findItem(R.id.list_context_menu_show_on_map).setVisible(isSingleSelection && !isSingleSelectionTrack);
// One item, can be a track or a marker // One item, can be a track or a marker
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection); menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
// One item. If track, no restriction. // 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 // Disable select all, no action is available for multiple selection
menu.findItem(R.id.list_context_menu_select_all).setVisible(false); menu.findItem(R.id.list_context_menu_select_all).setVisible(false);
} }
@@ -222,7 +226,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
startActivity(intent); startActivity(intent);
} }
}); });
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback); ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
handleIntent(getIntent()); handleIntent(getIntent());
} }
@@ -259,24 +263,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
handleIntent(intent); 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 @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH) { if (keyCode == KeyEvent.KEYCODE_SEARCH) {
@@ -301,10 +287,6 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
Long markerId = (Long) item.get(MARKER_ID_FIELD); Long markerId = (Long) item.get(MARKER_ID_FIELD);
Intent intent; Intent intent;
switch (itemId) { 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: 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) + ""); IntentUtils.showCoordinateOnMap(this, (double) item.get(MARKER_LATITUDE_FIELD), (double) item.get(MARKER_LONGITUDE_FIELD), item.get(NAME_FIELD) + "");
return true; return true;
@@ -130,11 +130,11 @@ public class TrackController {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable); handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
} }
void hide() { public void hide() {
containerView.setVisibility(View.GONE); containerView.setVisibility(View.GONE);
} }
void show() { public void show() {
containerView.setVisibility(View.VISIBLE); containerView.setVisibility(View.VISIBLE);
} }
@@ -31,7 +31,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ShareActionProvider;
import android.widget.TabHost; import android.widget.TabHost;
import android.widget.TabHost.TabSpec; import android.widget.TabHost.TabSpec;
import android.widget.Toast; 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.FileUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils; import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils; 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); insertPhotoMenuItem.setVisible(new Intent(MediaStore.ACTION_IMAGE_CAPTURE).resolveActivity(getPackageManager()) != null);
shareMenuItem = menu.findItem(R.id.track_detail_share); shareMenuItem = menu.findItem(R.id.track_detail_share);
ShareActionProvider shareActionProvider = (ShareActionProvider) shareMenuItem.getActionProvider(); ToolbarUtils.setupShareActionProviderCompat(this, shareMenuItem, new long[]{trackId});
shareActionProvider.setShareIntent(IntentUtils.newShareFileIntent(this, new long[]{trackId}));
voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency); voiceFrequencyMenuItem = menu.findItem(R.id.track_detail_voice_frequency);
splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency); splitFrequencyMenuItem = menu.findItem(R.id.track_detail_split_frequency);
@@ -392,6 +391,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
} }
return; return;
} }
super.onRequestPermissionsResult(requestCode, permissions, grantResults); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
@@ -28,8 +28,6 @@ import android.location.LocationManager;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity; import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@@ -37,14 +35,12 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SearchView;
import android.widget.ShareActionProvider;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.cursoradapter.widget.ResourceCursorAdapter; import androidx.cursoradapter.widget.ResourceCursorAdapter;
import androidx.loader.app.LoaderManager; 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.ITrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.settings.SettingsActivity;
import de.dennisguse.opentracks.util.ActivityUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.ListItemUtils;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
import de.dennisguse.opentracks.util.ToolbarUtils;
import de.dennisguse.opentracks.util.TrackIconUtils; import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils; import de.dennisguse.opentracks.util.TrackUtils;
@@ -118,8 +116,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
boolean isSingleSelection = trackIds.length == 1; boolean isSingleSelection = trackIds.length == 1;
MenuItem shareMenuItem = menu.findItem(R.id.list_context_menu_share); MenuItem shareMenuItem = menu.findItem(R.id.list_context_menu_share);
ShareActionProvider shareActionProvider = (ShareActionProvider) shareMenuItem.getActionProvider(); ToolbarUtils.setupShareActionProvider(TrackListActivity.this, shareMenuItem, trackIds);
shareActionProvider.setShareIntent(trackIds.length == 0 ? null : IntentUtils.newShareFileIntent(TrackListActivity.this, trackIds));
menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection); menu.findItem(R.id.list_context_menu_edit).setVisible(isSingleSelection);
menu.findItem(R.id.list_context_menu_select_all).setVisible(showSelectAll); menu.findItem(R.id.list_context_menu_select_all).setVisible(showSelectAll);
@@ -175,7 +172,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
// Menu items // Menu items
private MenuItem searchMenuItem; private MenuItem searchMenuItem;
private MenuItem startGpsMenuItem; private MenuItem startGpsMenuItem;
private MenuItem aggregatedStatisticsMenuItem;
private MenuItem deleteAllMenuItem; private MenuItem deleteAllMenuItem;
private final OnClickListener stopListener = new OnClickListener() { private final OnClickListener stopListener = new OnClickListener() {
@@ -317,7 +313,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
} }
}; };
listView.setAdapter(resourceCursorAdapter); listView.setAdapter(resourceCursorAdapter);
AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback);
ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback);
LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks); LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks);
showStartupDialogs(); showStartupDialogs();
@@ -379,10 +376,9 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
getMenuInflater().inflate(R.menu.track_list, menu); getMenuInflater().inflate(R.menu.track_list, menu);
searchMenuItem = menu.findItem(R.id.track_list_search); 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); 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); deleteAllMenuItem = menu.findItem(R.id.track_list_delete_all);
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
@@ -394,10 +390,9 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId); boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
updateMenuItems(isGpsStarted, isRecording); updateMenuItems(isGpsStarted, isRecording);
View searchView = searchMenuItem.getActionView(); SearchView searchView = (SearchView) searchMenuItem.getActionView();
if (searchView instanceof SearchView) { searchView.setQuery("", false);
((SearchView) searchView).setQuery("", false);
}
return super.onPrepareOptionsMenu(menu); return super.onPrepareOptionsMenu(menu);
} }
@@ -438,10 +433,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
intent = IntentUtils.newIntent(this, MarkerListActivity.class); intent = IntentUtils.newIntent(this, MarkerListActivity.class);
startActivity(intent); startActivity(intent);
return true; 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: case R.id.track_list_delete_all:
deleteTracks(new long[]{-1L}); deleteTracks(new long[]{-1L});
return true; return true;
@@ -453,24 +444,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
return super.onOptionsItemSelected(item); 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 @Override
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH && searchMenuItem != null) { 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); startGpsMenuItem.setIcon(isGpsStarted ? R.drawable.ic_gps_fixed_24dp : R.drawable.ic_gps_off_24dp);
} }
} }
if (aggregatedStatisticsMenuItem != null) {
aggregatedStatisticsMenuItem.setVisible(hasTrack);
}
if (deleteAllMenuItem != null) { if (deleteAllMenuItem != null) {
deleteAllMenuItem.setVisible(hasTrack && !isRecording); deleteAllMenuItem.setVisible(hasTrack && !isRecording);
} }
@@ -2,7 +2,7 @@ package de.dennisguse.opentracks.content.sensor;
public final class SensorDataSet { 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. //TODO It might be necessary to consider: sensor if sensor was connected as well.
public String sensorName; public String sensorName;
@@ -40,7 +40,7 @@ public final class SensorDataSet {
} }
public boolean hasHeartRate() { public boolean hasHeartRate() {
return heartRate != DATA_UNAVAILABLE; return !Float.isNaN(heartRate);
} }
public float getHeartRate() { public float getHeartRate() {
@@ -48,7 +48,7 @@ public final class SensorDataSet {
} }
public boolean hasCadence() { public boolean hasCadence() {
return cadence != DATA_UNAVAILABLE; return !Float.isNaN(cadence);
} }
public float getCadence() { public float getCadence() {
@@ -56,7 +56,7 @@ public final class SensorDataSet {
} }
public boolean hasPower() { public boolean hasPower() {
return power != DATA_UNAVAILABLE; return !Float.isNaN(power);
} }
public float getPower() { public float getPower() {
@@ -77,7 +77,7 @@ public final class SensorDataSet {
} }
public boolean hasBatteryLevel() { public boolean hasBatteryLevel() {
return batteryLevel != DATA_UNAVAILABLE; return !Float.isNaN(batteryLevel);
} }
public float getBatteryLevel() { public float getBatteryLevel() {
@@ -49,9 +49,10 @@ public class KmlTrackWriter implements TrackWriter {
private static final String END_STYLE = "end"; private static final String END_STYLE = "end";
private static final String TRACK_STYLE = "track"; private static final String TRACK_STYLE = "track";
private static final String SCHEMA_ID = "schema"; 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 SENSOR_TYPE_CADENCE = "cadence";
private static final String POWER = "power"; 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 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"; 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> powerList = new ArrayList<>();
private List<Float> cadenceList = new ArrayList<>(); private List<Float> cadenceList = new ArrayList<>();
private List<Float> heartRateList = new ArrayList<>(); private List<Float> heartRateList = new ArrayList<>();
private boolean hasPower;
private boolean hasCadence;
private boolean hasHeartRate;
private Location startLocation; private Location startLocation;
@@ -132,9 +130,9 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<Schema id=\"" + SCHEMA_ID + "\">"); printWriter.println("<Schema id=\"" + SCHEMA_ID + "\">");
if (exportSensorData) { if (exportSensorData) {
writeSensorStyle(POWER, context.getString(R.string.description_sensor_power)); writeSensorStyle(SENSOR_TYPE_POWER, context.getString(R.string.description_sensor_power));
writeSensorStyle(CADENCE, context.getString(R.string.description_sensor_cadence)); writeSensorStyle(SENSOR_TYPE_CADENCE, context.getString(R.string.description_sensor_cadence));
writeSensorStyle(HEART_RATE, context.getString(R.string.description_sensor_heart_rate)); writeSensorStyle(SENSOR_TYPE_HEART_RATE, context.getString(R.string.description_sensor_heart_rate));
} }
printWriter.println("</Schema>"); printWriter.println("</Schema>");
} }
@@ -235,9 +233,6 @@ public class KmlTrackWriter implements TrackWriter {
public void writeOpenSegment() { public void writeOpenSegment() {
if (printWriter != null) { if (printWriter != null) {
printWriter.println("<gx:Track>"); printWriter.println("<gx:Track>");
hasPower = false;
hasCadence = false;
hasHeartRate = false;
powerList.clear(); powerList.clear();
cadenceList.clear(); cadenceList.clear();
heartRateList.clear(); heartRateList.clear();
@@ -250,14 +245,14 @@ public class KmlTrackWriter implements TrackWriter {
printWriter.println("<ExtendedData>"); printWriter.println("<ExtendedData>");
printWriter.println("<SchemaData schemaUrl=\"#" + SCHEMA_ID + "\">"); printWriter.println("<SchemaData schemaUrl=\"#" + SCHEMA_ID + "\">");
if (exportSensorData) { if (exportSensorData) {
if (hasPower) { if (powerList.size() > 0) {
writeSensorData(powerList, POWER); writeSensorData(powerList, SENSOR_TYPE_POWER);
} }
if (hasCadence) { if (cadenceList.size() > 0) {
writeSensorData(cadenceList, CADENCE); writeSensorData(cadenceList, SENSOR_TYPE_CADENCE);
} }
if (hasHeartRate) { if (heartRateList.size() > 0) {
writeSensorData(heartRateList, HEART_RATE); writeSensorData(heartRateList, SENSOR_TYPE_HEART_RATE);
} }
} }
printWriter.println("</SchemaData>"); printWriter.println("</SchemaData>");
@@ -466,11 +461,11 @@ public class KmlTrackWriter implements TrackWriter {
* Writes a sensor style. * Writes a sensor style.
* *
* @param name the name of the sesnor * @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) { private void writeSensorStyle(String name, String sensorType) {
printWriter.println("<gx:SimpleArrayField name=\"" + name + "\" type=\"int\">"); printWriter.println("<gx:SimpleArrayField name=\"" + name + "\" type=\"float\">");
printWriter.println("<displayName>" + StringUtils.formatCData(displayName) + "</displayName>"); printWriter.println("<displayName>" + StringUtils.formatCData(sensorType) + "</displayName>");
printWriter.println("</gx:SimpleArrayField>"); printWriter.println("</gx:SimpleArrayField>");
} }
} }
@@ -384,8 +384,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
* @param message the message * @param message the message
*/ */
protected String createErrorMessage(String message) { protected String createErrorMessage(String message) {
return String.format(Locale.US, "Parsing error at line: %d column: %d. %s", return String.format(Locale.US, "Parsing error at line: %d column: %d. %s", locator.getLineNumber(), locator.getColumnNumber(), message);
locator.getLineNumber(), locator.getColumnNumber(), message);
} }
/** /**
@@ -19,6 +19,7 @@ package de.dennisguse.opentracks.io.file.importer;
import android.content.Context; import android.content.Context;
import android.location.Location; import android.location.Location;
import android.net.Uri; import android.net.Uri;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -39,6 +40,8 @@ import de.dennisguse.opentracks.content.sensor.SensorDataSet;
*/ */
public class KmlFileTrackImporter extends AbstractFileTrackImporter { public class KmlFileTrackImporter extends AbstractFileTrackImporter {
private static final String TAG = KmlFileTrackImporter.class.getSimpleName();
private static final String CADENCE = "cadence"; private static final String CADENCE = "cadence";
private static final String HEART_RATE = "heart_rate"; private static final String HEART_RATE = "heart_rate";
private static final String POWER = "power"; private static final String POWER = "power";
@@ -65,11 +68,11 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
private static final String ATTRIBUTE_NAME = "name"; private static final String ATTRIBUTE_NAME = "name";
private boolean trackStarted = false; private boolean trackStarted = false;
private String sensorName; private String sensorType;
private ArrayList<Location> locationList; private ArrayList<Location> locationList;
private ArrayList<Integer> cadenceList; private ArrayList<Float> cadenceList;
private ArrayList<Integer> heartRateList; private ArrayList<Float> heartRateList;
private ArrayList<Integer> powerList; private ArrayList<Float> powerList;
/** /**
* Constructor. * Constructor.
@@ -229,20 +232,30 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
*/ */
private void onTrackSegmentEnd() { private void onTrackSegmentEnd() {
// Close a track segment by inserting the segment locations // 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++) { for (int i = 0; i < locationList.size(); i++) {
Location location = locationList.get(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); insertTrackPoint(location);
} else { } 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())); SensorDataSetLocation sensorDataSetLocation = new SensorDataSetLocation(location, new SensorDataSet(heartrate, cadence, power, SensorDataSet.DATA_UNAVAILABLE, location.getTime()));
insertTrackPoint(sensorDataSetLocation); insertTrackPoint(sensorDataSetLocation);
} }
@@ -277,7 +290,7 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
* On sensor data start. gx:SimpleArrayData start tag. * On sensor data start. gx:SimpleArrayData start tag.
*/ */
private void onSensorDataStart(Attributes attributes) { 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("")) { if (content.equals("")) {
return; return;
} }
int value; float value;
try { try {
value = Integer.parseInt(content); value = Float.valueOf(content);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new SAXException(createErrorMessage("Unable to parse gx:value:" + content), e); throw new SAXException(createErrorMessage("Unable to parse gx:value:" + content), e);
} }
if (POWER.equals(sensorName)) { switch (sensorType) {
case POWER:
powerList.add(value); powerList.add(value);
} else if (HEART_RATE.equals(sensorName)) { break;
case HEART_RATE:
heartRateList.add(value); heartRateList.add(value);
} else if (CADENCE.equals(sensorName)) { break;
case CADENCE:
cadenceList.add(value); 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) { private void insertLocation(Track track, Location location, Location lastValidTrackPoint) {
if (location == null) { if (location == null) {
Log.w(TAG, "Ignore insertLocation. loation is null."); Log.w(TAG, "Ignore insertLocation. location is null.");
return; return;
} }
// Do not insert if inserted already // Do not insert if inserted already
@@ -27,9 +27,8 @@ import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.Spinner; import android.widget.Spinner;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.DialogPreference; import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragment; import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
@@ -67,7 +66,7 @@ public class ActivityTypePreference extends DialogPreference {
return R.layout.preference_activity_type; return R.layout.preference_activity_type;
} }
public static class ActivityPreferenceDialog extends PreferenceDialogFragment { public static class ActivityPreferenceDialog extends PreferenceDialogFragmentCompat {
private AutoCompleteTextView textView; private AutoCompleteTextView textView;
private Spinner spinner; private Spinner spinner;
@@ -75,7 +74,7 @@ public class ActivityTypePreference extends DialogPreference {
static ActivityPreferenceDialog newInstance(String preferenceKey) { static ActivityPreferenceDialog newInstance(String preferenceKey) {
ActivityTypePreference.ActivityPreferenceDialog dialog = new ActivityTypePreference.ActivityPreferenceDialog(); ActivityTypePreference.ActivityPreferenceDialog dialog = new ActivityTypePreference.ActivityPreferenceDialog();
final Bundle bundle = new Bundle(1); final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey); bundle.putString(PreferenceDialogFragmentCompat.ARG_KEY, preferenceKey);
dialog.setArguments(bundle); dialog.setArguments(bundle);
return dialog; return dialog;
@@ -134,10 +133,7 @@ public class ActivityTypePreference extends DialogPreference {
private void showIconSelectDialog() { private void showIconSelectDialog() {
String category = PreferencesUtils.getString(getActivity(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT); String category = PreferencesUtils.getString(getActivity(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
ChooseActivityTypeDialogFragment.showDialog(getActivity().getSupportFragmentManager(), category);
// TODO Remove casting when upgrading to new Androidx compat.
FragmentActivity fragmentActivity = (androidx.fragment.app.FragmentActivity) getActivity();
ChooseActivityTypeDialogFragment.showDialog(fragmentActivity.getSupportFragmentManager(), category);
} }
@Override @Override
@@ -6,7 +6,7 @@ import android.util.AttributeSet;
import android.widget.Toast; import android.widget.Toast;
import androidx.preference.DialogPreference; import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragment; import androidx.preference.PreferenceDialogFragmentCompat;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -17,12 +17,12 @@ public class ResetDialogPreference extends DialogPreference {
super(context, attrs); 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(); ResetPreferenceDialog dialog = new ResetPreferenceDialog();
final Bundle bundle = new Bundle(1); final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey); bundle.putString(PreferenceDialogFragmentCompat.ARG_KEY, preferenceKey);
dialog.setArguments(bundle); dialog.setArguments(bundle);
return dialog; return dialog;
@@ -1,20 +1,21 @@
package de.dennisguse.opentracks.settings; package de.dennisguse.opentracks.settings;
import android.app.DialogFragment;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; 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.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragment; import androidx.preference.PreferenceFragmentCompat;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils; 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(); private PrefsFragment prefsFragment = new PrefsFragment();
@@ -22,7 +23,13 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(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 @Override
@@ -30,7 +37,7 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
prefsFragment.setDefaultActivity(iconValue); prefsFragment.setDefaultActivity(iconValue);
} }
public static class PrefsFragment extends PreferenceFragment { public static class PrefsFragment extends PreferenceFragmentCompat {
/* /*
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class. * Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
@@ -62,7 +69,7 @@ public class SettingsActivity extends FragmentActivity implements ChooseActivity
@Override @Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.settings); setPreferencesFromResource(R.xml.settings, rootKey);
updateUnits(); 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" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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" /> <include layout="@layout/track_controller" />
+2
View File
@@ -4,6 +4,8 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" />
<ImageView <ImageView
android:id="@+id/imageView" android:id="@+id/imageView"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -17,6 +17,8 @@ limitations under the License.
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<include layout="@layout/toolbar" />
<androidx.viewpager.widget.ViewPager <androidx.viewpager.widget.ViewPager
android:id="@+id/maker_detail_activity_view_pager" android:id="@+id/maker_detail_activity_view_pager"
android:layout_width="match_parent" android:layout_width="match_parent"
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" />
<ScrollView style="@style/ScrollView.WithBottomButtons"> <ScrollView style="@style/ScrollView.WithBottomButtons">
<LinearLayout <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 See the License for the specific language governing permissions and
limitations under the License. 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_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView <ListView
android:id="@+id/marker_list" android:id="@+id/marker_list"
@@ -26,4 +29,4 @@ limitations under the License.
android:id="@+id/marker_list_empty" android:id="@+id/marker_list_empty"
style="@style/ListEmptyTextView" style="@style/ListEmptyTextView"
android:text="@string/marker_list_empty_message" /> 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 See the License for the specific language governing permissions and
limitations under the License. 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_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView <ListView
android:id="@+id/search_list" android:id="@+id/search_list"
@@ -26,4 +29,4 @@ limitations under the License.
android:id="@+id/search_list_empty" android:id="@+id/search_list_empty"
style="@style/ListEmptyTextView" style="@style/ListEmptyTextView"
android:text="@string/search_list_empty_message" /> 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:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" />
<TabHost <TabHost
android:id="@+id/tackdetail_tabhost" android:id="@+id/tackdetail_tabhost"
android:layout_width="match_parent" android:layout_width="match_parent"
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" />
<ScrollView style="@style/ScrollView.WithBottomButtons"> <ScrollView style="@style/ScrollView.WithBottomButtons">
<LinearLayout <LinearLayout
+2
View File
@@ -18,6 +18,8 @@ limitations under the License.
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" />
<ListView <ListView
android:id="@+id/track_list" android:id="@+id/track_list"
android:layout_width="match_parent" 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 See the License for the specific language governing permissions and
limitations under the License. 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 <item
android:id="@+id/list_context_menu_share" android:id="@+id/list_context_menu_share"
android:actionProviderClass="android.widget.ShareActionProvider" android:title="@string/menu_share"
android:showAsAction="ifRoom" app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider"
android:title="@string/menu_share" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/list_context_menu_show_on_map" android:id="@+id/list_context_menu_show_on_map"
android:icon="@drawable/ic_map_24dp" 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 <item
android:id="@+id/list_context_menu_edit" android:id="@+id/list_context_menu_edit"
android:icon="@drawable/ic_edit_24dp" android:icon="@drawable/ic_edit_24dp"
android:showAsAction="ifRoom" android:title="@string/menu_edit"
android:title="@string/menu_edit" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/list_context_menu_delete" android:id="@+id/list_context_menu_delete"
android:icon="@drawable/ic_delete_forever_24dp" android:icon="@drawable/ic_delete_forever_24dp"
android:showAsAction="ifRoom" android:title="@string/menu_delete"
android:title="@string/menu_delete" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/list_context_menu_select_all" android:id="@+id/list_context_menu_select_all"
android:icon="@drawable/ic_select_all_24dp" 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> </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 See the License for the specific language governing permissions and
limitations under the License. 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 <item
android:id="@+id/marker_detail_show_on_map" android:id="@+id/marker_detail_show_on_map"
android:icon="@drawable/ic_map_24dp" 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 <item
android:id="@+id/marker_detail_edit" android:id="@+id/marker_detail_edit"
android:icon="@drawable/ic_edit_24dp" android:icon="@drawable/ic_edit_24dp"
android:showAsAction="ifRoom" android:title="@string/menu_edit"
android:title="@string/menu_edit" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/marker_detail_delete" android:id="@+id/marker_detail_delete"
android:icon="@drawable/ic_delete_forever_24dp" android:icon="@drawable/ic_delete_forever_24dp"
android:showAsAction="ifRoom" android:title="@string/menu_delete"
android:title="@string/menu_delete" /> app:showAsAction="ifRoom" />
</menu> </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 See the License for the specific language governing permissions and
limitations under the License. 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 <item
android:id="@+id/marker_list_insert_marker" android:id="@+id/marker_list_insert_marker"
android:icon="@drawable/ic_marker_show_24dp" 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 <item
android:id="@+id/marker_list_search" android:id="@+id/marker_list_search"
android:actionViewClass="android.widget.SearchView" android:title="@string/menu_search"
android:showAsAction="ifRoom" app:actionViewClass="androidx.appcompat.widget.SearchView"
android:title="@string/menu_search" /> app:showAsAction="ifRoom" />
</menu> </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 See the License for the specific language governing permissions and
limitations under the License. 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 <item
android:id="@+id/track_detail_insert_marker" android:id="@+id/track_detail_insert_marker"
android:icon="@drawable/ic_marker_add_24dp" android:icon="@drawable/ic_marker_add_24dp"
android:orderInCategory="1" android:orderInCategory="1"
android:showAsAction="ifRoom" app:showAsAction="ifRoom"
android:title="@string/menu_insert_marker" /> android:title="@string/menu_insert_marker" />
<item <item
android:id="@+id/track_detail_insert_photo" android:id="@+id/track_detail_insert_photo"
android:icon="@drawable/ic_camera_24dp" android:icon="@drawable/ic_camera_24dp"
android:orderInCategory="2" android:orderInCategory="2"
android:showAsAction="ifRoom" app:showAsAction="ifRoom"
android:title="@string/menu_insert_photo" /> android:title="@string/menu_insert_photo" />
<item <item
android:id="@+id/track_detail_menu_show_on_map" android:id="@+id/track_detail_menu_show_on_map"
android:icon="@drawable/ic_map_24dp" android:icon="@drawable/ic_map_24dp"
android:showAsAction="ifRoom" app:showAsAction="ifRoom"
android:title="@string/menu_show_on_map" /> android:title="@string/menu_show_on_map" />
<item <item
android:id="@+id/track_detail_share" android:id="@+id/track_detail_share"
android:actionProviderClass="android.widget.ShareActionProvider" app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider"
android:orderInCategory="4" android:orderInCategory="4"
android:showAsAction="ifRoom" app:showAsAction="ifRoom"
android:title="@string/menu_share" /> android:title="@string/menu_share" />
<item <item
android:id="@+id/track_detail_markers" 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 See the License for the specific language governing permissions and
limitations under the License. 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 <item
android:id="@+id/track_list_search" android:id="@+id/track_list_search"
android:actionViewClass="android.widget.SearchView" android:title="@string/menu_search"
android:showAsAction="ifRoom" app:actionViewClass="androidx.appcompat.widget.SearchView"
android:title="@string/menu_search" /> app:showAsAction="ifRoom" />
<!-- Icon and title is overwritten by TrackListActivity --> <!-- Icon and title is overwritten by TrackListActivity -->
<item <item
android:id="@+id/track_list_start_gps" android:id="@+id/track_list_start_gps"
android:icon="@drawable/ic_gps_off_24dp" 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 <item
android:id="@+id/track_list_markers" android:id="@+id/track_list_markers"
android:icon="@drawable/ic_marker_show_24dp" android:icon="@drawable/ic_marker_show_24dp"
android:showAsAction="ifRoom" android:title="@string/menu_markers"
android:title="@string/menu_markers" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/track_list_aggregated_statistics"
android:icon="@drawable/ic_statistics_24dp"
android:title="@string/menu_aggregated_statistics" />
<item <item
android:id="@+id/track_list_delete_all" android:id="@+id/track_list_delete_all"
android:icon="@drawable/ic_delete_forever_24dp" 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"> <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"> <style name="BottomButton" parent="@android:style/Widget.Holo.Button.Borderless">
<!-- Same as BottomButton in values/styles.xml except inheriting from Widget.Holo.Button.Borderles. --> <!-- Same as BottomButton in values/styles.xml except inheriting from Widget.Holo.Button.Borderles. -->
<item name="android:layout_height">wrap_content</item> <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"> <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 --> <!-- Auto generated -->
<item name="android:activatedBackgroundIndicator">@drawable/activated_background_holo_dark <item name="android:activatedBackgroundIndicator">@drawable/activated_background_holo_dark
</item> </item>
@@ -26,11 +27,12 @@ limitations under the License.
<item name="android:listChoiceIndicatorMultiple">@drawable/btn_check_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:listChoiceIndicatorSingle">@drawable/btn_radio_holo_dark</item>
<item name="android:progressBarStyleHorizontal">@style/ProgressBarCustom</item> <item name="android:progressBarStyleHorizontal">@style/ProgressBarCustom</item>
<!-- Manually added -->
<item name="android:actionBarStyle">@style/ActionBarStyleCustom</item> <!-- <item name="colorPrimary">TODO</item>-->
<item name="android:actionModeBackground">@drawable/custom_action_mode_background</item> <!-- <item name="colorPrimaryDark">TODO</item>-->
<item name="android:alertDialogTheme">@style/CustomAlertDialogTheme</item>
<item name="android:colorAccent">@color/holo_orange_dark</item> <item name="android:colorAccent">@color/holo_orange_dark</item>
<item name="windowActionModeOverlay">true</item>
</style> </style>
<style name="ThemeCustomTransparent" parent="ThemeCustom"> <style name="ThemeCustomTransparent" parent="ThemeCustom">
@@ -42,23 +44,4 @@ limitations under the License.
<item name="android:windowIsFloating">true</item> <item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item> <item name="android:backgroundDimEnabled">false</item>
</style> </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> </resources>