【按键精灵安卓版小精灵进程守护-崩溃自启中(原理篇·下)】安卓版按键小精灵崩溃自启插件兼容不同系统在游戏场景和非游戏场景下的自启,源码分享。


前言

接着【按键精灵安卓版小精灵进程守护-崩溃自启中(原理篇·上)】博客的内容继续往下,要看懂本篇博客需要先阅读上篇内容。
在上篇内容中,通过使用shell脚本来创建后台进程。持续同按键小精灵进行通信,模拟服务器-客户端心跳验证。当验证失败时由shell脚本程序通过重启特定包名的按键小精灵程序,然后再通过shell命令input tap发送点击命令。
但是在上篇博客结尾抛出了一个问题,那就是shell命令input tap在游戏GUI界面时出现点击偏差的问题,导致在点击启动按钮时不受控制。为此需要增强按键小精灵守护插件,那么本篇博客便是解决方案!!!


一、了解几个重要的Android命令

下述解析由文心一言生成整理

1.getevent——事件查看捕获

  • 指令:getevent

  • 功能:getevent 是一个在Linux系统(尤其是Android设备的Linux内核)中用于接收和打印从输入设备(如触摸屏、键盘、鼠标等)发送的事件的工具。这对于开发者在调试输入设备时非常有用,因为它可以实时显示设备的输入事件。

  • 用法:getevent [选项] [设备文件]

  • 设备文件:这通常是输入设备在 /dev/input 目录下的设备文件,例如 /dev/input/eventX,其中 X 是一个数字,代表特定的输入设备。

  • 示例:
    getevent:不指定设备文件时,将不会显示任何事件,因为它不知道要监听哪个设备。
    getevent /dev/input/event0:实时显示/dev/input/event0设备上发生的所有输入事件。这将显示每个事件的详细信息,包括时间戳、事件类型、代码和值。
    getevent -l /dev/input/event0:除了显示事件的详细信息外,-l 选项还会列出与事件相关联的详细名称(如果可用),这有助于识别特定的事件。

  • 注意:
    你需要具有适当的权限(通常是root权限)来访问 /dev/input 目录下的设备文件。
    不是所有的设备都会产生易于理解的事件。某些设备的输出可能需要专门的知识来解读。
    对于Android设备,由于它们通常具有安全机制来限制对 /dev/input 目录的访问,因此可能需要通过root shell或使用具有相应权限的ADB shell来运行 getevent。

  • 选项:
    -l:显示长列表,包括事件的详细名称(如果可用)。
    -p:显示设备的信息,而不是实际的事件流。
    -s:打印同步事件。
    -n:在事件前面添加行号。
    -t:打印时间戳。
    -i:仅打印事件的类型代码和值。
    -r:读取文件描述符(而非标准输入)来捕获事件。
    -c:显示所有事件的详细信息,类似于 -l 但可能包含更多细节。

2.sendevent——底层事件模拟

  • 功能: sendevent 在 Android 系统中是一个用于向设备发送输入事件的工具,比如模拟按键按下、释放,或者模拟触摸屏上的触摸和移动等。

  • 用法(在 Android 设备上,通常需要 root 权限): sendevent [设备] [类型] [代码] [值]
    设备:通常是 /dev/input/eventX,其中 X 是一个数字,代表具体的输入设备。
    类型:事件的类型,如 EV_KEY(按键事件)、EV_ABS(绝对位置事件,如触摸屏)。
    代码:具体的事件代码,比如 KEY_POWER 表示电源键。
    :事件的值,对于按键事件,通常是 1(按下)和 0(释放)。

  • 示例(假设):
    模拟电源键按下和释放(注意:这只是一个示例,实际命令可能因设备和 Android 版本而异):

