diff --git a/modules/expo-keyboard-language/android/src/main/java/expo/modules/keyboardlanguage/ExpoKeyboardLanguageModule.kt b/modules/expo-keyboard-language/android/src/main/java/expo/modules/keyboardlanguage/ExpoKeyboardLanguageModule.kt index cb173e3606..1fe5856627 100644 --- a/modules/expo-keyboard-language/android/src/main/java/expo/modules/keyboardlanguage/ExpoKeyboardLanguageModule.kt +++ b/modules/expo-keyboard-language/android/src/main/java/expo/modules/keyboardlanguage/ExpoKeyboardLanguageModule.kt @@ -1,31 +1,68 @@ package expo.modules.keyboardlanguage +import android.database.ContentObserver import android.os.Build +import android.os.Handler +import android.os.Looper +import android.provider.Settings import android.view.inputmethod.InputMethodManager import androidx.core.content.getSystemService import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class ExpoKeyboardLanguageModule : Module() { + private var subtypeObserver: ContentObserver? = null + private var lastLanguage: String? = null + override fun definition() = ModuleDefinition { Name("ExpoKeyboardLanguage") - Function("getCurrentKeyboardLanguage") { - val context = appContext.reactContext ?: return@Function null - val imm = context.getSystemService() ?: return@Function null - val subtype = imm.currentInputMethodSubtype ?: return@Function null + Events("onKeyboardLanguageChange") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - val tag = subtype.languageTag - if (tag.isNotEmpty()) return@Function tag + Function("getCurrentKeyboardLanguage") { + return@Function getCurrentLanguage() + } + + OnStartObserving { + val context = appContext.reactContext ?: return@OnStartObserving + val uri = Settings.Secure.getUriFor("selected_input_method_subtype") + + subtypeObserver = object : ContentObserver(Handler(Looper.getMainLooper())) { + override fun onChange(selfChange: Boolean) { + val language = getCurrentLanguage() + if (language != lastLanguage) { + lastLanguage = language + sendEvent("onKeyboardLanguageChange", mapOf("language" to language)) + } + } } - @Suppress("DEPRECATION") - val locale = subtype.locale - if (locale.isNotEmpty()) return@Function locale + context.contentResolver.registerContentObserver(uri, false, subtypeObserver!!) + } - return@Function null + OnStopObserving { + subtypeObserver?.let { observer -> + appContext.reactContext?.contentResolver?.unregisterContentObserver(observer) + } + subtypeObserver = null } } + + private fun getCurrentLanguage(): String? { + val context = appContext.reactContext ?: return null + val imm = context.getSystemService() ?: return null + val subtype = imm.currentInputMethodSubtype ?: return null + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val tag = subtype.languageTag + if (tag.isNotEmpty()) return tag + } + + @Suppress("DEPRECATION") + val locale = subtype.locale + if (locale.isNotEmpty()) return locale + + return null + } }