diff --git a/app/build.gradle b/app/build.gradle index 3caf91def..cd692d859 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -95,6 +95,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.preference:preference:1.2.0' // Required -- JUnit 4 framework testImplementation 'junit:junit:4.13.2' @@ -111,6 +112,7 @@ dependencies { // Required for instrumented tests androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.7.0' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test:rules:1.6.1' } diff --git a/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java new file mode 100644 index 000000000..796ace41d --- /dev/null +++ b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java @@ -0,0 +1,185 @@ +package net.osmtracker.activity; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.clearText; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.stringContainsInOrder; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import net.osmtracker.OSMTracker; +import net.osmtracker.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.Arrays; + + +@RunWith(AndroidJUnit4.class) +public class PreferencesTest { + + private Context context; + private ActivityScenario activity; + + @Before + public void setup() { + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + // Reset preferences to default before each test to ensure a clean state + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().clear().commit(); + + // Launch the activity + activity = ActivityScenario.launch(Preferences.class); + } + + @After + public void tearDown() { + activity.close(); + } + + /** + * Test that the Storage Directory preference logic works to rejects empty input. + */ + @Test + public void testStorageDirectoryValidatesNonEmpty() { + String keyTitle = context.getString(R.string.prefs_storage_dir); + String defaultValue = OSMTracker.Preferences.VAL_STORAGE_DIR; + + // Looks for storage directory preference + scrollToAndClick(keyTitle); + + // Try to save an empty value + onView(withId(android.R.id.edit)).perform(clearText()); + onView(withText(android.R.string.ok)).perform(click()); + + // Open the preference to verify the value in the list remains the default (unchanged) + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(defaultValue)))); + } + + /** + * Test that the Storage Directory preference logic works to automatically append a leading + * slash separator if missing. + */ + @Test + public void testStorageDirectoryValidatesAppendLeadingSlash() { + String keyTitle = context.getString(R.string.prefs_storage_dir); + String expected = File.separator + "my_folder"; + + + // Looks for storage directory preference + scrollToAndClick(keyTitle); + + // Try to type a value without a slash + onView(withId(android.R.id.edit)).perform(clearText()); + onView(withId(android.R.id.edit)) + .perform(typeText("my_folder")); + onView(withText(android.R.string.ok)).perform(click()); + + // Open the preference to verify the value in the list is the expected + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(expected)))); + } + + /** + * Test Numeric Input logic (GPS Logging Interval): update summary with suffix. + */ + @Test + public void testNumericInputLogic() { + String title = context.getString(R.string.prefs_gps_logging_interval); + String suffix = context.getString(R.string.prefs_gps_logging_interval_seconds); + + scrollToAndClick(title); + + // Enter a valid number + onView(withId(android.R.id.edit)) + .perform(clearText(), typeText("30")); + onView(withText(android.R.string.ok)).perform(click()); + + // Verify summary format: "30 seconds. " + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(stringContainsInOrder(Arrays.asList("30", + suffix)))))); + } + + /** + * Test ListPreference custom summary logic (Screen Orientation) + * Should show "Selected Value. \n ..." (don't check for the 2nd line of the summary) + */ + @Test + public void testListPreferenceCustomSummary() { + String title = context.getString(R.string.prefs_ui_orientation); + + scrollToAndClick(title); + + // Select 1st option from array resource entries + String[] entries = context.getResources() + .getStringArray(R.array.prefs_ui_orientation_options_keys); + onView(withText(entries[0])).perform(click()); + + // Verify the two-line summary exists + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)).check(matches(hasDescendant( + withText(stringContainsInOrder(Arrays.asList(entries[0], ".\n")))))); + } + + /** + * Test Clear OAuth Data logic. + */ + @Test + public void testClearOAuthData() { + String title = context.getString(R.string.prefs_osm_clear_oauth_data); + + // Inject a fake token to enable the button + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context) + .edit(); + editor.putString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, "fake_token"); + editor.commit(); + + // Relaunch to refresh UI state + ActivityScenario.launch(Preferences.class); + + + scrollToAndClick(title); + + // Click OK on Confirmation Dialog + onView(withText(R.string.prefs_osm_clear_oauth_data_dialog)).check(matches(isDisplayed())); + onView(withText(android.R.string.ok)).perform(click()); + + // Verify token is gone in prefs + assert(!PreferenceManager.getDefaultSharedPreferences(context) + .contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)); + } + + // --- Helper Methods --- + + /** + * Helper to scroll to a preference in the RecyclerView and click it. + */ + private void scrollToAndClick(String text) { + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .perform(RecyclerViewActions.actionOnItem( + hasDescendant(withText(text)), + click())); + } + +} diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java index 339caaccb..c1bc2cdbb 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java @@ -22,7 +22,7 @@ import net.osmtracker.R; import net.osmtracker.activity.ButtonsPresets; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.CustomLayoutsUtils; import org.junit.After; @@ -98,6 +98,6 @@ public void layoutDeletionTest() { assertFalse(filesAfterDeletion.contains(layoutFileName)); // Check the icons folder was deleted - assertFalse(filesAfterDeletion.contains(layoutName + Preferences.ICONS_DIR_SUFFIX)); + assertFalse(filesAfterDeletion.contains(layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX)); } } diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java index 7882dbea6..5d7c99d24 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java @@ -1,12 +1,9 @@ package net.osmtracker.layouts; -import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.PreferenceMatchers.withTitleText; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; import static androidx.test.espresso.matcher.ViewMatchers.withId; @@ -17,11 +14,13 @@ import android.Manifest; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import androidx.lifecycle.Lifecycle; +import androidx.preference.PreferenceManager; import androidx.test.core.app.ActivityScenario; import androidx.test.espresso.Espresso; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.rule.GrantPermissionRule; import net.osmtracker.OSMTracker; @@ -101,7 +100,11 @@ public void navigateToAvailableLayouts() { // Click on "Settings" in this menu onView(withText(TestUtils.getStringResource(R.string.menu_settings))).perform(click()); // Click on "Buttons presets" settings - onData(withTitleText(TestUtils.getStringResource(R.string.prefs_ui_buttons_layout))).perform(scrollTo(), click()); + onView(ViewMatchers.withId(androidx.preference.R.id.recycler_view)) + .perform(RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(withText(R.string.prefs_ui_buttons_layout)), + click() + )); // Wait for "+" to be visible onView(isRoot()).perform(waitForView(R.id.launch_available, WAIT_VIEW_TIMEOUT)); // Perform a click action on the "+" button diff --git a/app/src/androidTest/java/net/osmtracker/util/TestUtils.java b/app/src/androidTest/java/net/osmtracker/util/TestUtils.java index 2c733c75f..18d94d3a2 100644 --- a/app/src/androidTest/java/net/osmtracker/util/TestUtils.java +++ b/app/src/androidTest/java/net/osmtracker/util/TestUtils.java @@ -4,13 +4,13 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import androidx.test.platform.app.InstrumentationRegistry; import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; import net.osmtracker.data.Mocks; +import net.osmtracker.db.DataHelper; import java.io.File; import java.io.FileWriter; @@ -66,7 +66,7 @@ public static void injectMockLayout(String layoutName, String ISOLangCode) { writeToFile(newLayout, Mocks.MOCK_LAYOUT_CONTENT); // Create the icons directory - File iconsDir = createDirectory(layoutsDir, layoutName + Preferences.ICONS_DIR_SUFFIX); + File iconsDir = createDirectory(layoutsDir, layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX); // And put some mock files inside int pngsToCreate = 4; @@ -109,7 +109,7 @@ public static File getAppDirectory(){ */ public static File getLayoutsDirectory(){ String appDirectory = getAppDirectory().getAbsolutePath(); - File layoutsDirectory = new File(appDirectory + File.separator + Preferences.LAYOUTS_SUBDIR); + File layoutsDirectory = new File(appDirectory + File.separator + DataHelper.LAYOUTS_SUBDIR); layoutsDirectory.mkdirs(); return layoutsDirectory; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4dc8627d4..15271702c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,9 @@ android:launchMode="singleTop" /> + android:exported="false" + android:label="@string/prefs" + android:theme="@style/AppTheme" /> diff --git a/app/src/main/java/net/osmtracker/activity/About.java b/app/src/main/java/net/osmtracker/activity/About.java index 84aa7804c..9ab141da0 100644 --- a/app/src/main/java/net/osmtracker/activity/About.java +++ b/app/src/main/java/net/osmtracker/activity/About.java @@ -15,12 +15,12 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Environment; -import android.preference.PreferenceManager; import android.view.View; import android.view.View.OnClickListener; -import android.widget.Button; import android.widget.TextView; +import androidx.preference.PreferenceManager; + import java.io.File; /** diff --git a/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java b/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java index eb215767c..c4ad46b18 100644 --- a/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java +++ b/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java @@ -13,7 +13,6 @@ import android.net.NetworkInfo; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -26,6 +25,8 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.preference.PreferenceManager; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java b/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java index 2d5f864dd..50438c96a 100644 --- a/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java +++ b/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java @@ -11,9 +11,10 @@ import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.Log; import android.view.ContextMenu; import android.view.Menu; @@ -26,6 +27,7 @@ import net.osmtracker.OSMTracker; import net.osmtracker.R; +import net.osmtracker.db.DataHelper; import net.osmtracker.layout.DownloadCustomLayoutTask; import net.osmtracker.util.CustomLayoutsUtils; import net.osmtracker.util.FileSystemUtils; @@ -41,7 +43,7 @@ public class ButtonsPresets extends Activity { @SuppressWarnings("unused") - private static final String TAG = Preferences.class.getSimpleName(); + private static final String TAG = ButtonsPresets.class.getSimpleName(); final private int RC_WRITE_PERMISSION = 1; @@ -108,7 +110,7 @@ private void initializeAttributes(){ private void listLayouts(LinearLayout rootLayout){ File layoutsDir = new File(this.getExternalFilesDir(null), storageDir + - File.separator + Preferences.LAYOUTS_SUBDIR + File.separator); + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator); int AT_START = 0; //the position to insert the view at int fontSize = 20; if (layoutsDir.exists() && layoutsDir.canRead()) { @@ -116,7 +118,7 @@ private void listLayouts(LinearLayout rootLayout){ String[] layoutFiles = layoutsDir.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { - return filename.endsWith(Preferences.LAYOUT_FILE_EXTENSION); + return filename.endsWith(DataHelper.LAYOUT_FILE_EXTENSION); } }); //Remove all the layouts @@ -272,10 +274,10 @@ protected void onPostExecute(Boolean status){ @Override public void onClick(DialogInterface dialog, int which) { String fileName = layoutsFileNames.get(checkboxHeld.getText()); - String rootDir = storageDir + File.separator + Preferences.LAYOUTS_SUBDIR + File.separator; + String rootDir = storageDir + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator; File fileToDelete = new File(externalFilesDir, rootDir + fileName); String iconDirName = fileName.substring(0, fileName.length() - CustomLayoutsUtils.LAYOUT_EXTENSION_ISO.length()) - + Preferences.ICONS_DIR_SUFFIX; + + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX; File iconDirToDelete = new File(externalFilesDir, rootDir + iconDirName); boolean successfulDeletion = FileSystemUtils.delete(fileToDelete, false); @@ -312,7 +314,7 @@ public void onClick(DialogInterface dialog, int which) { * Example: given "foo_es.xml" return only "es" */ private String getIso(String layoutName){ - String tmp = layoutName.substring(0, layoutName.length() - Preferences.LAYOUT_FILE_EXTENSION.length()); + String tmp = layoutName.substring(0, layoutName.length() - DataHelper.LAYOUT_FILE_EXTENSION.length()); String iso = ""; for (int i=tmp.length() - AvailableLayouts.ISO_CHARACTER_LENGTH; i { - Intent intent = new Intent(this, ButtonsPresets.class); - startActivity(intent); - return true; - }); + setContentView(R.layout.settings_activity); + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings, new SettingsFragment()) + .commit(); } + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + } - // External storage directory - EditTextPreference storageDirPref = (EditTextPreference) findPreference(OSMTracker.Preferences.KEY_STORAGE_DIR); - storageDirPref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR)); - storageDirPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Ensure there is always a leading slash - if (! ((String) newValue).startsWith(File.separator)) { - newValue = File.separator + (String) newValue; + public static class SettingsFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.preferences, rootKey); + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(requireContext()); + + // General settings + setupVoiceRecDuration(); + setupOSMAuthClearData(prefs); + + // GPS Settings + //Open Android GPS Settings screen + setupPreferenceNavigation( + OSMTracker.Preferences.KEY_GPS_OSSETTINGS, + new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + //GPSLogging Interval + setupEditTextNum( + OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, + getString(R.string.prefs_gps_logging_interval_seconds), + getString(R.string.prefs_gps_logging_interval_summary), + getString(R.string.prefs_gps_logging_interval_empty) + ); + //GPS Logging Min Distance + setupEditTextNum( + OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, + getString(R.string.prefs_gps_logging_min_distance_meters), + getString(R.string.prefs_gps_logging_min_distance_summary), + getString(R.string.prefs_gps_logging_min_distance_empty) + ); + + + // GPX Settings + setupStorageDirectory(); + //Filename + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_FILENAME, + getString(R.string.prefs_output_filename_summary) + ); + //Accuracy + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_ACCURACY, + getString(R.string.prefs_output_accuracy_summary) + ); + //Compas Heading + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_COMPASS, + getString(R.string.prefs_compass_heading_summary) + ); + + // User Interface Settings + // Camera + setupListPreference( + OSMTracker.Preferences.KEY_UI_PICTURE_SOURCE, + getString(R.string.prefs_ui_picture_source_summary) + ); + // App Theme + setupListPreference( + OSMTracker.Preferences.KEY_UI_THEME, + getString(R.string.prefs_theme_summary) + ); + //Explicit execution of buttons presets window + setupPreferenceNavigation( + OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT, + new Intent(requireContext(), ButtonsPresets.class)); + //Map tile provider + setupListPreference( + OSMTracker.Preferences.KEY_UI_MAP_TILE, + getString(R.string.prefs_map_tile_summary) + ); + // Screen Orientation + setupListPreference( + OSMTracker.Preferences.KEY_UI_ORIENTATION, + getString(R.string.prefs_ui_orientation_summary) + ); + + } + + /** + * + */ + private void setupStorageDirectory() { + // External storage directory + EditTextPreference storageDirPref = findPreference( + OSMTracker.Preferences.KEY_STORAGE_DIR); + + if (storageDirPref == null) return; + + // Set summary provider + storageDirPref.setSummaryProvider(preference -> { + String val = storageDirPref.getText(); + if (TextUtils.isEmpty(val)) { + return OSMTracker.Preferences.VAL_STORAGE_DIR; } + return val; + }); - // Set summary with the directory value - preference.setSummary((String) newValue); + // Enforce the leading slash + storageDirPref.setOnPreferenceChangeListener((preference, newValue) -> { + String val = newValue.toString().trim(); + // Empty + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), + R.string.prefs_storage_dir_empty, + Toast.LENGTH_SHORT).show(); + return false; + } + + // Ensure there is always a leading slash + if (!val.startsWith(File.separator)) { + String fixedVal = File.separator + val; + ((EditTextPreference) preference).setText(fixedVal); + return false; //ignores the user input + } return true; - } - }); - - // Voice record duration - Preference pref = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); - pref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_VOICEREC_DURATION, OSMTracker.Preferences.VAL_VOICEREC_DURATION) + " " + getResources().getString(R.string.prefs_voicerec_duration_seconds)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the number of seconds, following by "seconds" - preference.setSummary(newValue+ " " + getResources().getString(R.string.prefs_voicerec_duration_seconds)); - return true; - } - }); - - // Use barometer yes/no - pref = findPreference(OSMTracker.Preferences.KEY_USE_BAROMETER); - pref.setSummary(getResources().getString(R.string.prefs_use_barometer_summary)); - - - // Update GPS logging interval summary to the current value - pref = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); - pref.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - return true; - } - }); - - // Update GPS min. distance summary to the current value - pref = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); - pref.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); + }); + } + + /** + * Voice record duration: set a custom SummaryProvider + */ + private void setupVoiceRecDuration() { + Preference voiceRec = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); + + if (voiceRec == null) return; + + voiceRec.setSummaryProvider( + (Preference.SummaryProvider) preference -> { + // Return your combined string + return preference.getEntry() + " " + + getString(R.string.prefs_voicerec_duration_seconds); + }); + } + + /** + * Clear OSM data: Disable if there's no OSM data stored + * + * @param prefs SharedPreferences + */ + private void setupOSMAuthClearData(SharedPreferences prefs) { + + Preference OSMAuthClearData = findPreference( + OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); + + if (OSMAuthClearData == null) return; + + String tokenKey = OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN; + OSMAuthClearData.setEnabled(prefs.contains(tokenKey)); + // Set a Click Listener to show the confirmation dialog + OSMAuthClearData.setOnPreferenceClickListener(preference -> { + new androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle(preference.getTitle()) + .setMessage(R.string.prefs_osm_clear_oauth_data_dialog) + .setIcon(preference.getIcon()) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + // User clicked OK: Clear the data + prefs.edit().remove(tokenKey).apply(); + // Disable the button now that data is gone + preference.setEnabled(false); + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); return true; - } - }); - - // don't allow the logging_min_distance to be empty - final EditText et = ((EditTextPreference)pref).getEditText(); - final EditTextPreference etp = (EditTextPreference)pref; - et.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - if (s.length() >= 0) { - try { - Button bt_ok = ((AlertDialog) etp.getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); - if (s.length() == 0) { - bt_ok.setEnabled(false); - } else { - ((AlertDialog) etp.getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); - } - } catch (Exception ex) { - } - } - } - - @Override - public void afterTextChanged(Editable s) { - } - } - ); + }); + + } + + /** + * Setup a preference that launches an activity via Intent + * @param preferenceKey The preference key + * @param intent The intent to launch + */ + private void setupPreferenceNavigation(String preferenceKey, Intent intent) { + Preference preference = findPreference(preferenceKey); + + if (preference == null) return; - pref = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + preference.setOnPreferenceClickListener(p -> { + startActivity(intent); return true; - } - }); - - // Button screen orientation option - pref = findPreference(OSMTracker.Preferences.KEY_UI_ORIENTATION); - ListPreference orientationListPreference = (ListPreference) pref; - String displayValueKey = prefs.getString(OSMTracker.Preferences.KEY_UI_ORIENTATION, OSMTracker.Preferences.VAL_UI_ORIENTATION); - int displayValueIndex = orientationListPreference.findIndexOfValue(displayValueKey); - String displayValue = orientationListPreference.getEntries()[displayValueIndex].toString(); - orientationListPreference.setSummary(displayValue + ".\n" - + getResources().getString(R.string.prefs_ui_orientation_summary)); - - // Set a listener to update the preference display after a change is made - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the display text of the item and a description of the preference - ListPreference orientationListPreference = (ListPreference)preference; - // Pull the display string from the list preference rather than simply using the key value - int newValueIndex = orientationListPreference.findIndexOfValue((String)newValue); - String newPreferenceDisplayValue = orientationListPreference.getEntries()[newValueIndex].toString(); - - preference.setSummary(newPreferenceDisplayValue - + ".\n" + getResources().getString(R.string.prefs_ui_orientation_summary)); + }); + } + + /** + * + * @param preferenceKey from OSMTracker.Preferences + * @param valueSuffix appended to the end of the value, shown in the summary + * @param summary static summary to be appended to the end of the summary + * @param validationError in case of empty value + */ + private void setupEditTextNum(String preferenceKey, String valueSuffix, String summary, + String validationError) { + EditTextPreference numInputPref = findPreference(preferenceKey); + if (numInputPref == null) return; + + // Set input type to number and move cursor to the end + numInputPref.setOnBindEditTextListener(editText -> { + editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); + editText.setSelection(editText.getText().length()); + }); + + // Set summary provider + numInputPref.setSummaryProvider(preference -> { + EditTextPreference editTextPreference = (EditTextPreference) preference; + return editTextPreference.getText() + " " + valueSuffix + ". " + summary; + }); + + numInputPref.setOnPreferenceChangeListener((preference, newValue) -> { + String val = (String) newValue; + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), validationError, Toast.LENGTH_SHORT).show(); + return false; + } return true; - } - }); - - // Clear OSM data: Disable if there's no OSM data stored - pref = findPreference(OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); - if (prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)) { - pref.setEnabled(true); - } else { - pref.setEnabled(false); + }); + } + + /** + * Setup a ListPreference with a custom two lines summary, displays the selected entry + * on the first line, and the static summary on the second line. + * + * @param preferenceKey preference identifier + * @param staticSummary text to show on the second line + */ + private void setupListPreference(String preferenceKey, String staticSummary) { + ListPreference listPref = findPreference(preferenceKey); + + if (listPref == null) return; + + listPref.setSummaryProvider(preference -> { + ListPreference lp = (ListPreference) preference; + CharSequence entry = lp.getEntry(); + // Null check: entry might be null if no value is selected + String displayValue = Objects.requireNonNull(entry).toString(); + return displayValue + ".\n" + staticSummary; + }); } - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Clear data - Editor editor = prefs.edit(); - editor.remove(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN); - editor.commit(); - - preference.setEnabled(false); - return false; - } - }); } - -} +} \ No newline at end of file diff --git a/app/src/main/java/net/osmtracker/activity/TrackDetail.java b/app/src/main/java/net/osmtracker/activity/TrackDetail.java index 5cb640f0c..d73a40949 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackDetail.java +++ b/app/src/main/java/net/osmtracker/activity/TrackDetail.java @@ -24,9 +24,10 @@ import android.graphics.Paint; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.Log; import android.view.Menu; import android.view.MenuInflater; diff --git a/app/src/main/java/net/osmtracker/activity/TrackLogger.java b/app/src/main/java/net/osmtracker/activity/TrackLogger.java index 0cbb5f405..45c4a1f34 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackLogger.java +++ b/app/src/main/java/net/osmtracker/activity/TrackLogger.java @@ -20,7 +20,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.StrictMode; -import android.preference.PreferenceManager; import android.provider.MediaStore; import android.provider.Settings; import android.util.Log; @@ -36,6 +35,7 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; @@ -313,7 +313,7 @@ protected void onResume() { File layoutFile = new File( this.getExternalFilesDir(null), OSMTracker.Preferences.VAL_STORAGE_DIR - + File.separator + Preferences.LAYOUTS_SUBDIR + + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator + userLayout); mainLayout = new UserDefinedLayout(this, currentTrackId, layoutFile); } diff --git a/app/src/main/java/net/osmtracker/activity/TrackManager.java b/app/src/main/java/net/osmtracker/activity/TrackManager.java index f4d6ca9e6..10a7b40e9 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackManager.java +++ b/app/src/main/java/net/osmtracker/activity/TrackManager.java @@ -1,11 +1,11 @@ package net.osmtracker.activity; -import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -17,13 +17,11 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.util.Base64OutputStream; import android.util.Log; import android.view.ContextMenu; @@ -53,8 +51,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.Files; -import java.util.Base64; import java.util.Date; /** diff --git a/app/src/main/java/net/osmtracker/db/DataHelper.java b/app/src/main/java/net/osmtracker/db/DataHelper.java index aafdbb751..fa50d8a56 100644 --- a/app/src/main/java/net/osmtracker/db/DataHelper.java +++ b/app/src/main/java/net/osmtracker/db/DataHelper.java @@ -8,10 +8,10 @@ import android.database.Cursor; import android.location.Location; import android.net.Uri; -import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.db.model.Track; import net.osmtracker.db.model.TrackPoint; @@ -53,6 +53,12 @@ public class DataHelper { */ public static final String EXTENSION_ZIP = ".zip"; + /** + * File extension for layout files + */ + + public static final String LAYOUT_FILE_EXTENSION = ".xml"; + /** * GPX Files MIME standard for sharing */ @@ -68,6 +74,19 @@ public class DataHelper { */ public static final String MIME_TYPE_IMAGE = "image/*"; + /** + * Directory containing user layouts, relative to storage dir. + */ + public static final String LAYOUTS_SUBDIR = "layouts"; + + /** + * The suffix that must be added to the layout's name for getting its icons directory + * Example: water_supply <- layout name + * water_supply_icons <- icon directory + */ + + public static final String LAYOUTS_ICONS_DIR_SUFFIX = "_icons"; + /** * APP sign plus FileProvider = authority */ diff --git a/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java b/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java index 855929f85..347bf3467 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java @@ -5,9 +5,10 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java b/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java index fdc971180..61369fca4 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java @@ -2,9 +2,10 @@ import android.content.Context; import android.database.Cursor; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.db.DataHelper; import net.osmtracker.exception.ExportTrackException; diff --git a/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java b/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java index a9dec64da..c54faa2a3 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java @@ -10,7 +10,6 @@ import android.database.Cursor; import android.media.MediaScannerConnection; import android.os.AsyncTask; -import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; @@ -36,6 +35,8 @@ import static net.osmtracker.db.DataHelper.EXTENSION_GPX; import static net.osmtracker.util.FileSystemUtils.getUniqueChildNameFor; +import androidx.preference.PreferenceManager; + /** * Base class to writes a GPX file and export * track media (Photos, Sounds) diff --git a/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java b/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java index 2c4048aa5..525c34447 100644 --- a/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java +++ b/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java @@ -4,9 +4,10 @@ import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import org.json.JSONArray; import org.json.JSONObject; import net.osmtracker.OSMTracker; @@ -21,7 +22,7 @@ import java.util.Set; import net.osmtracker.R; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.CustomLayoutsUtils; import net.osmtracker.util.URLCreator; @@ -55,11 +56,11 @@ public boolean downloadLayout(String layoutName, String iso){ String layoutURL = URLCreator.createLayoutFileURL(context, layoutFolderName, iso); String layoutPath = context.getExternalFilesDir(null) + storageDir + File.separator + - Preferences.LAYOUTS_SUBDIR + File.separator; + DataHelper.LAYOUTS_SUBDIR + File.separator; //TODO: change "_icons" for Preferences.ICONS_DIR_SUFFIX String iconsPath = context.getExternalFilesDir(null) + storageDir + File.separator + - Preferences.LAYOUTS_SUBDIR + File.separator + layoutFolderName+"_icons" + + DataHelper.LAYOUTS_SUBDIR + File.separator + layoutFolderName+"_icons" + File.separator; Boolean status = false; diff --git a/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java b/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java index f2b264d9d..3afd60bc5 100644 --- a/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java +++ b/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java @@ -16,10 +16,11 @@ import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; diff --git a/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java index f78c80b9f..46d2c4a63 100644 --- a/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java +++ b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java @@ -6,9 +6,10 @@ import android.content.DialogInterface; import android.content.SharedPreferences.Editor; import android.os.AsyncTask; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java b/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java index fb785d279..a6a735fb2 100644 --- a/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java +++ b/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java @@ -18,11 +18,11 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.preference.PreferenceManager; import android.util.Log; import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; diff --git a/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java b/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java index b07f7884f..6e27b27ce 100644 --- a/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java +++ b/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java @@ -2,11 +2,12 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.activity.AvailableLayouts; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.layout.GetStringResponseTask; import java.io.BufferedReader; @@ -32,7 +33,7 @@ public class CustomLayoutsUtils { */ public static String convertFileName(String fileName) { //Remove de file extension - String subname = fileName.replace(Preferences.LAYOUT_FILE_EXTENSION,""); + String subname = fileName.replace(DataHelper.LAYOUT_FILE_EXTENSION,""); //Check if it has iso: if(subname.matches("\\w+_..")){ @@ -49,7 +50,7 @@ public static String convertFileName(String fileName) { * @return Layout filename. */ public static String unconvertFileName(String representation){ - return representation.replace(" ","_") + Preferences.LAYOUT_FILE_EXTENSION; + return representation.replace(" ","_") + DataHelper.LAYOUT_FILE_EXTENSION; } /** diff --git a/app/src/main/java/net/osmtracker/util/URLCreator.java b/app/src/main/java/net/osmtracker/util/URLCreator.java index e87f5d81e..d50ee82e7 100644 --- a/app/src/main/java/net/osmtracker/util/URLCreator.java +++ b/app/src/main/java/net/osmtracker/util/URLCreator.java @@ -2,9 +2,11 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; /** * Created by labexp on 13/12/17. @@ -66,7 +68,7 @@ public static String createLayoutFileURL(Context context, String layoutFolderNam String[] ghParams = getGithubParams(context); String url = RAW_CONTENT + ghParams[USERNAME] + "/" + ghParams[REPO] + "/" + ghParams[BRANCH] - + "/layouts/" + layoutFolderName + "/" + iso + Preferences.LAYOUT_FILE_EXTENSION; + + "/layouts/" + layoutFolderName + "/" + iso + DataHelper.LAYOUT_FILE_EXTENSION; return url; } diff --git a/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java b/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java index 97018ffc0..f50e8f373 100644 --- a/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java +++ b/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java @@ -10,11 +10,12 @@ import android.media.MediaRecorder; import android.media.MediaRecorder.OnInfoListener; import android.os.SystemClock; -import android.preference.PreferenceManager; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml new file mode 100644 index 000000000..de6591a20 --- /dev/null +++ b/app/src/main/res/layout/settings_activity.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 32f528bf6..729d97e93 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -21,10 +21,12 @@ GPS logging interval Use 0 for the shortest possible (affects battery life) seconds + GPS logging interval cannot be empty GPS logging distance Min. distance between track points in meters, use 0 for the shortest possible meters + Min. distance between track points cannot be empty User interface @@ -75,6 +77,7 @@ GPX settings Storage folder in documents Effective for the next track (not the current one) + Storage folder value cannot be empty One directory per track Save each track and associated files to its own directory Filename for named tracks diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cbb191bbd..fa928bea4 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1,133 +1,148 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java b/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java index 07c7b5f6b..0786ac9d5 100644 --- a/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java +++ b/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java @@ -5,7 +5,6 @@ import android.content.Context; import android.content.res.Resources; import android.os.Environment; -import android.preference.PreferenceManager; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -33,6 +32,8 @@ import static org.powermock.api.mockito.PowerMockito.verifyPrivate; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PowerMockIgnore("jdk.internal.reflect.*") public class ButtonsPresetsTest { diff --git a/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java b/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java index 2bd6f8775..59b5b8013 100644 --- a/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java +++ b/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java @@ -21,7 +21,8 @@ import android.content.res.Resources; import android.database.Cursor; import android.os.Environment; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; diff --git a/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java b/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java index f0f3334c1..9410e7c21 100644 --- a/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java +++ b/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java @@ -3,11 +3,10 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.UnitTestUtils; import org.junit.Test; @@ -24,6 +23,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest({PreferenceManager.class, Environment.class, Log.class}) @PowerMockIgnore("jdk.internal.reflect.*") @@ -68,7 +69,7 @@ public void downloadLayoutWithoutIconsTest() { // Check if layout was downloaded at .../osmtracker/layouts/abc_en.xml String expectedLayoutFilePath = mockContext.getExternalFilesDir(null) + OSMTracker.Preferences.VAL_STORAGE_DIR + File.separator - + Preferences.LAYOUTS_SUBDIR + File.separator + + DataHelper.LAYOUTS_SUBDIR + File.separator + expectedLayoutFilename; System.out.println(expectedLayoutFilePath); diff --git a/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java b/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java index 0d0a2efaa..05faea75e 100644 --- a/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java +++ b/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java @@ -3,7 +3,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.AssetManager; -import android.preference.PreferenceManager; import net.osmtracker.OSMTracker; @@ -26,6 +25,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class) @PowerMockIgnore("jdk.internal.reflect.*") diff --git a/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java b/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java index 7072e3966..8eeedd0a8 100644 --- a/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java +++ b/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; -import android.preference.PreferenceManager; import android.content.SharedPreferences.Editor; import net.osmtracker.OSMTracker; @@ -21,6 +20,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class) diff --git a/app/src/test/java/net/osmtracker/util/URLCreatorTest.java b/app/src/test/java/net/osmtracker/util/URLCreatorTest.java index 001366bea..4b4888f9a 100644 --- a/app/src/test/java/net/osmtracker/util/URLCreatorTest.java +++ b/app/src/test/java/net/osmtracker/util/URLCreatorTest.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,6 +14,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class)