diff --git a/build-logic/android-library/src/main/kotlin/AndroidLibraryBasePlugin.kt b/build-logic/android-library/src/main/kotlin/AndroidLibraryBasePlugin.kt index 60289f3..0612fce 100644 --- a/build-logic/android-library/src/main/kotlin/AndroidLibraryBasePlugin.kt +++ b/build-logic/android-library/src/main/kotlin/AndroidLibraryBasePlugin.kt @@ -18,7 +18,7 @@ class AndroidLibraryBasePlugin: Plugin { namespace = "de.sipgate.${target.name.replace("-", ".")}" compileSdk = 34 - defaultConfig.minSdk = 24 + defaultConfig.minSdk = 23 } setJdkVersion(JavaVersion.VERSION_1_8) diff --git a/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/activity/ContextExt.kt b/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/activity/ContextExt.kt index c6d0c70..9a62ae6 100644 --- a/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/activity/ContextExt.kt +++ b/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/activity/ContextExt.kt @@ -3,7 +3,10 @@ package de.sipgate.dachlatten.android.activity import android.app.Activity import android.content.Context import android.content.ContextWrapper +import android.content.res.Configuration +import android.os.Build import androidx.activity.ComponentActivity +import java.util.Locale fun Context.getActivity(): Activity? = when (this) { @@ -12,5 +15,15 @@ fun Context.getActivity(): Activity? = else -> null } -val Context.languageTag: String - get() = resources.configuration.locales[0].toLanguageTag() ?: "en-GB" +const val DEFAULT_LANGUAGE = "en" + +val Context.language: String + get() = resources.configuration.primaryLocale.language ?: DEFAULT_LANGUAGE + +val Configuration.primaryLocale: Locale + get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + locales[0] + } else { + @Suppress("DEPRECATION") + locale + } diff --git a/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/connectivity/ConnectionStateFlow.kt b/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/connectivity/ConnectionStateFlow.kt index c214477..464391d 100644 --- a/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/connectivity/ConnectionStateFlow.kt +++ b/dachlatten-android/src/main/kotlin/de/sipgate/dachlatten/android/connectivity/ConnectionStateFlow.kt @@ -3,6 +3,8 @@ package de.sipgate.dachlatten.android.connectivity import android.Manifest.permission.ACCESS_NETWORK_STATE import android.net.ConnectivityManager import android.net.Network +import android.os.Build +import androidx.annotation.RequiresApi import androidx.annotation.RequiresPermission import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow @@ -12,14 +14,17 @@ import kotlinx.coroutines.flow.onStart @get:RequiresPermission(ACCESS_NETWORK_STATE) val ConnectivityManager.isOffline: Flow + @RequiresApi(Build.VERSION_CODES.N) get() = observeConnectivityAsFlow() .map { it == ConnectionState.Unavailable } @get:RequiresPermission(ACCESS_NETWORK_STATE) val ConnectivityManager.isOnline: Flow + @RequiresApi(Build.VERSION_CODES.N) get() = observeConnectivityAsFlow() .map { it == ConnectionState.Available } +@RequiresApi(Build.VERSION_CODES.N) @RequiresPermission(ACCESS_NETWORK_STATE) private fun ConnectivityManager.observeConnectivityAsFlow() = callbackFlow { val callback = object : ConnectivityManager.NetworkCallback() { diff --git a/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/ContextExt.kt b/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/ContextExt.kt new file mode 100644 index 0000000..4474654 --- /dev/null +++ b/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/ContextExt.kt @@ -0,0 +1,20 @@ +package de.sipgate.dachlatten.compose + +import android.content.Context +import android.content.res.Configuration +import android.os.Build +import java.util.Locale + + +const val DEFAULT_LANGUAGE = "en" + +val Context.language: String + get() = resources.configuration.primaryLocale.language ?: DEFAULT_LANGUAGE + +val Configuration.primaryLocale: Locale + get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + locales[0] + } else { + @Suppress("DEPRECATION") + locale + } diff --git a/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/text/UiText.kt b/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/text/UiText.kt index 0a6874b..82e0b23 100644 --- a/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/text/UiText.kt +++ b/dachlatten-compose/src/main/kotlin/de/sipgate/dachlatten/compose/text/UiText.kt @@ -1,12 +1,13 @@ package de.sipgate.dachlatten.compose.text +import android.content.res.Configuration import android.content.res.Resources -import android.os.LocaleList +import android.os.Build import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.toUpperCase +import java.util.Locale sealed interface UiText { data class DynamicString(val value: String) : UiText @@ -31,10 +32,19 @@ sealed interface UiText { vararg args: Any, ) : this(language, fallbackResource, args.asList()) - fun LocaleList.getStringForLocales(): String? { - val locale = getFirstMatch(language.keys.toTypedArray()) + fun Configuration.getStringForLocales(): String? { + val locale = resolveLocale(language.keys) return language[locale?.language?.uppercase()] } + + private fun Configuration.resolveLocale(supportedLanguages: Set): Locale? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + locales.getFirstMatch(supportedLanguages.toTypedArray()) + } else { + @Suppress("DEPRECATION") + locale + } + } } fun asString(resources: Resources) = when (this) { @@ -42,7 +52,7 @@ sealed interface UiText { is StringResource -> resources.getString(resId, *(args.toTypedArray())) is MultiLangString -> { val arguments = args.toTypedArray() - resources.configuration.locales.getStringForLocales()?.format(*arguments) + resources.configuration.getStringForLocales()?.format(*arguments) ?: fallbackResource?.let { resources.getString(it, *arguments) } ?: throw Resources.NotFoundException("Could not find multilang string") } @@ -54,7 +64,7 @@ sealed interface UiText { is StringResource -> stringResource(id = resId, formatArgs = args.toTypedArray()) is MultiLangString -> { val arguments = args.toTypedArray() - LocalConfiguration.current.locales.getStringForLocales()?.format(*arguments) + LocalConfiguration.current.getStringForLocales() ?.format(*arguments) ?: fallbackResource?.let { stringResource(id = it, formatArgs = arguments) } ?: throw Resources.NotFoundException("Could not find multilang string") }