因为currentInputConnection总是返回null



我正在尝试为Android构建一个IME(输入法编辑器(。我知道我必须创建一个扩展InputMethodService的类,才能访问getCurrentInputConnection方法。我的理解是,这会将我返回到当前关注的文本字段,如果没有,则返回null。

然后我知道我必须做这样的事情:

val focusedTextField = currentInputConnection ?: return

问题是,我总是得到null作为结果。我的理论是,文本编辑器(当前关注的文本字段(不将我的应用程序识别为IME,或者可能";没有意识到";它正在被集中。所以也许我必须提供更多的信息。我已经检查了声明服务和提供元数据的清单,一切似乎都是正确的。res/xml/method.xml文件是正确的。

这是清单文件。我被告知,自安卓11以来,我们必须申请位置许可才能使用服务

<service
android:name=".IMEService"
android:label="Amazing Keyboard"
android:foregroundServiceType="location"
android:permission="android.permission.BIND_INPUT_METHOD"
android:exported="true">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="@xml/method" />
</service>

这是方法文件

<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.example.amazingkeyboard.MainActivity">
<subtype
android:name = "my app"
android:label="English (U.S)"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard"/>
</input-method>

这就是我正在做的,我正在使用jetpack-compose,但这不是问题所在,因为我已经尝试返回xml视图,但我总是有错误

class IMEService : InputMethodService(), LifecycleOwner, 
ViewModelStoreOwner, SavedStateRegistryOwner {
fun sendText(text : CharSequence, newCursorPosition : Int) {
val focusedTextField = currentInputConnection ?: return //always returns null 
focusedTextField.commitText(text, newCursorPosition) 
} 
...
}

这就是我称之为的方法

val connection = IMEService()
@Composable fun TestKey(modifier: Modifier = Modifier) {
Key( 
modifier = modifier .clickable { 
connection.sendText(unicodeToString(0x1F436), 1)
}...

当我删除验证时。正如我在上面所说的,问题是我总是得到零。显然,如果我进行验证,就不会有错误,但我不能发送任何一个(因为我总是空的(

// val focusedTextField = currentInputConnection ?: return
val focusedTextField = currentInputConnection

我有这个错误。

java.lang.NullPointerException:
Attempt to invoke interface method 'boolean android.view.inputmethod.InputConnection.commitText(java.lang.CharSequence, int)' on a null object reference
at com.chrrissoft.amazingkeyboard.IMEService.sendText(IMEService.kt:21)
at com.chrrissoft.amazingkeyboard.composables.GeneralKeysKt$TestKey$1.invoke(generalKeys.kt:32)
at com.chrrissoft.amazingkeyboard.composables.GeneralKeysKt$TestKey$1.invoke(generalKeys.kt:31)

这是完整的项目,以防你想审查它。

您在以下代码的第二行获得NullPointerException

val focusedTextField = currentInputConnection
focusedTextField.commitText(text, newCursorPosition) 

因为当前活动的InputConnection没有绑定到输入法,这就是currentInputConnection为null的原因。

InputConnection中有一个onBindInput方法,当新客户端绑定到输入方法时调用该方法。在这个调用中,您知道currentInputConnection返回有效对象。所以在使用currentInputConnection之前,客户端应该绑定到输入法。

要在类作用域之外使用IMEService的公共方法,您需要有一个绑定服务的实例。深入了解GitHub上的源代码,通过将IMEService传递给TestKey()函数似乎很容易解决这个问题。整个代码看起来像这样:

@Composable
fun TestKey(modifier: Modifier = Modifier, connection: IMEService) {
Key(
modifier = modifier
//...
.clickable {
connection.sendText(unicodeToString(0x1F383), 1)
}
) {
Icon(/*...*/)
}
}
@Composable
fun EmojiLayout(navController: NavHostController, connection: IMEService) {
val (currentPage, onPageChange) = remember {
mutableStateOf(EmoticonsAndEmotionsPage)
}
Column(modifier = Modifier.fillMaxSize()) {
EmojiPage(
//...
)
Row(
//...
) {
//...
TestKey(Modifier.weight(1f), connection)
}
}
}
@Composable
fun KeyboardScreen(connection: IMEService) {
AmazingKeyboardTheme() {
Column(
//...
) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "qwertyLayout") {
//...
composable("emojiLayout") { EmojiLayout(navController, connection) }
}
}
}
}
class AndroidKeyboardView(context: Context) : FrameLayout(context) {
constructor(service: IMEService) : this(service as Context) {
inflate(service, R.layout.keyboard_view, this)
findViewById<ComposeView>(R.id.compose_view).setContent {
KeyboardScreen(connection = service)
}
}
}

IMEService类保持不变。

我假设您遵循了本文档并进行了所有必要的设置,包括将IMEService添加到Android清单中。

val connection = IMEService()

不幸的是,你不能像那样使用Service,你不能自己创建Service类的实例并相信它会正确工作。服务由安卓系统创建。如果您想使用currentInputConnection属性,您应该在IMEService中使用它,或者您需要以某种方式将它的实例传递到您想使用它的地方,或者如果您想拥有IMEService服务的实例,则需要绑定到它。另请参阅这些关于如何绑定到Service的答案。

相关内容

  • 没有找到相关文章

最新更新