sendevent /dev/input/eventX 1 116 1
#这里,116 是 KEY_POWER 的代码,1 表示按键被按下。
sendevent /dev/input/eventX 1 116 0
#eventX 需要替换为实际负责该输入事件的设备
  • 注意:
    在 Android 设备上使用 sendevent 需要 root 权限。
    具体的设备文件(如 /dev/input/eventX)和事件代码(如 116)可能因设备和 Android 版本的不同而有所变化。
    由于 sendevent 不是 Linux 通用命令,因此它在标准的 Linux 发行版(如 Ubuntu、Fedora 等)中不可用。
    如果你是在询问 Linux 系统中与发送事件相关的其他命令或工具,请提供更具体的上下文或需求。例如,在 Linux 桌面环境中,可以使用 xdotool 或 xte 等工具来模拟键盘和鼠标操作。

二、逻辑解析

整体逻辑分为四步:
获取负责tap事件的输入设备 —— 获取点击事件的输入事件序列 —— 获取物理分辨率和设备输入分辨率的映射关系 —— 组合形成自定义底层点击函数

1.获取设备名称

第一步需要通过命令getevent查看具体是哪个输入设备负责tap事件的输入:

  1. 使用mt管理器打开**/dev/input**目录查看你的event设备的数目
    在这里插入图片描述
  2. 依次使用命令getevent -lp /dev/input/eventX | grep "ABS_MT_POSITION_X"来查看是否有输出,如果有输出则次eventX就是负责tap事件输入的设备。需要注意针对于上图X代表0-3。
    指令解析:这个命令组合用于从指定的输入设备(如触摸屏)中捕获事件,并通过管道(|)将这些事件传递给grep命令以过滤出与触摸屏上多点触控(Multi-Touch)中X轴位置(ABS_MT_POSITION_X)相关的事件。getevent是一个用于监视和打印从输入设备(如键盘、鼠标、触摸屏等)接收到的事件的工具,而grep则用于搜索包含指定模式的行。
  3. 依次监测event设备,出现下图说明找到。图中模拟器负责tap事件的设备为event2
    在这里插入图片描述

2.获取tap事件序列

指令:getevent -t -c 30 /dev/input/event2
指令解析:getevent命令在Linux系统中用于从指定的输入设备(如触摸屏、按键、鼠标等)捕获和打印事件。这对于调试和测试输入设备的行为非常有用。-t选项让getevent以时间戳形式显示事件,-c 30选项设置一次从设备读取的事件数量限制。/dev/input/event2指定了要读取事件的具体输入设备文件。

首先在命令输入getevent -t -c 30 /dev/input/event2后回车,随便点击屏幕某个地方便会有一系列的输入序列生成,我们需要提取到完整的一次点击的输入序列。
在这里插入图片描述
我这里仅仅展示了一次点击,多次点击可以更好判断一次完整的点击事件序列。

[    1285.819243] 0003 0039 00000016
[    1285.819243] 0001 014a 00000001
[    1285.819243] 0003 0035 000004f7
[    1285.819243] 0003 0036 000000e4
[    1285.819243] 0000 0000 00000000
[    1285.920969] 0003 0039 ffffffff
[    1285.920969] 0001 014a 00000000
[    1285.920969] 0000 0000 00000000

其中对我们有用的为0003 0035 000004f70003 0036 000000e4
其中0003表示触摸事件
0035H表示ABS_MT_POSITION_X
0036H表示ABS_MT_POSITION_Y
我们需要做的就是构建输入序列,修改x,y坐标的值即可完成。

3.获取映射关系

