深入理解input命令只支持单指,是否可以修改实现多指?-千里马android framework实战开发

Android WMS深度解析:从窗口管理到车机系统实战 在Android系统开发中,窗口管理是构建复杂用户界面的核心技术基础。其核心原理在于通过WindowManagerService(WMS)统一管理系统中的所有窗口(Window),负责窗口的创建、排序(Z-order)、布局以及输入事件分发。这项技术的核心价值在于为应用提供了稳定、高效的显示与交互基础,尤其在多窗口、分屏以及系统级悬浮窗等高级场景中不可或缺。在智能座舱、车机系统等复杂应用场景下,对WMS的深入理解和定制能力直接决定了系统UI的稳定性与表现力。本文聚焦WMS的架构设计与实战,通过剖析窗口类型、 阅读详情

背景:

经常使用的input命令如下:
在这里插入图片描述
正常情况下一般要模拟一个触摸点击事件一般用如下命令
input tap 200 300
执行完成后手机画面一般就会响应一个click事件,这里发现一般都是一个手指,一直寻找看看input命令是否可以支持多个手指通过命令同时按下操作的情况,发现并没有这种多指的触摸的命令。难道确实是不支持吗?

input只支持单指源码分析

源码路径
frameworks/base/cmds/input/src/com/android/commands/input/Input.java

public static void main(String[] args) {
        (new Input()).run(args);
    }

    private void run(String[] args) {
        if (args.length < 1) {
            showUsage();
            return;
        }

        int index = 0;
        String command = args[index];
        int inputSource = InputDevice.SOURCE_UNKNOWN;
        if (SOURCES.containsKey(command)) {
            inputSource = SOURCES.get(command);
            index++;
            command = args[index];
        }
        final int length = args.length - index;

        try {
            if (command.equals("text")) {
                if (length == 2) {
                    inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);
                    sendText(inputSource, args[index+1]);
                    return;
                }
            } else if (command.equals("keyevent")) {
                if (length >= 2) {
                    final boolean longpress = "--longpress".equals(args[index + 1]);
                    final int start = longpress ? index + 2 : index + 1;
                    inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);
                    if (length > start) {
                        for (int i = start; i < length; i++) {
                            int keyCode = KeyEvent.keyCodeFromString(args[i]);
                            if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
                                keyCode = KeyEvent.keyCodeFromString("KEYCODE_" + args[i]);
                            }
                            sendKeyEvent(inputSource, keyCode, longpress);
                        }
                        return;
                    }
                }
            } else if (command.equals("tap")) {//可以看到这里input tap走的是这里
                if (length == 3) {
                    inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
                    sendTap(inputSource, Float.parseFloat(args[index+1]),
                            Float.parseFloat(args[index+2]));
                    return;
                }
            } else if (command.equals("swipe")) {
                int duration = -1;
                inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
                switch (length) {
                    case 6:
                        duration = Integer.parseInt(args[index+5]);
                    case 5:
                        sendSwipe(inputSource,
                                Float.parseFloat(args[index+1]), Float.parseFloat(args[index+2]),
                                Float.parseFloat(args[index+3]), Float.parseFloat(args[index+4]),
                                duration);
                        return;
                }
            } else if (command.equals("draganddrop")) {
                int duration = -1;
                inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
                switch (length) {
                    case 6:
                        duration = Integer.parseInt(args[index+5]);
                    case 5:
                        sendDragAndDrop(inputSource,
                                Float.parseFloat(args[index+1]), Float.parseFloat(args[index+2]),
                                Float.parseFloat(args[index+3]), Float.parseFloat(args[index+4]),
                                duration);
                        return;
                }
            } else if (command.equals("press")) {
                inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
                if (length == 1) {
                    sendTap(inputSource, 0.0f, 0.0f);
                    return;
                }
            } else if (command.equals("roll")) {
                inputSource = getSource(inputSource, InputDevice.SOURCE_TRACKBALL);
                if (length == 3) {
                    sendMove(inputSource, Float.parseFloat(args[index+1]),
                            Float.parseFloat(args[index+2]));
                    return;
                }
            } else {
                System.err.println("Error: Unknown command: " + command);
                showUsage();
                return;
            }
        } catch (NumberFormatException ex) {
        }
        System.err.println(INVALID_ARGUMENTS + command);
        showUsage();
    }

