如标题,在某些较大的游戏应用中,会限制鼠标点击不生效,导致我们的鼠标在系统其他应用上都能使用,就是某个游戏应用无法点击。调试发现,触摸事件不受影响,那么我们可以在当前游戏应用中,点击的时候模拟一下触摸点击,查看是否生效。安卓有一个触摸命令input tap x y,通过试验发现该触摸命令可以生效,那么我们可以在游戏应用界面,点击鼠标时发送一次input命令模拟触摸点击,从而解决在游戏界面鼠标点击不生效的问题。话不多说,直接上代码
framework/base/core/java/android/view/ViewRootImpl.java
private static final boolean DEBUG_BLAST = false || LOCAL_LOGV;+ private static final String PACKAGE_NAME = "com.Vishee.Cycling2";+ static boolean JUST_CLICK_ONCE = true;public final void deliver(QueuedInputEvent q) {if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {+//final List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1);+//if(tasks.get(0).topActivity.getPackageName().equals(PACKAGE_NAME)){+String appName = ActivityThread.currentOpPackageName();+if(appName.equals(PACKAGE_NAME)){+ final MotionEvent event = (MotionEvent)q.mEvent;+ final int action = event.getAction();+ //Log.d(TAG,"appName="+appName+" x="+event.getX()+" y="+event.getY());+ if(action == MotionEvent.ACTION_DOWN){+ if(JUST_CLICK_ONCE) {+ event.setTouchInstruct(event.getX(),event.getY());+ JUST_CLICK_ONCE = false;+ }else{+ JUST_CLICK_ONCE = true;+ }+ }+}forward(q);} else if (shouldDropInputEvent(q)) {finish(q, false);} else {traceEvent(q, Trace.TRACE_TAG_VIEW);final int result;try {result = onProcess(q);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}apply(q, result);}}
通过打日志发现该游戏apk是在deliver函数里的mflag判断一直为FLAG_FINISHED,未进入到onProcess函数,导致一直点击无效。添加的代码的目的是在进入FLAG_FINISHED后,判断当前包名是否为该游戏应用,通过ActivityThread.currentOpPackageName()获取包名,android12的tasks.get(0).topActivity.getPackageName()方法获取包名会报错,在android11上用tasks获取包名没问题,这一块我还没看懂,有明白的朋友麻烦跟我说一下。
判断当前应用为我们的游戏应用后,判断当前action是否为鼠标点击ACTION_DOWN事件,然后执行setTouchInstruct方法模拟一次触摸事件。JUST_CLICK_ONCE是因为一次点击会有两次ACTION_DOWN事件,所以需要JUST_CLICK_ONCE过滤一次ACTION_DOWN,否则一次点击会执行两次触摸。setTouchInstruct方法添加代码如下
framework/base/core/java/android/view/MotionEvent.java
+import java.lang.Runtime;+import java.lang.Process;+ /** @hide */+ public void setTouchInstruct(float x,float y){+ try{+ Log.d(TAG,"setTouchInstruct x="+x+" y="+y);+ String[] commands = { "bin/sh", "-c","input tap "+Float.toString(x)+" "+Float.toString(y)};+ Process process = Runtime.getRuntime().exec(commands);+}catch(Exception e){+ e.printStackTrace();+}+ }
至此,实现了某些游戏应用鼠标点击无效的问题。