add android keyboard language change detection
uses ContentObserver on Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE to detect when the user switches keyboard language on Android. deduplicates events like the iOS side. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+48
-11
@@ -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<InputMethodManager>() ?: 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<InputMethodManager>() ?: 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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user