上面代码可以看到最后input tap这个命令最后走入是sendTap方法:

看看这里sendTap

//注意这里传递的参数只有坐标x,y,和一个inputsource,根本没有看到有多个手指的id传入,基本就可以确定这里其实是不支持多指的
   private void sendTap(int inputSource, float x, float y) {
        long now = SystemClock.uptimeMillis();
        injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x, y, 1.0f);
        injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x, y, 0.0f);
    }

明显可以看到其实tap就是注入了2个触摸事件,一个是ACTION_DOWN一个是ACTION_UP,按下抬起就是tap也就是常说的click事件。
在看看injectMotionEvent方法:

   private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
        final float DEFAULT_SIZE = 1.0f;
        final int DEFAULT_META_STATE = 0;
        final float DEFAULT_PRECISION_X = 1.0f;
        final float DEFAULT_PRECISION_Y = 1.0f;
        final int DEFAULT_EDGE_FLAGS = 0;
        //构建出对应的MotionEvent对象
        MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
                DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y,
                getInputDeviceId(inputSource), DEFAULT_EDGE_FLAGS);
        event.setSource(inputSource);
        Log.i(TAG, "injectMotionEvent: " + event);
        //然后在通过inputmanager的相关方法注入这个motionevent
        InputManager.getInstance().injectInputEvent(event,
                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    }

总结:
input tap命令只是进行传递了x,y坐标值,并没有传递多指相关的任何id,所以是不支持的多指的
在这里插入图片描述

input扩展成多指需求设计

目前只支持单指,那么是否可以考虑让input实现多指呢?
其实是完全可以的,因为MotionEvent构造时候完全可以构造成多个手指的这种MotionEvent,然后进行注入,下面就先进行input命令扩展成支持多指的一个命令设计:

考虑设置一个可以多指点击命令项,暂时命名叫做multiple-tap
所以输入命令如下:

input multiple-tap pointId0 x y pointId1 x y …(省略)
命令解释:
multiple-tap --代表多个手指按下点击情况
pointId1 x y --pointId0代表具体手指索引,可以区分不一样手指,一般0开始,x,y代表是触摸事件的坐标位置

更多framework干货请关注“千里马学框架”

Android APK逆向工程实战:从工具链到Smali修改与Frida动态调试 逆向工程是软件安全与开发领域的一项核心技术,它通过分析程序的最终产物来理解其内部逻辑与实现原理。在Android生态中,APK逆向工程尤为关键,其核心目标在于分析应用逻辑、定位关键功能点并进行安全审计。实现这一目标依赖于一套成熟的工具链,例如Apktool用于解码资源与反编译dex文件,Jadx则能将字节码高效还原为可读的Java代码,二者构成了静态分析的基石。这项技术的价值在于,它不仅能帮助开发者学习优秀实现、排查自身应用的安全风险,也是安全研究人员进行漏洞挖掘和恶意软件分析的重要手段。在应用场景上,无论 阅读详情

相关推荐

Android 7系统输入(六)定制安卓系统的输入模块

定制点位置核心代码作用① DOWN/UP 打印ALOGD(...)在源头过滤 MOVE,只打印按下和抬起② 窗口名打印知道事件发给了哪个窗口② 控件名打印知道事件最终被哪个控件消费③ 焦点变更去掉窗口切换时实时输出焦点信息三个定制点覆盖了输入系统从事件产生 → 目标定位 → 焦点管理的完整链路。这些改造不需要深入理解 Android 输入系统的全部细节——只需要知道在哪个文件的哪个函数里加一行日志,就能让原本"静默"的输入系统变得透明可见。

AfinalStone的专栏 241

UniApp安卓原生插件开发指南与实战技巧

原生插件开发是跨平台框架中解决性能瓶颈和功能扩展的关键技术。通过原生代码与JavaScript的桥接,开发者可以突破Web容器的限制,直接调用平台特有API。这种技术特别适用于需要高性能计算或硬件交互的场景,如蓝牙通信、传感器数据采集等。UniApp作为基于Vue.js的跨平台解决方案,其原生插件机制支持Module和Component两种模式,分别对应功能扩展和原生UI嵌入。在实际开发中,合理处理线程通信、内存管理以及性能优化是保证插件质量的重点。本指南详细介绍了从环境搭建到插件发布的完整流程,并提供了蓝

