Issue
I need to simulate typing text with char-by-char delays using soft input keyboard on a WebView. I can't use WebView#dispatchKeyEvent because it's not suitable for typing Unicode text and does not simulate soft input keyboard.
I am overriding WebView#onCreateInputConnection to get a reference to the actual input connection being used by the webview so I can send input to it like soft input keyboard does:
class CustomWebView(context: Context, attrs: AttributeSet): WebView(context, attrs) {
private var inputConnection: InputConnection? = null
override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection? {
val newInputConnection = super.onCreateInputConnection(outAttrs) ?: return inputConnection
inputConnection = newInputConnection
return newInputConnection
}
suspend fun sendTextInput(text: String, keyDelayStart: Long, keyDelayEnd: Long) {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager ?:
throw Exception("could not get system's InputMethodManager")
requestFocus()
val defer = CompletableDeferred<Int>()
// AsyncResultReceiver is a custom ResultReceiver which resolves a deferred on the callback
imm.showSoftInput(this, 0, AsyncResultReceiver(WeakReference(defer)))
val result = defer.await()
if (result == InputMethodManager.RESULT_HIDDEN || result == InputMethodManager.RESULT_UNCHANGED_HIDDEN)
throw Exception("could not show IME keyboard")
val ic = onCreateInputConnection(EditorInfo()) ?:
throw Exception("could not create InputConnection")
for (char in text) {
ic.commitText(char.toString(), 1)
delay(Random.nextLong(keyDelayStart, keyDelayEnd))
}
imm.hideSoftInputFromWindow(windowToken, 0)
}
}
I tested by typing Hello, world!
on an input field, but when typing next chars it's clearing previous ones:
when typing backwards with ic.commitText(char.toString(), 0)
it types fully:
The test is running on Android 12.
Solution
InputConnection#commitText()
replaces the contents of the actual composing region. To add new characters you need to move the composing region forward (the "cursor") with InputConnection#setComposingRegion()
. Try:
for (i in text.indices) {
ic.setComposingRegion(i, i + 1)
ic.commitText(text[i].toString(), 1)
delay(Random.nextLong(keyDelayStart, keyDelayEnd))
}
Answered By - hldev
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.