Settings: moved to Androidx Compat and use one screen only.

This commit is contained in:
Dennis Guse
2019-09-19 18:37:26 +02:00
parent c2841092da
commit c93e5ca1a6
26 changed files with 498 additions and 590 deletions
@@ -109,7 +109,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa
private ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
@Override
public void onPrepare(Menu menu, int[] positions, long[] ids, boolean showSelectAll) {
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
boolean isSingleSelection = positions.length == 1;
boolean isSingleSelectionTrack;
if (isSingleSelection) {
@@ -48,7 +48,6 @@ import de.dennisguse.opentracks.content.Waypoint.WaypointType;
import de.dennisguse.opentracks.content.WaypointCreationRequest;
import de.dennisguse.opentracks.fragments.ChartFragment;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
import de.dennisguse.opentracks.fragments.FrequencyDialogFragment;
import de.dennisguse.opentracks.fragments.StatsFragment;
@@ -66,7 +65,7 @@ import de.dennisguse.opentracks.util.TrackUtils;
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
public class TrackDetailActivity extends AbstractListActivity implements ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller {
public class TrackDetailActivity extends AbstractListActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, ConfirmDeleteDialogFragment.ConfirmDeleteCaller {
public static final String EXTRA_TRACK_ID = "track_id";
public static final String EXTRA_MARKER_ID = "marker_id";
@@ -33,7 +33,6 @@ import androidx.annotation.NonNull;
import de.dennisguse.opentracks.content.ContentProviderUtils;
import de.dennisguse.opentracks.content.Track;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.util.TrackIconUtils;
import de.dennisguse.opentracks.util.TrackUtils;
@@ -43,7 +42,7 @@ import de.dennisguse.opentracks.util.TrackUtils;
*
* @author Leif Hendrik Wilden
*/
public class TrackEditActivity extends AbstractActivity implements ChooseActivityTypeCaller {
public class TrackEditActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
public static final String EXTRA_TRACK_ID = "track_id";
public static final String EXTRA_NEW_TRACK = "new_track";
@@ -148,7 +148,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
PreferencesUtils.getKey(TrackListActivity.this, R.string.recording_track_id_key))) {
recordingTrackId = PreferencesUtils.getLong(
TrackListActivity.this, R.string.recording_track_id_key);
if (key != null && recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
if (key != null && PreferencesUtils.isRecording(recordingTrackId)) {
trackRecordingServiceConnection.startAndBind();
}
}
@@ -164,7 +164,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
public void run() {
TrackListActivity.this.invalidateOptionsMenu();
LoaderManager.getInstance(TrackListActivity.this).restartLoader(0, null, loaderCallbacks);
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
trackController.update(isRecording, recordingTrackPaused);
}
});
@@ -200,7 +200,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
runOnUiThread(new Runnable() {
@Override
public void run() {
trackController.update(recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT, recordingTrackPaused);
trackController.update(PreferencesUtils.isRecording(recordingTrackId), recordingTrackPaused);
}
});
@@ -339,8 +339,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
// Update UI
this.invalidateOptionsMenu();
LoaderManager.getInstance(this).restartLoader(0, null, loaderCallbacks);
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
trackController.onResume(isRecording, recordingTrackPaused);
trackController.onResume(PreferencesUtils.isRecording(recordingTrackId), recordingTrackPaused);
}
@Override
@@ -392,7 +391,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean isGpsStarted = TrackRecordingServiceConnection.isRecordingServiceRunning(this);
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
updateMenuItems(isGpsStarted, isRecording);
View searchView = searchMenuItem.getActionView();
@@ -208,7 +208,7 @@ public class TrackDataHub implements DataSourceListener {
* Returns true if the selected track is recording.
*/
public boolean isSelectedTrackRecording() {
return selectedTrackId == recordingTrackId && recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
return selectedTrackId == recordingTrackId && PreferencesUtils.isRecording(recordingTrackId);
}
/**
@@ -1,21 +1,6 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.fragments;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
@@ -23,7 +8,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import androidx.annotation.NonNull;
@@ -38,24 +22,15 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
/**
* A DialogFragment to choose an activity type.
*
* @author apoorvn
*/
public class ChooseActivityTypeDialogFragment extends DialogFragment {
public class ChooseActivityTypeDialogFragment extends DialogFragment implements AdapterView.OnItemClickListener {
private static final String CHOOSE_ACTIVITY_TYPE_DIALOG_TAG = "chooseActivityType";
private final String preselectedCategory;
private ChooseActivityTypeDialogFragment(String preselectedCategory) {
this.preselectedCategory = preselectedCategory;
}
public static void showDialog(FragmentManager fragmentManager, String preselectedCategory) {
new ChooseActivityTypeDialogFragment(preselectedCategory).show(fragmentManager, ChooseActivityTypeDialogFragment.CHOOSE_ACTIVITY_TYPE_DIALOG_TAG);
}
private ChooseActivityTypeCaller caller;
private static int getPosition(Context context, String category) {
if (category == null) {
return -1;
@@ -65,21 +40,18 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment {
return TrackIconUtils.getAllIconValues().indexOf(iconValue);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
caller = (ChooseActivityTypeCaller) context;
} catch (ClassCastException e) {
throw new ClassCastException(context + " must implement " + ChooseActivityTypeCaller.class.getSimpleName());
}
private String preselectedCategory;
private ChooseActivityTypeCaller chooseActivityTypeCaller;
private ChooseActivityTypeDialogFragment(String preselectedCategory) {
this.preselectedCategory = preselectedCategory;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setTitle(R.string.track_edit_activity_type_hint);
return dialog;
}
@@ -103,28 +75,44 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment {
imageAdapter.notifyDataSetChanged();
}
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
caller.onChooseActivityTypeDone(TrackIconUtils.getAllIconValues().get(position));
dismiss();
}
});
gridView.setOnItemClickListener(this);
return view;
}
/**
* Interface for caller of this dialog fragment.
*
* @author apoorvn
* TODO: Only used by obsolete Androidx preferences. Remove when onAttach(Context) is called.
*/
@Override
public void onAttach(@NonNull Activity activity) {
super.onAttach(activity);
try {
chooseActivityTypeCaller = (ChooseActivityTypeCaller) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity + " must implement " + ChooseActivityTypeCaller.class.getSimpleName());
}
}
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
chooseActivityTypeCaller = (ChooseActivityTypeCaller) context;
} catch (ClassCastException e) {
throw new ClassCastException(context + " must implement " + ChooseActivityTypeCaller.class.getSimpleName());
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
chooseActivityTypeCaller.onChooseActivityTypeDone(TrackIconUtils.getAllIconValues().get(position));
dismiss();
}
/**
* Interface for chooseActivityTypeCaller of this dialog fragment.
*/
public interface ChooseActivityTypeCaller {
/**
* Called when choose activity type is done.
*/
void onChooseActivityTypeDone(String iconValue);
}
}
@@ -99,7 +99,7 @@ public class ExportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
protected Boolean doInBackground(Void... params) {
try {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
boolean isRecording = PreferencesUtils.getLong(exportActivity, R.string.recording_track_id_key) != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean isRecording = PreferencesUtils.isRecording(exportActivity);
boolean isPaused = PreferencesUtils.getBoolean(exportActivity, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
// Get the wake lock if not recording or paused
if (!isRecording || isPaused) {
@@ -103,7 +103,7 @@ public class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
try {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
// Get the wake lock if not recording or paused
boolean isRecording = PreferencesUtils.getLong(importActivity, R.string.recording_track_id_key) != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
boolean isRecording = PreferencesUtils.isRecording(importActivity);
boolean isPaused = PreferencesUtils.getBoolean(importActivity, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
if (!isRecording || isPaused) {
wakeLock = SystemUtils.acquireWakeLock(importActivity, wakeLock);
@@ -119,10 +119,9 @@ public class TrackRecordingService extends Service {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_id_key))) {
long trackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
// Only through the TrackRecordingService can one stop a recording and set the recordingTrackId to -1L.
if (trackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
recordingTrackId = trackId;
if (PreferencesUtils.isRecording(context)) {
recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
}
}
if (key == null || key.equals(PreferencesUtils.getKey(context, R.string.recording_track_paused_key))) {
@@ -310,7 +309,7 @@ public class TrackRecordingService extends Service {
* Returns true if the service is recording.
*/
public boolean isRecording() {
return recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
return PreferencesUtils.isRecording(recordingTrackId);
}
/**
@@ -226,37 +226,14 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death
}
}
/**
* Stops the recording.
*
* @param context the context
* @param showEditor true to show the editor
*/
public void stopRecording(@NonNull Context context, boolean showEditor) {
ITrackRecordingService trackRecordingService = getServiceIfBound();
if (trackRecordingService == null) {
resetRecordingState(context);
} else {
try {
if (showEditor) {
// Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L.
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
trackRecordingService.endCurrentTrack();
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
Intent intent = IntentUtils.newIntent(context, TrackEditActivity.class)
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, recordingTrackId)
.putExtra(TrackEditActivity.EXTRA_NEW_TRACK, true);
context.startActivity(intent);
}
} else {
trackRecordingService.endCurrentTrack();
}
} catch (Exception e) {
//TODO What exception are we catching here? Should be removed...
Log.e(TAG, "Unable to stop recording.", e);
}
private static void resetRecordingState(Context context) {
if (PreferencesUtils.isRecording(context)) {
PreferencesUtils.setLong(context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
}
boolean recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
if (!recordingTrackPaused) {
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
}
unbindAndStop();
}
/**
@@ -284,14 +261,36 @@ public class TrackRecordingServiceConnection implements ServiceConnection, Death
return -1L;
}
private static void resetRecordingState(Context context) {
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
if (recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT) {
PreferencesUtils.setLong(context, R.string.recording_track_id_key, PreferencesUtils.RECORDING_TRACK_ID_DEFAULT);
}
boolean recordingTrackPaused = PreferencesUtils.getBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
if (!recordingTrackPaused) {
PreferencesUtils.setBoolean(context, R.string.recording_track_paused_key, PreferencesUtils.RECORDING_TRACK_PAUSED_DEFAULT);
/**
* Stops the recording.
*
* @param context the context
* @param showEditor true to show the editor
*/
public void stopRecording(@NonNull Context context, boolean showEditor) {
ITrackRecordingService trackRecordingService = getServiceIfBound();
if (trackRecordingService == null) {
resetRecordingState(context);
} else {
try {
if (showEditor) {
// Need to remember the recordingTrackId before calling endCurrentTrack() as endCurrentTrack() sets the value to -1L.
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
trackRecordingService.endCurrentTrack();
if (PreferencesUtils.isRecording(context)) {
Intent intent = IntentUtils.newIntent(context, TrackEditActivity.class)
.putExtra(TrackEditActivity.EXTRA_TRACK_ID, recordingTrackId)
.putExtra(TrackEditActivity.EXTRA_NEW_TRACK, true);
context.startActivity(intent);
}
} else {
trackRecordingService.endCurrentTrack();
}
} catch (Exception e) {
//TODO What exception are we catching here? Should be removed...
Log.e(TAG, "Unable to stop recording.", e);
}
}
unbindAndStop();
}
}
@@ -17,8 +17,7 @@
package de.dennisguse.opentracks.settings;
import android.content.Context;
import android.os.Parcelable;
import android.preference.DialogPreference;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -28,7 +27,12 @@ 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 de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.TrackIconUtils;
@@ -39,106 +43,122 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
*/
public class ActivityTypePreference extends DialogPreference {
private RecordingSettingsActivity recordingSettingsActivity;
private AutoCompleteTextView textView;
private Spinner spinner;
private SummaryProvider<DialogPreference> summaryProvider = new SummaryProvider<DialogPreference>() {
@Override
public CharSequence provideSummary(DialogPreference preference) {
String defaultActivity = PreferencesUtils.getString(ActivityTypePreference.this.getContext(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
return defaultActivity != null && !defaultActivity.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? defaultActivity : getContext().getString(R.string.value_unknown);
}
};
public ActivityTypePreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.activity_type_preference);
setDialogLayoutResource(R.layout.preference_activity_type);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
setPersistent(false);
setPersistent(true);
//TODO: for some reason the summary is not updated; after changing it. Enable summaryprovider, when fixed.
// setSummaryProvider(summaryProvider);
}
@Override
protected View onCreateDialogView() {
View view = super.onCreateDialogView();
textView = view.findViewById(R.id.activity_type_preference_text_view);
spinner = view.findViewById(R.id.activity_type_preference_spinner);
public int getDialogLayoutResource() {
return R.layout.preference_activity_type;
}
String category = PreferencesUtils.getString(
getContext(), R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
textView.setText(category);
public static class ActivityPreferenceDialog extends PreferenceDialogFragment {
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(), R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
textView.setAdapter(adapter);
textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
String iconValue = TrackIconUtils.getIconValue(getContext(), (String) textView.getAdapter().getItem(position));
TrackIconUtils.setIconSpinner(spinner, iconValue);
}
});
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String iconValue = TrackIconUtils.getIconValue(getContext(), textView.getText().toString());
private AutoCompleteTextView textView;
private Spinner spinner;
static ActivityPreferenceDialog newInstance(String preferenceKey) {
ActivityTypePreference.ActivityPreferenceDialog dialog = new ActivityTypePreference.ActivityPreferenceDialog();
final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey);
dialog.setArguments(bundle);
return dialog;
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
final Context context = getActivity();
textView = view.findViewById(R.id.activity_type_preference_text_view);
String category = PreferencesUtils.getString(context, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
textView.setText(category);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.activity_types, android.R.layout.simple_dropdown_item_1line);
textView.setAdapter(adapter);
textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
String iconValue = TrackIconUtils.getIconValue(context, (String) textView.getAdapter().getItem(position));
TrackIconUtils.setIconSpinner(spinner, iconValue);
}
}
});
String iconValue = TrackIconUtils.getIconValue(getContext(), category);
spinner.setAdapter(TrackIconUtils.getIconSpinnerAdapter(getContext(), iconValue));
spinner.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
recordingSettingsActivity.showChooseActivityTypeDialog();
});
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String iconValue = TrackIconUtils.getIconValue(context, textView.getText().toString());
TrackIconUtils.setIconSpinner(spinner, iconValue);
}
}
return true;
}
});
spinner.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
recordingSettingsActivity.showChooseActivityTypeDialog();
}
return true;
}
});
return view;
}
});
@Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String value = textView.getText().toString();
if (callChangeListener(value)) {
PreferencesUtils.setString(getContext(), R.string.default_activity_key, value);
String iconValue = TrackIconUtils.getIconValue(context, category);
spinner = view.findViewById(R.id.activity_type_preference_spinner);
spinner.setAdapter(TrackIconUtils.getIconSpinnerAdapter(context, iconValue));
spinner.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
showIconSelectDialog();
}
return true;
}
});
spinner.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
showIconSelectDialog();
}
return true;
}
});
}
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);
}
@Override
public void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String newDefaultActivity = textView.getText().toString();
if (getPreference().callChangeListener(newDefaultActivity)) {
PreferencesUtils.setString(getActivity(), R.string.default_activity_key, newDefaultActivity);
}
}
}
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
String iconValue = TrackIconUtils.getIconValue(getContext(), textView.getText().toString());
TrackIconUtils.setIconSpinner(spinner, iconValue);
textView.clearFocus();
}
/**
* Sets the recording settings activity.
*
* @param activity the activity
*/
void setRecordingSettingsActivity(RecordingSettingsActivity activity) {
recordingSettingsActivity = activity;
}
/**
* Updates the value of the dialog.
*
* @param iconValue the icon value
*/
void updateValue(String iconValue) {
TrackIconUtils.setIconSpinner(spinner, iconValue);
textView.setText(recordingSettingsActivity.getString(TrackIconUtils.getIconActivityType(iconValue)));
textView.clearFocus();
/**
* Updates the value of the dialog.
*
* @param iconValue the icon value
*/
public void updateUI(String iconValue) {
TrackIconUtils.setIconSpinner(spinner, iconValue);
textView.setText(getActivity().getString(TrackIconUtils.getIconActivityType(iconValue)));
textView.clearFocus();
}
}
}
@@ -2,7 +2,8 @@ package de.dennisguse.opentracks.settings;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.preference.ListPreference;
import androidx.preference.ListPreference;
import java.util.ArrayList;
import java.util.List;
@@ -183,7 +184,7 @@ final class PreferenceHelper {
/**
* Configures the bluetooth sensor.
*/
static void configBluetoothSensor(ListPreference preference) {
static void configureBluetoothSensorList(ListPreference preference) {
Context context = preference.getContext();
String value = PreferencesUtils.getString(context, R.string.bluetooth_sensor_key, PreferencesUtils.BLUETOOTH_SENSOR_DEFAULT);
@@ -1,136 +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.settings;
import android.app.Dialog;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
/**
* An activity for accessing recording settings.
*
* @author Jimmy Shih
*/
public class RecordingSettingsActivity extends PreferenceActivity implements ChooseActivityTypeCaller {
private static final int DIALOG_CHOOSE_ACTIVITY = 0;
private ActivityTypePreference activityTypePreference;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
addPreferencesFromResource(R.xml.settings_recording);
boolean metricUnits = PreferencesUtils.isMetricUnits(this);
configFrequencyPreference(R.string.voice_frequency_key, metricUnits);
configFrequencyPreference(R.string.split_frequency_key, metricUnits);
configDefaultActivity();
configListPreference(R.string.min_recording_interval_key, R.array.min_recording_interval_values, metricUnits);
configListPreference(R.string.recording_distance_interval_key, R.array.recording_distance_interval_values, metricUnits);
configListPreference(R.string.max_recording_distance_key, R.array.max_recording_distance_values, metricUnits);
configListPreference(R.string.recording_gps_accuracy_key, R.array.recording_gps_accuracy_values, metricUnits);
configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits);
}
private void configFrequencyPreference(int key, boolean metricUnits) {
ListPreference preference = (ListPreference) findPreference(getString(key));
String[] options = StringUtils.getFrequencyOptions(this, metricUnits);
preference.setEntries(options);
}
private void configDefaultActivity() {
activityTypePreference = (ActivityTypePreference) findPreference(getString(R.string.default_activity_key));
String defaultActivity = PreferencesUtils.getString(
this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
activityTypePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
String stringValue = (String) newValue;
pref.setSummary(stringValue != null && !stringValue.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? stringValue : getString(R.string.value_unknown));
return true;
}
});
activityTypePreference.setSummary(defaultActivity != null && !defaultActivity.equals(PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT) ? defaultActivity : getString(R.string.value_unknown));
activityTypePreference.setRecordingSettingsActivity(this);
}
private void configListPreference(int key, int valueArray, boolean metricUnits) {
ListPreference preference = (ListPreference) findPreference(getString(key));
@Deprecated //TODO Can we make values an int array?
String[] values = getResources().getStringArray(valueArray);
String[] options = new String[values.length];
switch (key) {
case R.string.min_recording_interval_key:
PreferenceHelper.setMinRecordingIntervalOptions(this, options, values);
break;
case R.string.recording_distance_interval_key:
PreferenceHelper.setRecordingDistanceIntervalOptions(this, options, values, metricUnits);
break;
case R.string.max_recording_distance_key:
PreferenceHelper.setMaxRecordingDistanceOptions(this, options, values, metricUnits);
break;
case R.string.recording_gps_accuracy_key:
PreferenceHelper.setRecordingGpsAccuracyOptions(this, options, values, metricUnits);
break;
case R.string.auto_resume_track_timeout_key:
PreferenceHelper.setAutoResumeTrackTimeoutOptions(this, options, values);
break;
default:
return;
}
preference.setEntries(options);
}
public void showChooseActivityTypeDialog() {
try {
removeDialog(DIALOG_CHOOSE_ACTIVITY);
} catch (Exception e) {
// Can safely ignore.
}
showDialog(DIALOG_CHOOSE_ACTIVITY);
}
@Override
protected Dialog onCreateDialog(int id, Bundle bundle) {
if (id != DIALOG_CHOOSE_ACTIVITY) {
return null;
}
String category = PreferencesUtils.getString(this, R.string.default_activity_key, PreferencesUtils.DEFAULT_ACTIVITY_DEFAULT);
//TODO ATTENTION: Need to switch to FragmentActivity before this can be used.
// ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), category);
return null;
}
@Override
public void onChooseActivityTypeDone(String iconValue) {
activityTypePreference.updateValue(iconValue);
}
}
@@ -1,11 +1,13 @@
package de.dennisguse.opentracks.settings;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.DialogPreference;
import android.os.Bundle;
import android.util.AttributeSet;
import android.widget.Toast;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragment;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.PreferencesUtils;
@@ -15,13 +17,24 @@ public class ResetDialogPreference extends DialogPreference {
super(context, attrs);
}
@Override
public void onClick(DialogInterface dialog, int which) {
super.onClick(dialog, which);
if (which == DialogInterface.BUTTON_POSITIVE) {
PreferencesUtils.resetPreferences(getContext(), true);
public static class ResetPreferenceDialog extends PreferenceDialogFragment {
Toast.makeText(getContext(), R.string.settings_reset_done, Toast.LENGTH_SHORT).show();
static PreferenceDialogFragment newInstance(String preferenceKey) {
ResetPreferenceDialog dialog = new ResetPreferenceDialog();
final Bundle bundle = new Bundle(1);
bundle.putString(PreferenceDialogFragment.ARG_KEY, preferenceKey);
dialog.setArguments(bundle);
return dialog;
}
@Override
public void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
PreferencesUtils.resetPreferences(getActivity(), true);
Toast.makeText(getActivity(), R.string.settings_reset_done, Toast.LENGTH_SHORT).show();
}
}
}
}
@@ -1,126 +1,156 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.settings;
import android.content.Intent;
import android.app.DialogFragment;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.IntentUtils;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.StringUtils;
/**
* An activity for accessing settings.
*
* @author Jimmy Shih
*/
public class SettingsActivity extends PreferenceActivity {
public class SettingsActivity extends FragmentActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller {
private long recordingTrackId = PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
/*
* Note that sharedPreferenceChangeListenr cannot be an anonymous inner class.
* Anonymous inner class will get garbage collected.
*/
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (key != null && key.equals(PreferencesUtils.getKey(SettingsActivity.this, R.string.recording_track_id_key))) {
recordingTrackId = PreferencesUtils.getLong(SettingsActivity.this, R.string.recording_track_id_key);
}
//TODO Should only be called if something meaningful happens.
runOnUiThread(new Runnable() {
@Override
public void run() {
updateUI();
}
});
}
};
private PrefsFragment prefsFragment = new PrefsFragment();
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
getFragmentManager().beginTransaction().replace(android.R.id.content, prefsFragment).commit();
}
configPreference(R.string.settings_stats_key, StatsSettingsActivity.class);
configPreference(R.string.settings_recording_key, NewSettingsActivity.class);
@Override
public void onChooseActivityTypeDone(String iconValue) {
prefsFragment.setDefaultActivity(iconValue);
}
findPreference(getString(R.string.settings_sensor_bluetooth_pairing_key))
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Intent settingsIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(settingsIntent);
return true;
public static class PrefsFragment extends PreferenceFragment {
/*
* Note that sharedPreferenceChangeListener cannot be an anonymous inner class.
* Anonymous inner class will get garbage collected.
*/
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateUI();
}
});
}
@Override
protected void onResume() {
super.onResume();
PreferencesUtils.getSharedPreferences(this).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
recordingTrackId = PreferencesUtils.getLong(this, R.string.recording_track_id_key);
updateUI();
ListPreference preference = (ListPreference) findPreference(getString(R.string.bluetooth_sensor_key));
PreferenceHelper.configBluetoothSensor(preference);
}
@Override
protected void onPause() {
super.onPause();
PreferencesUtils.getSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
}
/**
* Configures a preference by starting a new activity when it is clicked.
*
* @param key the preference key
* @param cl the class to start the new activity
*/
private void configPreference(int key, final Class<?> cl) {
Preference preference = findPreference(getString(key));
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference pref) {
Intent intent = IntentUtils.newIntent(SettingsActivity.this, cl);
startActivity(intent);
return true;
}
});
}
};
private void updateUI() {
//TODO Remove the following if recordingTrackId is replaced by direct communication rather than via preferences.
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
Preference resetPreference = findPreference(getString(R.string.settings_reset_key));
resetPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : "");
resetPreference.setEnabled(!isRecording);
// Used to forward update from ChooseActivityTypeDialogFragment; TODO Could be replaced with LiveData.
private ActivityTypePreference.ActivityPreferenceDialog activityPreferenceDialog;
Preference speedCheckBoxPreference = findPreference(getString(R.string.chart_show_speed_key));
speedCheckBoxPreference.setTitle(PreferencesUtils.isReportSpeed(this) ? R.string.stats_speed : R.string.stats_pace);
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.settings);
boolean metricUnits = PreferencesUtils.isMetricUnits(getActivity());
configFrequencyPreference(R.string.voice_frequency_key, metricUnits);
configFrequencyPreference(R.string.split_frequency_key, metricUnits);
configListPreference(R.string.min_recording_interval_key, R.array.min_recording_interval_values, metricUnits);
configListPreference(R.string.recording_distance_interval_key, R.array.recording_distance_interval_values, metricUnits);
configListPreference(R.string.max_recording_distance_key, R.array.max_recording_distance_values, metricUnits);
configListPreference(R.string.recording_gps_accuracy_key, R.array.recording_gps_accuracy_values, metricUnits);
configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits);
configListPreference(R.string.auto_resume_track_timeout_key, R.array.auto_resume_track_timeout_values, metricUnits);
ListPreference bluetoothPreference = findPreference(getString(R.string.bluetooth_sensor_key));
PreferenceHelper.configureBluetoothSensorList(bluetoothPreference);
}
@Override
public void onResume() {
super.onResume();
PreferencesUtils.getSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
updateUI();
}
@Override
public void onPause() {
super.onPause();
PreferencesUtils.getSharedPreferences(getActivity()).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
}
private void configFrequencyPreference(int key, boolean metricUnits) {
ListPreference preference = findPreference(getString(key));
String[] options = StringUtils.getFrequencyOptions(getActivity(), metricUnits);
preference.setEntries(options);
}
private void configListPreference(int key, int valueArray, boolean metricUnits) {
//TODO Can we make values an int array?
String[] values = getResources().getStringArray(valueArray);
final String[] options = new String[values.length];
switch (key) {
case R.string.min_recording_interval_key:
PreferenceHelper.setMinRecordingIntervalOptions(getActivity(), options, values);
break;
case R.string.recording_distance_interval_key:
PreferenceHelper.setRecordingDistanceIntervalOptions(getActivity(), options, values, metricUnits);
break;
case R.string.max_recording_distance_key:
PreferenceHelper.setMaxRecordingDistanceOptions(getActivity(), options, values, metricUnits);
break;
case R.string.recording_gps_accuracy_key:
PreferenceHelper.setRecordingGpsAccuracyOptions(getActivity(), options, values, metricUnits);
break;
case R.string.auto_resume_track_timeout_key:
PreferenceHelper.setAutoResumeTrackTimeoutOptions(getActivity(), options, values);
break;
default:
return;
}
final ListPreference listPreference = findPreference(getString(key));
listPreference.setEntries(options);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
DialogFragment dialogFragment = null;
if (preference instanceof ResetDialogPreference) {
dialogFragment = ResetDialogPreference.ResetPreferenceDialog.newInstance(preference.getKey());
} else if (preference instanceof ActivityTypePreference) {
activityPreferenceDialog = ActivityTypePreference.ActivityPreferenceDialog.newInstance(preference.getKey());
dialogFragment = activityPreferenceDialog;
}
if (dialogFragment != null) {
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getFragmentManager(), getClass().getSimpleName());
return;
}
super.onDisplayPreferenceDialog(preference);
}
public void setDefaultActivity(String iconValue) {
if (activityPreferenceDialog != null) {
activityPreferenceDialog.updateUI(iconValue);
}
}
private void updateUI() {
final boolean isRecording = PreferencesUtils.isRecording(getActivity());
Preference resetPreference = findPreference(getString(R.string.settings_reset_key));
resetPreference.setSummary(isRecording ? getString(R.string.settings_not_while_recording) : "");
resetPreference.setEnabled(!isRecording);
Preference speedCheckBoxPreference = findPreference(getString(R.string.chart_show_speed_key));
speedCheckBoxPreference.setTitle(PreferencesUtils.isReportSpeed(getActivity()) ? R.string.stats_speed : R.string.stats_pace);
}
}
}
@@ -1,78 +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.settings;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.util.PreferencesUtils;
/**
* An activity for accessing stats settings.
*
* @author Jimmy Shih
*/
public class StatsSettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
addPreferencesFromResource(R.xml.settings_statistics);
configUnitsListPreference();
boolean metricUnits = PreferencesUtils.STATS_UNITS_DEFAULT.equals(PreferencesUtils.getString(this, R.string.stats_units_key, ""));
configRateListPreference(metricUnits);
}
/**
* Configures the preferred units list preference.
*/
private void configUnitsListPreference() {
ListPreference listPreference = (ListPreference) findPreference(getString(R.string.stats_units_key));
final OnPreferenceChangeListener listener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
boolean metricUnits = PreferencesUtils.STATS_UNITS_DEFAULT.equals(newValue);
configRateListPreference(metricUnits);
return true;
}
};
listPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
return listener.onPreferenceChange(pref, newValue);
}
});
}
/**
* Configures the preferred rate list preference.
*
* @param metricUnits true if metric units
*/
private void configRateListPreference(boolean metricUnits) {
ListPreference listPreference = (ListPreference) findPreference(getString(R.string.stats_rate_key));
String[] options = getResources().getStringArray(metricUnits ? R.array.stats_rate_metric_options : R.array.stats_rate_imperial_options);
listPreference.setEntries(options);
}
}
@@ -19,7 +19,8 @@ package de.dennisguse.opentracks.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import androidx.preference.PreferenceManager;
import de.dennisguse.opentracks.R;
@@ -252,9 +253,16 @@ public class PreferencesUtils {
return CHART_X_AXIS_DEFAULT.equals(getString(context, R.string.chart_x_axis_key, CHART_X_AXIS_DEFAULT));
}
public static boolean isRecording(Context context) {
long recordingTrackId = PreferencesUtils.getLong(context, R.string.recording_track_id_key);
return recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
}
public static boolean isRecording(long recordingTrackId) {
return recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
}
public static void resetPreferences(Context context, boolean readAgain) {
PreferenceManager.setDefaultValues(context, R.xml.settings, readAgain);
PreferenceManager.setDefaultValues(context, R.xml.settings_recording, readAgain);
PreferenceManager.setDefaultValues(context, R.xml.settings_statistics, readAgain);
}
}
@@ -62,7 +62,7 @@ public class TrackIconUtils {
private static final LinkedHashMap<String, Pair<Integer, Integer>> MAP = new LinkedHashMap<>();
static {
//Reflects order in ChooseActivityTypeDialogFragment
//Reflects order in ChooseActivityTypeDialogFragmentActivity
MAP.put(UNKNOWN, new Pair<>(R.string.activity_type_unknown, ACTIVITY_UNKNOWN_LOGO));
MAP.put(RUN, new Pair<>(R.string.activity_type_running, R.drawable.ic_activity_run_24dp));
MAP.put(WALK, new Pair<>(R.string.activity_type_walking, R.drawable.ic_activity_walk_24dp));