weixin_34116110的博客 418

GSL1680触摸驱动移植实战:从内核ko编译到Android HAL适配

电容式触摸控制器是嵌入式人机交互的核心组件,其驱动需完成坐标上报、多指识别、ESD抗扰等关键功能。GSL1680作为国产早期I²C触控芯片,不支持标准hid-multitouch协议,必须通过定制Linux内核模块(ko)、设备树(DTS)配置与Android HAL层协同实现完整输入链路。技术价值在于打通从硬件中断响应、input子系统注册,到Framework事件分发的全栈路径;典型应用于RK3288/RK3368等ARM平台的工控HMI、车载中控及教育终端。本文聚焦GSL1680驱动移植中的ko编译兼

weixin_29188043的博客 253

【微信小程序】基础篇 -- WXML 模板语法 - 事件绑定 -- tap & input (十)

大家好,又见面了,我是夜阑的狗🐶,本文是专栏【微信小程序开发教程】专栏的第10篇文章;今天开始学习微信小程序的第五天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。【微信小程序开发教程】, 此专栏是我是夜阑的狗微信小程序开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。在一起学习小程序里事件怎么绑定之前,首先先来了解一下什么是事件?事件是渲染层到逻辑层的通讯方式。

JMFive的博客 4524

基因家族的鉴定-基于Windows系统上的HMMER

基因家族的鉴定-基于Windows系统上的HMMER。

liangjinghui123的博客 3247

四旋翼黑科技揭秘:如何利用PX4隐藏的角加速度数据提升控制性能

本文深入探讨了如何利用PX4飞控中隐藏的角加速度数据,结合增量非线性动态逆(INDI)控制方法,显著提升四旋翼无人机的控制性能。通过实战教程,指导开发者从数据订阅、INDI原理到代码实现,构建响应更快、鲁棒性更强的控制回路,有效应对突风与快速机动。

lake5的博客 720

android cmd input tap

Android命令行工具:使用input tap进行屏幕点击 在Android开发过程中,我们经常需要对设备进行自动化测试或模拟用户操作。adb(Android Debug Bridge)是一个强大的命令行工具,它允许我们与Android设备进行交互。其中,input tap命令可以模拟屏幕点击操作,这对于自动化测试和调试...

weixin_36526023的博客 653

OpenEuler内核编译及替换

一、内核源码下载 在gitee上下载OpenEuler内核源码 下载地址 选择需要的内核版本源码压缩包进行下载 二、内核编译 1.解压缩 将下载好的源码进行解压 tar xvf openeuler-kernel-4.19.90-2107.1.0.tar.gz 2.清理源代码树 解压后得到一个名为kernel的内核源码文件夹,进入后执行命令 make mrproper 清理过去内核编译产生的config,第一次编译时可不执行此命令 3.生成内核配置文件.config 先将将系统原配置文件拷贝过来,原

m0_56602092的博客 2万+

小程序input组件事件tap、input、focus、blur触发顺序

  微信小程序表单组件中的input组件应该是很常用的一个组件了,经常用到难免会要用上各种事件,这里说几个最常用的和执行顺序问题,这个没弄清楚很容易出现意料之外的结果。   先来看看这几个事件。tap事件:这个是小程序中的点击事件,绑定语法是bindtap,微信小程序中每个组件都是有tap事件的;input事件:是键盘输入事件,绑定语法是bindinput;focus事件:输入框聚焦事件,绑定语法...

你那里开花了吗 2万+

【鸿蒙游戏上架审核规范指南】

华为鸿蒙游戏上架审核规范指南摘要

weixin_44161102的博客 919

什么是 SAP Fiori 的 Technical Catalog

笔者之前的文章曾经提到一个叫做本文介绍 Technical Catalog 这个概念在 SAP Fiori 技术体系中的作用。首先我们如何在系统里查看这个 Catalog SAP_BASIS_TCR_T 里面包含的内容呢?如果大家照着本文开头那篇文章里提到的步骤,那么在自己系统里会创建好名叫的 PFCG role.我们登录 ABAP 系统,启动事务码 PFCG,打开这个 role, 就能看到它。展开之后,发现它扮演着一个容器的角色,里面包含了很多 ABAP 对象。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 742

