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
|
package expo.modules.keyboardlanguage
|
||||||
|
|
||||||
|
import android.database.ContentObserver
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.provider.Settings
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import expo.modules.kotlin.modules.Module
|
import expo.modules.kotlin.modules.Module
|
||||||
import expo.modules.kotlin.modules.ModuleDefinition
|
import expo.modules.kotlin.modules.ModuleDefinition
|
||||||
|
|
||||||
class ExpoKeyboardLanguageModule : Module() {
|
class ExpoKeyboardLanguageModule : Module() {
|
||||||
|
private var subtypeObserver: ContentObserver? = null
|
||||||
|
private var lastLanguage: String? = null
|
||||||
|
|
||||||
override fun definition() =
|
override fun definition() =
|
||||||
ModuleDefinition {
|
ModuleDefinition {
|
||||||
Name("ExpoKeyboardLanguage")
|
Name("ExpoKeyboardLanguage")
|
||||||
|
|
||||||
Function("getCurrentKeyboardLanguage") {
|
Events("onKeyboardLanguageChange")
|
||||||
val context = appContext.reactContext ?: return@Function null
|
|
||||||
val imm = context.getSystemService<InputMethodManager>() ?: return@Function null
|
|
||||||
val subtype = imm.currentInputMethodSubtype ?: return@Function null
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
Function("getCurrentKeyboardLanguage") {
|
||||||
val tag = subtype.languageTag
|
return@Function getCurrentLanguage()
|
||||||
if (tag.isNotEmpty()) return@Function tag
|
}
|
||||||
|
|
||||||
|
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")
|
context.contentResolver.registerContentObserver(uri, false, subtypeObserver!!)
|
||||||
val locale = subtype.locale
|
}
|
||||||
if (locale.isNotEmpty()) return@Function locale
|
|
||||||
|
|
||||||
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