diff --git a/CHANGELOG.md b/CHANGELOG.md index 741cb66d8..32a801e41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- integrate with OS app language settings on Android >=14 + ## [v1.11.18] - 2024-11-18 ### Changed diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt index 3fe35ae01..47cb4a572 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt @@ -1,11 +1,14 @@ package deckers.thibault.aves.channel.calls +import android.app.LocaleConfig +import android.app.LocaleManager import android.content.Context import android.content.Intent import android.content.res.Resources import android.location.Geocoder import android.net.Uri import android.os.Build +import android.os.LocaleList import android.provider.MediaStore import android.provider.Settings import androidx.core.content.pm.ShortcutManagerCompat @@ -32,6 +35,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { "getCapabilities" -> defaultScope.launch { safe(call, result, ::getCapabilities) } "getDefaultTimeZoneRawOffsetMillis" -> safe(call, result, ::getDefaultTimeZoneRawOffsetMillis) "getLocales" -> safe(call, result, ::getLocales) + "setLocaleConfig" -> safe(call, result, ::setLocaleConfig) "getPerformanceClass" -> safe(call, result, ::getPerformanceClass) "isLocked" -> safe(call, result, ::isLocked) "isSystemFilePickerEnabled" -> safe(call, result, ::isSystemFilePickerEnabled) @@ -88,6 +92,21 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { result.success(locales) } + private fun setLocaleConfig(call: MethodCall, result: MethodChannel.Result) { + val locales = call.argument>("locales") + if (locales.isNullOrEmpty()) { + result.error("setLocaleConfig-args", "missing arguments", null) + return + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val lm = context.getSystemService(Context.LOCALE_SERVICE) as? LocaleManager + lm?.overrideLocaleConfig = LocaleConfig(LocaleList.forLanguageTags(locales.joinToString(","))) + } + + result.success(true) + } + private fun getPerformanceClass(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val performanceClass = Build.VERSION.MEDIA_PERFORMANCE_CLASS diff --git a/lib/services/device_service.dart b/lib/services/device_service.dart index 0eac24328..ad702490d 100644 --- a/lib/services/device_service.dart +++ b/lib/services/device_service.dart @@ -12,6 +12,8 @@ abstract class DeviceService { Future> getLocales(); + Future setLocaleConfig(List locales); + Future getPerformanceClass(); Future isLocked(); @@ -80,6 +82,17 @@ class PlatformDeviceService implements DeviceService { return []; } + @override + Future setLocaleConfig(List locales) async { + try { + await _platform.invokeMethod('setLocaleConfig', { + 'locales': locales.map((v) => v.toLanguageTag()).toList(), + }); + } on PlatformException catch (e, stack) { + await reportService.recordError(e, stack); + } + } + @override Future getPerformanceClass() async { try { diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index e75829d11..cc1179ffd 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -502,6 +502,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { _monitorSettings(); videoControllerFactory.init(); + unawaited(deviceService.setLocaleConfig(AvesApp.supportedLocales)); unawaited(storageService.deleteTempDirectory()); unawaited(_setupErrorReporting());