通过NativeActivity获取InputQueue对象
private fun getField(cls: Class<*>, str: String): Field? { // 传入Activity Class
var mCls: Class<*>? = cls
try {
return mCls?.getField(str)
} catch (e: NoSuchFieldException) {
while (true) {
try {
val field = mCls?.getDeclaredField(str)?.apply {
isAccessible = true
}
return field
} catch (unused: NoSuchFieldException) {
e.printStackTrace()
mCls = mCls?.superclass
if (mCls == null) {
return null
}
}
}
}
}
val field = getField(activity.javaClass, "mCurInputQueue")
反射执行InputQueue的sendInputEvent方法
inputQueue.javaClass.methods.forEach { method ->
if(method.name == "sendInputEvent") {
method.isAccessible = true
method.invoke(inputQueue, event, 0, false, inputEventCallback)
}
}
// 构建inputEventCallback
private fun getInputEventCallback(obj: Any): Any? {
try {
return Proxy.newProxyInstance(
obj.javaClass.classLoader,
arrayOf<Class<*>>(Class.forName("android.view.InputQueue\$FinishedInputEventCallback"))
) { _, _, _ -> null }
} catch (e: Exception) {
Log.d("dqs", ">>>>>>>>>>>>>>> ${Log.getStackTraceString(e)}")
return null
}
}
// 不同情况完整示例
GmLifecycleUtils.getTopActivity()?.let { activity ->
if (activity is NativeActivity) {
val field = getField(activity.javaClass, "mCurInputQueue")
val inputEventCallback = getInputEventCallback(activity)
if (field != null) {
val inputQueue = field.get(activity)
inputQueue.javaClass.methods.forEach { method ->
if(method.name == "sendInputEvent") {
method.isAccessible = true
method.invoke(inputQueue, event, 0, false, inputEventCallback)
}
}
} else {
}
} else {
activity.window?.decorView?.apply {
dispatchTouchEvent(event)
}
}
}