先明确两个概念:物理分辨率输入设备分辨率
这两个是我个人这样说的,对于专业的是否是这样说我不是很清楚。当然我们也不需要做到那么专业,只需要明确缘由用法即可。
物理分辨率:顾名思义,这是我们的手机设备固有的硬件分辨率。常说的手机分辨率便是指这个,坐标原点位于左上角(0,0)。
输入设备分辨率:这个是负责输入设备中的一个属性,可以通过命令查看。一般这个分辨率应该是和物理分辨率一致,但也有例外。同样的坐标原点位于左上角(0,0)。
如何获取这两个分辨率呢?
命令:wm size [获取设备物理分辨率]
命令:getevent -lp | awk -F 'max' '/ABS_MT_POSITION_X/{print $2} [获取ABS_MT_POSITION_X属性最大值]
命令:getevent -lp | awk -F 'max' '/ABS_MT_POSITION_Y/{print $2} [获取ABS_MT_POSITION_Y属性最大值]
在这里插入图片描述
从图中可以知道
物理分辨率:720X1280
输入设备分辨率:1279X719
需要注意,程序使用的统一是物理分辨率
因此我们要点击屏幕上(200,200)的坐标时,需要将它映射到输入设备的坐标轴上。这个坐标转换我这里就不说,如果这个搞不来就别编程了,趁早转行!

4.自定义底层点击

这一步主要是测试用的,通过序列形成点击函数
需要注意捕获的输入序列均是十六进制,而我们编写的时候用的是10进制

Function SendTap(deviceName, intx , inty)
	zm.Execute "sendevent " & deviceName & " 3 57 1"
	zm.Execute "sendevent " & deviceName & " 1 330 1"
	zm.Execute "sendevent " & deviceName & " 3 53 " & intx
	zm.Execute "sendevent " & deviceName & " 3 54 " & inty
	zm.Execute "sendevent " & deviceName & " 0 0 0"
	zm.Execute "sendevent " & deviceName & " 3 57 4294967295"
	zm.Execute "sendevent " & deviceName & " 1 330 0"
	zm.Execute "sendevent " & deviceName & " 0 0 0"
End Function

dim deviceName = "/dev/input/event2"
Dim intx = 890
Dim inty = 716
call SendTap(deviceName, intx , inty)

三、代码实现

1.设备获取

deviceName=
# 循环遍历 /dev/input/eventX 设备
for deviceName in /dev/input/event*; do
    # 使用 getevent -lp 命令获取设备信息,并筛选包含 ABS_MT_POSITION_X 的行
    info=$(getevent -lp "$deviceName" | grep "ABS_MT_POSITION_X")

    # 判断是否有输出,如果有则表示设备具有 ABS_MT_POSITION_X 输入属性
    if [ -n "$info" ]; then
        echo "设备 $deviceName 具有 ABS_MT_POSITION_X 输入属性"
        break  # 找到第一个设备后跳出循环
    fi
done

2.分辨率获取

# 定义全局变量
absWidth=$(getevent -lp | awk -F 'max' '/ABS_MT_POSITION_X/{print $2}' | awk '{print $1}' | sed 's/,//')
absHeight=$(getevent -lp | awk -F 'max' '/ABS_MT_POSITION_Y/{print $2}' | awk '{print $1}' | sed 's/,//')

size=$(wm size | awk '{print $3}')
width=$(echo $size | cut -d "x" -f1)
height=$(echo $size | cut -d "x" -f2)

3.封装模拟点击函数

send_tap() {
    # 检查参数是否提供
    if [ $# -lt 2 ]; then
        echo "Usage: send_tap <input_x> <input_y>"
        return 1
    fi
    input_x="$1"
    input_y="$2"

    # 计算点击位置
    x_value=$((input_x * absWidth / width))
    y_value=$((input_y * absHeight / height))

    # 调用第一层封装的函数 send_event
    sendevent "$deviceName" 3 57 1
    sendevent "$deviceName" 1 330 1 
    sendevent "$deviceName" 3 53 "$x_value"
    sendevent "$deviceName" 3 54 "$y_value"
    sendevent "$deviceName" 0 0 0
    sendevent "$deviceName" 3 57 4294967295
    sendevent "$deviceName" 1 330 0
    sendevent "$deviceName" 0 0 0
}

到这里整个增强版原理就讲解完成,主要就是处理底层模拟输入适配游戏GUI。究其原因是因为游戏层级GUI会重合,是分层的,而input tap只能输入当前层级。


源码+视频

非常感谢各位的阅读,如果对你有帮助还请给个赞吧!
源码+视频获取:戳我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值