feat: use current input method to send key

This commit is contained in:
mcfans 2023-10-20 00:32:59 +08:00
parent 26e77ba2c3
commit 9a903a1ca3
2 changed files with 10 additions and 72 deletions

View File

@ -17,6 +17,8 @@ import android.util.Log
import android.widget.EditText import android.widget.EditText
import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo import android.view.accessibility.AccessibilityNodeInfo
import android.accessibilityservice.AccessibilityServiceInfo
import android.accessibilityservice.AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import java.util.* import java.util.*
import kotlin.math.abs import kotlin.math.abs
@ -65,8 +67,6 @@ class InputService : AccessibilityService() {
private var isWheelActionsPolling = false private var isWheelActionsPolling = false
private var isWaitingLongPress = false private var isWaitingLongPress = false
private var fakeEditTextForTextStateCalculation: EditText? = null
@RequiresApi(Build.VERSION_CODES.N) @RequiresApi(Build.VERSION_CODES.N)
fun onMouseInput(mask: Int, _x: Int, _y: Int) { fun onMouseInput(mask: Int, _x: Int, _y: Int) {
val x = max(0, _x) val x = max(0, _x)
@ -264,85 +264,24 @@ class InputService : AccessibilityService() {
@RequiresApi(Build.VERSION_CODES.N) @RequiresApi(Build.VERSION_CODES.N)
fun onKeyEvent(data: ByteArray) { fun onKeyEvent(data: ByteArray) {
val keyEvent = KeyEvent.parseFrom(data); val keyEvent = KeyEvent.parseFrom(data);
val handler = Handler(Looper.getMainLooper()) getInputMethod()?.let { inputMethod ->
handler.post { inputMethod.getCurrentInputConnection()?.let { inputConnection ->
findFocus(AccessibilityNodeInfo.FOCUS_INPUT)?.let { node ->
val text = node.getText()
val isShowingHint = node.isShowingHintText()
var textSelectionStart = node.getTextSelectionStart()
var textSelectionEnd = node.getTextSelectionEnd()
if (text != null) {
if (textSelectionStart > text.length) {
textSelectionStart = text.length
}
if (textSelectionEnd > text.length) {
textSelectionEnd = text.length
}
if (textSelectionStart > textSelectionEnd) {
textSelectionStart = textSelectionEnd
}
}
if (keyEvent.hasSeq()) {
val seq = keyEvent.getSeq()
var newText = ""
if ((textSelectionStart == -1) || (textSelectionEnd == -1)) {
newText = seq
} else {
newText = text.let {
it.substring(0, textSelectionStart) + seq + it.substring(textSelectionStart)
}
}
val arguments = Bundle()
arguments.putCharSequence(
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
newText
)
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
} else {
KeyEventConverter.toAndroidKeyEvent(keyEvent).let { event -> KeyEventConverter.toAndroidKeyEvent(keyEvent).let { event ->
Log.d(logTag, "event $event text $text start $textSelectionStart end $textSelectionEnd") inputConnection.sendKeyEvent(event)
if (isShowingHint) {
this.fakeEditTextForTextStateCalculation?.setText(null)
} else {
this.fakeEditTextForTextStateCalculation?.setText(text)
}
if (textSelectionStart != -1 && textSelectionEnd != -1) {
this.fakeEditTextForTextStateCalculation?.setSelection(
textSelectionStart,
textSelectionEnd
)
}
this.fakeEditTextForTextStateCalculation?.dispatchKeyEvent(event)
this.fakeEditTextForTextStateCalculation?.getText()?.let { newText ->
val arguments = Bundle()
arguments.putCharSequence(
AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
newText.toString()
)
node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
}
}
} }
} }
} }
} }
override fun onAccessibilityEvent(event: AccessibilityEvent) { override fun onAccessibilityEvent(event: AccessibilityEvent) {}
}
override fun onServiceConnected() { override fun onServiceConnected() {
super.onServiceConnected() super.onServiceConnected()
ctx = this ctx = this
fakeEditTextForTextStateCalculation = EditText(this) val info = AccessibilityServiceInfo()
info.flags = FLAG_INPUT_METHOD_EDITOR
setServiceInfo(info)
Log.d(logTag, "onServiceConnected!") Log.d(logTag, "onServiceConnected!")
} }

View File

@ -1,6 +1,5 @@
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowsChanged" android:accessibilityEventTypes="typeWindowsChanged"
android:canRetrieveWindowContent="true"
android:accessibilityFlags="flagDefault" android:accessibilityFlags="flagDefault"
android:notificationTimeout="50" android:notificationTimeout="50"
android:description="@string/accessibility_service_description" android:description="@string/accessibility_service_description"