appium+python adb shell模拟点击事件(input tap)

前言 此篇文章大部分内容为转载,部分内容本人细化,加工! appium有时候定位一个元素很难定位到,或者说明明定位到这个元素了,却无法点击,这个时候该怎么办呢? 求助大神是没用的,点击不了就是点击不了,appium不是万能的,这个时候应该转换思路,换其它的方法去点击,比如我们可以用adb去执行点击事件 input事件 1.先查看input事件语法有哪些,首先确保手机连上电脑(我这里是电脑上...

xgh1951的博客 9851

数控系统(CNC)系列:Hurco VMX42SR_(11).加工准备流程

在开始使用Hurco VMX42SR进行加工之前,首先需要对机床进行初始设置。这包括机床的水平调整、电源连接和控制系统的基本配置。正确的初始设置是确保加工精度和机床安全运行的前提。

2401_87715305的博客 841

android input命令模拟事件以及事件注入实现

在坐标(500,100)的位置模拟点击事件参数解析:int inputSource:表示模拟事件的类型float x, float y:表示事件坐标点int displayId:在哪个屏幕上触发事件(一般用于多屏)

yimelancholy的博客 2922

从码农到生态建造者:我的一人公司运作方案

华哥·OPC 运营方案 v1.0 - 第一次迭代 🚀,搭建闭环生态系统,赋能 AI 时代的超级个体,更好的做自己,同时照亮别人。

AaronZZH 的博客 995

基于YOLOv8的人群聚集检测系统:含UI界面设计与数据集应用

人群聚集检测是智慧城市、公共安全和疫情防控等领域的重要任务。本文结合YOLOv8最新目标检测技术,设计并实现了一个高效的人群聚集检测系统,支持可视化UI界面操作,方便用户实时检测和分析视频中的人群密度。本文详细介绍了系统设计思路、使用的数据集、YOLOv8模型训练和推理过程,以及UI界面的开发与整合。最后通过实验验证了该系统的实用性和性能表现。更灵活的模型架构强化的特征融合网络(PAN++)自动混合精度训练支持支持多任务学习(目标检测+分类+分割)预训练模型丰富,适应多种应用场景。

YOLO 433

嵌入式Linux与安卓驱动开发实战:从内核到HAL完整项目

嵌入式Linux驱动开发是智能硬件、车载系统等领域的关键技术,涉及内核裁剪、设备树配置、字符设备驱动及总线操作。其核心原理在于通过设备树解耦硬件与驱动,利用file_operations实现用户空间与内核交互,并借助GPIO/I2C/SPI等总线控制外设。掌握这些技术能显著提升底层问题定位能力,应用于工业控制、消费电子等场景。安卓HAL层进一步将驱动能力暴露给应用,打通从内核到框架的完整链路。本项目以实战为导向,覆盖环境搭建、驱动编写、HAL对接及调试技巧,帮助开发者系统掌握嵌入式Linux与安卓驱动开发。

weixin_34005042的博客 461

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android系统定制实战指南:Magisk模块架构深度解析与开发实践

Magisk作为Android系统的"魔法面具",通过创新的挂载机制实现了对系统文件的无侵入式修改。本文深入解析Magisk模块的架构设计、核心工作原理,并提供从基础到高级的模块开发实战指南。无论你是希望定制系统功能、添加命令行工具,还是实现应用行为修改,掌握Magisk模块开发都能为你的Android定制之旅打开全新的大门。 ## 传统Root方案 vs Magisk模块化架构 在深入技术细

gitblog_01094的博客 777

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Relay Store 命令式数据修改指南:深入理解 Relay 18 的 updater 函数与 RecordSourceSelectorProxy

本文以 Relay(relay29/relay 仓库)v18 官方文档为主线,系统讲解如何在 updater 函数中**命令式(imperatively)修改 Relay Store**:包括 `optimisticUpdater` / `updater` 的使用时机、多乐观响应并发时的行为差异、`RecordSourceSelectorProxy` 的完整读写 API,以及通过 `Connect

gitblog_00268的博客 153

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

嵌入式Linux与安卓驱动开发实战:从内核模块到HAL层对接

嵌入式Linux驱动开发涉及交叉编译、内核模块、设备树、字符设备及GPIO/I2C子系统等核心技术。其原理在于通过内核抽象层管理硬件资源,实现驱动与硬件的解耦,提升可移植性与稳定性。掌握这些技术能显著增强系统级调试与优化能力,广泛应用于智能硬件、车机、IoT等领域。安卓HAL层作为驱动与框架的桥梁,进一步扩展了驱动工程师的就业场景。本文聚焦驱动开发全链路,涵盖环境搭建、设备树配置、驱动编写及HAL对接,帮助开发者从应用层转向底层,积累真实项目经验。

weixin_34408624的博客 332

Android输入子系统全解析:从硬件到App的事件分发链路

在Android系统开发中,触摸失灵、按键错乱等输入问题往往源于对事件链路缺乏整体认知。理解输入子系统工作原理,需从内核input_event协议出发,掌握EventHub的设备监听与事件读取机制,以及InputReader如何完成坐标变换与语义解析。进一步,InputDispatcher基于队列模型实现窗口级事件派发,并与ANR机制紧密相关。在应用层,dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三者协作决定事件消费路径。通过getevent、d

weixin_34239592的博客 255

MediaPipe实战:跨平台实时媒体处理的完整开发指南

还在为多平台机器学习应用开发而头疼吗?面对Android、iOS、桌面端和Web端的不同技术栈,想要实现统一的实时媒体处理功能往往需要重复造轮子。MediaPipe正是为解决这一痛点而生,它提供了一套完整的跨平台机器学习解决方案框架,让你能够一次性构建,多端部署。本文将带你深入理解MediaPipe的核心机制,掌握从基础配置到高级优化的完整开发流程。 ## 为什么选择MediaPipe?解决跨平

gitblog_00603的博客 411

Windows 7环境下Android APK逆向工程实战:从IDA Pro静态分析到动态调试

逆向工程是理解软件内部工作原理、进行安全评估的核心技术,它通过分析程序的二进制代码来揭示其逻辑结构与数据流。其基本原理包括静态反汇编、动态调试和代码重构,能够帮助开发者深入理解系统机制、发现潜在漏洞。在移动应用安全领域,这项技术的价值尤为突出,可用于评估应用的安全性、分析第三方库行为,以及进行合法的漏洞挖掘。典型的应用场景包括移动应用安全审计、恶意软件分析和软件兼容性研究。本文聚焦于Android平台,详细演示了在Windows 7系统中,如何搭建包含IDA Pro、Android逆向助手和雷电模拟器的完整

weixin_30394981的博客 405

APK Installer 完整指南:3 步在 Windows 上装好安卓应用

APK Installer 是一款 Windows 平台的安卓应用安装器:把 .apk 文件拖进窗口,它会立刻报出应用名、版本号和完整权限清单,再让你一键装进系统自带的安卓子系统(WSA),或直接推到安卓真机上。不用模拟器,不用敲 adb 命令。这篇文章带你从零走完"装好 APK Installer → 装上第一个安卓应用 → 推送到手机"全程,全程只有拖拽和点击。 ## 先搞清楚:APK In

gitblog_00753的博客 418

ER-Save-Editor:改艾尔登法环存档的桌面工具,从 8 项属性到整箱仓库 5 步跑通

ER-Save-Editor 是一款用 Rust 编写的艾尔登法环(Elden Ring)存档修改工具,桌面 GUI 操作,兼容 PC 的 .sl2 存档与 PlayStation 经 Save Wizard 导出的存档。改属性、塞仓库、装备换护符、复活 BOSS、跨存档导入角色都在这一个程序里完成。修改前务必备份原存档,线上使用风险自担。 ## 1|快速上手:从克隆仓库到打开第一个存档 本章

gitblog_00942的博客 719
上一篇: hal/SurfaceFlinger/perfetto实战需求问题探讨作业-千里马framework开发
下一篇: android input命令支持多指触摸成果展示-千里马framework实战开发
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值