diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index ed26730a3..9c5bf3d96 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -401,6 +401,16 @@ limitations under the License.
android:name=".services.TrackDeleteService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE"/>
+
+
+
+
+
diff --git a/src/main/java/de/dennisguse/opentracks/settings/LocalePreference.java b/src/main/java/de/dennisguse/opentracks/settings/LocalePreference.java
index 56742ffeb..95687143c 100644
--- a/src/main/java/de/dennisguse/opentracks/settings/LocalePreference.java
+++ b/src/main/java/de/dennisguse/opentracks/settings/LocalePreference.java
@@ -1,25 +1,36 @@
package de.dennisguse.opentracks.settings;
+import android.annotation.SuppressLint;
import android.app.LocaleConfig;
import android.content.Context;
import android.os.Build;
import android.os.LocaleList;
import android.util.AttributeSet;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDelegate;
+import androidx.core.app.LocaleManagerCompat;
import androidx.core.os.LocaleListCompat;
import androidx.preference.ListPreference;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.List;
import java.util.Locale;
+import java.util.Optional;
import de.dennisguse.opentracks.R;
public class LocalePreference extends ListPreference {
+ private String TAG = LocalePreference.class.getSimpleName();
+
public LocalePreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
@@ -40,18 +51,17 @@ public LocalePreference(@NonNull Context context) {
init(context);
}
+ // /data/user/0/de.dennisguse.opentracks.debug/files/androidx.appcompat.app.AppCompatDelegate.application_locales_record_file: open failed: ENOENT (No such file or directory)
private void init(Context context) {
setPersistent(false);
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- setEnabled(false);
- return;
- }
+
LocaleItem systemDefaultLocale = new LocaleItem("", context.getString(R.string.settings_locale_system_default));
LocaleItem currentLocale = new LocaleItem(Locale.getDefault().toLanguageTag(), Locale.getDefault().getDisplayName());
// All available options
- LocaleList supportedLocales = LocaleConfig.fromContextIgnoringOverride(context).getSupportedLocales();
+ LocaleList supportedLocales = getLocaleListCompat();
+
ArrayList localeItemsSorting = new ArrayList<>();
for (int i = 0; i < supportedLocales.size(); i++) {
Locale current = supportedLocales.get(i);
@@ -104,4 +114,36 @@ record LocaleItem(
String displayName
) {
}
+
+ // TODO Get this functionality from any Androidx compat library: should be in LocaleListCompat or LocaleManagerCompat
+ // 2024-12-12: on Android 14-: LocaleManagerCompat.getApplicationLocales(getContext()) returned "[]"
+ // See: https://stackoverflow.com/questions/78116375/per-app-language-preferences-get-list-of-apps-available-language-programmatic
+ @Deprecated
+ private LocaleList getLocaleListCompat() {
+ var a = LocaleManagerCompat.getApplicationLocales(getContext());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return LocaleConfig.fromContextIgnoringOverride(getContext()).getSupportedLocales();
+ }
+
+ @SuppressLint("DiscouragedApi") int localesConfigId = getContext().getResources().getIdentifier("_generated_res_locale_config", "xml", getContext().getPackageName());
+
+ List localeList = new ArrayList<>();
+ XmlPullParser xpp = getContext().getResources().getXml(localesConfigId);
+ try {
+ while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
+ if (xpp.getEventType() == XmlPullParser.START_TAG) {
+ if ("locale".equals(xpp.getName()) && xpp.getAttributeCount() > 0 && xpp.getAttributeName(0).equals("name")) {
+ localeList.add(xpp.getAttributeValue(0));
+ }
+ }
+ xpp.next();
+ }
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Could not load locales: " + e.getMessage());
+ }
+ Optional locales = localeList.stream().reduce((s1, s2) -> s1 + "," + s2);
+ return locales
+ .map(LocaleList::forLanguageTags)
+ .orElseGet(LocaleList::getEmptyLocaleList);
+ }
}