调安卓应用的时候很多人的操作习惯是左手搭在电脑键盘上右手握着鼠标眼睛盯着 Android 模拟器 AVD 的窗口。结果一敲回车没反应按 Backspace 退格退不了想用方向键在列表里挪一格模拟器纹丝不动。更别扭的是想模拟个返回、电源、音量还得把鼠标挪到模拟器右侧那条竖排物理按键上一个个点。这篇文章就聊透两件事电脑键盘的按键怎么被 Android 模拟器 AVD 正确接收以及模拟器上的物理按键侧边栏那几个、以及通过 HID 设备接进来的真实按键怎么被准确触发。内容包括 AVD 配置里那几个真正管键盘的参数、宿主机键位到 Android 按键的映射关系、用 adb 把按键这件事脚本化的完整路子以及我这些年踩过的坑。不管你刚装好模拟器第一次跑 Demo还是已经在写自动化脚本批量点按钮下面的内容都能直接抄。1. 先把问题说清楚敲键盘为什么没反应1.1 三种输入其实是三条完全不同的链路很多人把在模拟器里打字当成一件理所当然的事但它在底层其实分成了三条互不相干的链路任何一条断了表现都是键盘没反应而你得修的地方却完全不同。第一条是宿主机键盘事件到模拟器窗口这一层。电脑上按下的键先被操作系统捕获再交给模拟器进程模拟器进程判定这个键应该映射成 Android 的哪个KEYCODE_xxx。这一层管的是模拟器认不认这块键盘。第二条是Android 系统内部从按键到界面这一层。事件进了 Android 之后要经过输入法框架IME和窗口焦点分发才能落到某个控件上。这一层管的是这个按键应该交给谁。如果你的焦点在一个 EditText 上按键会先被输入法截走看起来像按键没生效其实是生效了但走的不是你以为的那条路。第三条是物理按键与系统按键这一层比如 Power、Volume、Back。这一类按键在 Android 里是系统键由系统的 PhoneWindowManager 之类的组件优先拦截压根不会分发给普通应用。你按对了键位但应用没接收到不代表按键没生效。排查口诀先在模拟器里打开一个纯文本输入框敲字母能出字说明第一层通再按返回看界面退不退能退说明第二层和系统键链路通。两件事分开验证比一上来就翻配置文件高效得多。我见过不少人的键盘失灵其实是第一层就没通AVD 在创建时默认把硬件键盘关掉了模拟器窗口收到的键位事件被直接丢弃所以你敲什么都没反应但鼠标点击完全正常这个特征非常好辨认。1.2 从现象反推三步锁定问题层与其漫无目的地翻配置不如用现象反推。下面这张表是我自己排查时用的顺序基本三步之内能定位到具体哪一层出了问题。现象最可能的原因层优先验证动作敲字母、数字完全无反应鼠标正常宿主机到模拟器检查 AVD 的hw.keyboard是否为yes能敲英文但中文打不出来、候选框不弹Android 输入法框架检查模拟器内是否装了中文输入法并设为当前 IME字母能打退格键、方向键、Esc 无反应键位映射换键盘布局测试看是否被系统快捷键截走返回键能退但应用内监听不到返回系统键分发改用onBackPressed/手势回调或 adb 事件验证侧边栏点 Power 有效adb 发 KEYCODE_POWER 无效屏幕状态机检查屏幕是否已亮、是否被锁屏挡住键盘偶尔灵偶尔不灵焦点/输入法抢占检查当前焦点窗口与 IME 状态这张表里的第二行是最容易被忽略的很多人以为模拟器不支持中文实际上模拟器对中文的支持完全取决于你装没装输入法。AVD 的系统镜像里默认只有一个英文输入法你拿它当然打不出中文。这是另一个话题后面会单独说。第三行的情况在 macOS 上特别多。Mac 的 Command 键被系统拿去做全局快捷键了模拟器的一部分组合键又恰好和系统快捷键撞车于是你按下去是系统响应应用毫无动静。换台 Windows 机器一试就正常很多人因此误判成模拟器在 Mac 上有 Bug。2. AVD 侧的配置让模拟器真正认下硬件键盘2.1 config.ini 里真正管键盘的那几个参数AVD 的所有硬件特性都写在一个叫config.ini的纯文本文件里位置固定在用户目录下的 AVD 目录中。这个文件才是模拟器行为的最终依据图形界面上那些勾选项本质只是这个文件的另一个编辑器。路径分布是这样的Linux / macOS~/.android/avd/你的AVD名字.avd/config.iniWindowsC:\Users\你的用户名\.android\avd\你的AVD名字.avd\config.ini如果你设过ANDROID_AVD_HOME环境变量那就去那个变量指向的目录下找和键盘、物理按键最相关的参数其实就那么几个我整理成了下面这张表后面会逐条说清楚它们的实际效果。参数常用取值实际作用我的建议hw.keyboardyes/no是否存在硬件键盘设备一律设yes这是本文的前提hw.mainKeysyes/no是否有物理主按键Home/Back/Menu建议no把导航交给系统手势或软件导航栏hw.dPadyes/no是否有物理方向键测试遥控器/车机类应用时设yeshw.trackBallyes/no是否有轨迹球基本用不上保持nohw.rotaryInput?—部分新版本支持的旋钮输入按镜像版本决定不确定就别写hw.lcd.width/hw.lcd.height如1080/2400屏幕分辨率改分辨率比改 DPI 更直观hw.lcd.density如420屏幕密度影响布局配合分辨率一起调hw.gpu.enabledyes/no是否启用 GPU 加速建议开启否则动画卡顿影响手感hw.keyboard是这篇文章的主角。它设成no的时候Android 系统会认为这台设备没有物理键盘于是所有来自宿主机键盘的输入事件在框架层就被过滤掉了——注意是认为没有不是驱动坏了。这也解释了一个很典型的现象模拟器里软键盘弹出来你用电脑键盘敲字输入框毫无反应但鼠标点软键盘上的字母就能输进去。因为软键盘走的是触摸事件从头到尾不经过硬件键盘那条链路。改法很直接用文本编辑器打开config.ini找到hw.keyboard这一行改成yes如果没有这一行直接在文件末尾另起一行补上hw.keyboardyes即可。改完必须完整关闭并重启模拟器热重载不生效因为硬件信息是在虚拟机启动时一次性挂载的。2.2 修改配置的两种姿势与生效验证改配置有两条路图形界面和直接编辑文件。图形界面在 AVD 管理器里点编辑找到 Show Advanced Settings 或者类似的高级选项在 Hardware 那一栏里把 Keyboard 的存在与否勾上。这条路适合不想碰文件的人但有个小缺点不同版本的界面文案会有微调找起来费劲。直接改文件这条路我更推荐因为快且可控。下面是完整操作流程以 Linux/macOS 为例# 1. 先确认你的 AVD 名字 emulator -list-avds # 2. 看一眼当前配置里键盘相关项 grep -E hw.keyboard|hw.mainKeys|hw.dPad ~/.android/avd/AVD名字.avd/config.ini # 3. 备份一份再改养成习惯改坏了能一分钟回滚 cp ~/.android/avd/AVD名字.avd/config.ini ~/.android/avd/AVD名字.avd/config.ini.bak # 4. 用 sed 直接改没有这一行就追加 sed -i /hw.keyboard/d ~/.android/avd/AVD名字.avd/config.ini echo hw.keyboardyes ~/.android/avd/AVD名字.avd/config.ini # 5. 从命令行冷启动避开快照恢复带来的旧状态 emulator -avd AVD名字 -no-snapshot-load这里有个细节值得说-no-snapshot-load这个参数不是可有可无的。模拟器默认会从上次的快照快速恢复而快照里保存的是上一台虚拟机的硬件状态你改了 config.ini 但直接快照恢复很可能还是旧配置。我最早折腾的时候就栽在这上面改了三四遍文件以为没生效后来加了冷启动参数一次就好了。验证是否真的生效最靠谱的办法是进系统看设备列表而不是凭手感# 查看 Android 系统识别到的输入设备能看到键盘设备就说明挂载成功了 adb shell dumpsys input | grep -i -A2 keyboard # 更直观的方式抓一下按键事件流按键盘上任意键看有没有输出 adb shell getevent -l第二种方式最直观。getevent -l会把所有输入事件打出来你按一下电脑键盘的 A 键如果终端里刷出一行形如/dev/input/eventX: EV_KEY KEY_A DOWN的内容说明从宿主机到 Android 内核这条链路是通的。如果一片安静那说明事件压根没进内核问题一定在第一层继续回去查hw.keyboard。顺带说一句getevent的输出会非常多触摸屏的坐标事件也在里面刷。想只看按键可以用adb shell getevent -l /dev/input/eventX指定具体设备设备号从adb shell getevent -lp的列表里找列表里会标注设备名和能力位找名字里带 keyboard 的那个就行。2.3 输入法层面的坑软键盘与硬键盘的争夺把hw.keyboard打开之后下一个高频问题来了键盘能打英文字母了但一进输入框软键盘弹出来物理键盘敲字没反应或者反过来物理键盘好用软键盘死活不弹。这属于第二层的问题跟 AVD 配置没关系了是输入法框架在决定要不要用硬件键盘。Android 里有个概念叫硬件键盘的 IME 策略。简单说当一个物理键盘存在时系统会倾向隐藏软键盘因为用户显然有更好的输入方式。这个行为在某些定制界面上表现得很怪比如你点开输入框软键盘不弹光标在那儿闪但打不了中文。排查思路很直接先确认当前激活的输入法是谁。# 列出系统里所有可用的输入法 adb shell ime list -s # 查看当前激活的是哪个 adb shell settings get secure default_input_method # 强制切换某个输入法把包名换成列表里实际的 adb shell ime set com.example.ime/.SomeImeService关于中文输入说个实在话模拟器自带镜像里通常只有一个英文输入法你想要中文就得自己装一个。装完之后记得在设置里切过去或者用上面的命令直接切。这一步做完电脑键盘敲拼音出候选框是正常的不需要额外配置。还有一个反直觉的现象有的人打开了硬件键盘结果软键盘反而不弹了想用鼠标点虚拟按键都没机会。这是因为系统认为你有物理键盘就把软键盘收起来了。解决办法是在系统的语言与输入法设置里找到物理键盘相关选项把显示虚拟键盘打开。不同版本的入口位置不一样一般在设置里的系统 → 语言和输入法 → 物理键盘下面。这个开关不在 AVD 配置里也不在输入法设置里藏得比较深第一次找会花点时间。实操心得如果你做的是需要频繁切换中英文的测试建议在模拟器里装两个输入法一个英文一个中文用 adb 脚本ime set来回切比手动点设置快十倍。写自动化脚本的时候这一步几乎必做因为输入法状态是不确定的一旦跑在中文输入法上input text发英文也会被吃成候选词。3. 宿主机键位到 Android 按键的映射关系3.1 常用映射速查表硬件键盘挂上之后模拟器会按照一套内置规则把宿主机键位翻译成 Android 的按键码。大部分映射是符合直觉的字母键就是字母键回车是KEYCODE_ENTER方向键是四个方向。但也有几个特殊映射不查一下真的想不到。电脑键盘Android 侧效果说明字母 / 数字键对应字符输入最常见直接可用方向键 ↑↓←→D-pad 上下左右列表导航、游戏方向键都靠它Esc返回BACK我个人的高频键比找侧边栏快Home 键回到桌面HOME部分窗口管理器会截走回车确认ENTER输入框内是换行列表里是选中Backspace删除DEL输入框内表现为退格Tab焦点切换表单类测试非常好用Page Up / Page Down上下滚动长列表翻页Ctrl 方向键屏幕横竖旋转部分版本版本差异较大以本机 Help 清单为准Alt Enter全屏切换Windows / Linux 平台Ctrl Shift 某些键截图、快照等辅助功能建议打开模拟器 Help 菜单确认关于最后一行的组合键我要提醒一句模拟器的快捷键在不同版本、不同平台上调整过不止一次。网上流传的很多快捷键大全其实是某个旧版本的东西照着按未必有用。最稳妥的查法是打开模拟器窗口的菜单找 Keyboard Shortcuts有的版本叫 Help → Shortcuts那里列的是你这台机器上这一版的真实映射以它为准。注意如果你看到某个组合键在官方清单里有、自己按了却没反应优先怀疑被宿主机抢了。Windows 的输入法切换、macOS 的 Mission Control、Linux 桌面环境的窗口管理器都会抢占一部分组合键模拟器根本没收到。3.2 组合键、长按与模拟不了的边界这里必须讲清楚一个边界否则你会在这上面浪费大量时间通过宿主键盘直接按出的组合键和真正的多指触摸不是一回事。键盘上的 CtrlA、Shift方向这类组合走的是键盘事件里的修饰键modifier机制Android 侧接收到的是带 metaState 的按键事件应用能正常识别成复制全选按住 Shift 做范围选择。这个没问题。但是像两根手指同时按屏幕的两个位置这种多点触控键盘是模拟不出来的。有些游戏和地图应用需要双指缩放你在电脑上按 Ctrl滚轮模拟器未必映射成缩放按 Ctrl加号减号也未必。真要测双指手势还是老老实实用鼠标操作——模拟器支持按住 Ctrl 或 Alt 再用鼠标点击来产生两只手指具体哪个修饰键取决于版本一般在模拟器设置里能看到提示。长按也是同理。键盘按住一个键不放模拟器确实会连发重复事件但这和触摸屏长按 800 毫秒是两码事。前者是按键重复key repeat后者是触摸手势。如果你的应用逻辑里区分了这两种测试时必须用鼠标按住或者 adb 发手势不能靠键盘按住来凑。至于完全模拟不了的主要是这几类电源键长按呼出关机菜单侧边栏能点键盘映射不了、三指截屏、物理音量键的硬件级耳放触发、以及部分厂商定制的组合键。前者用侧边栏或 adb后者在原生镜像里本来就没有。3.3 跨平台差异Windows、macOS、Linux 各踩一遍同一套 AVD 配置换个宿主机操作系统键盘手感可能完全不一样这点我深有体会。三平台的主要差异点集中在修饰键和全局快捷键冲突上。Windows 上最典型的问题是输入法。中文系统默认开着微软拼音按下 Shift 会切换中英文状态模拟器收到的可能就是一个奇怪的修饰状态你以为是模拟器的问题其实是宿主机输入法在吞键。测试类工作我一般建议临时把宿主机切到英文输入法状态跑完再切回来。macOS 上最典型的是 Command 键。Command 是系统级修饰键很多全局快捷键都绑在它上面模拟器的大部分辅助快捷键在 Mac 上会被换成 Ctrl 或 Cmd 的组合而这个组合恰好又容易和系统功能撞车。如果你发现某个组合键在 Mac 上无论如何都不生效先去系统设置里看快捷键有没有占用它九成是这个原因。Linux 上最典型的是键盘布局。部分发行版默认布局不是美式 QWERTY而是带变体的布局于是你在模拟器里敲出来的字符和键盘上印的对不上比如按 Y 出来 Z。这个问题跟模拟器一点关系都没有是布局层面的错位。查一下当前布局# 查看当前键盘布局 localectl status # 临时切到美式布局验证 setxkbmap usWindows 也有类似的布局问题只是藏得更深。如果你用的是非美式布局比如德语、法语键盘config.ini里还应该显式声明键盘布局否则模拟器按美式来处理特殊符号全乱。相关参数在 config.ini 里通常是hw.keyboard.lid盖子笔记本用和布局相关的条目但更稳的做法是从模拟器启动参数里指定具体参数名以你本机emulator -help的输出为准别照抄网上的旧参数名。我在跨平台切换时养成一个习惯新机器上第一次跑模拟器先花两分钟做三件事——敲字母看能不能出字、按 Esc 看能不能返回、按方向键看列表动不动。三个都过再开始正式调试省得后面把环境问题误判成代码问题。4. 用 adb 把按键这件事脚本化4.1 keyevent 常用键值表前面讲的都是手动按一旦进入自动化或者要精确复现某个操作序列就得切换到 adb 这条线。adb shell input keyevent是最基础也最常用的命令它直接往 Android 的输入系统注入一个按键事件绕过了宿主机和模拟器窗口的映射层所以即使hw.keyboard是no这条命令照样有效。这个特性非常有用它意味着你可以把按键操作和模拟器配置解耦。下面这张表是我日常用得最多的一批键值按使用频率排的。键值常量数值典型用途KEYCODE_HOME3回桌面KEYCODE_BACK4返回新版本会映射成返回手势KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT19/20/21/22焦点移动KEYCODE_DPAD_CENTER23选中当前焦点KEYCODE_VOLUME_UP/VOLUME_DOWN24 / 25音量调节KEYCODE_POWER26电源键点亮/熄灭屏幕KEYCODE_CAMERA27相机快门KEYCODE_A到KEYCODE_Z29 到 54字母输入KEYCODE_0到KEYCODE_97 到 16数字输入KEYCODE_TAB61焦点切换KEYCODE_SPACE62空格KEYCODE_ENTER66确认 / 换行KEYCODE_DEL67退格删除KEYCODE_MENU82菜单KEYCODE_NOTIFICATION83下拉通知栏KEYCODE_SEARCH84搜索KEYCODE_MEDIA_PLAY_PAUSE85媒体播放控制KEYCODE_APP_SWITCH187多任务界面用法有两种写常量或者写数值都行实测效果完全一样# 写法一常量名可读性好推荐 adb shell input keyevent KEYCODE_BACK # 写法二数值脚本里短一些 adb shell input keyevent 4 # 一次发多个键按顺序执行 adb shell input keyevent KEYCODE_HOME KEYCODE_HOME # 长按部分版本支持 --longpress 参数 adb shell input keyevent --longpress KEYCODE_POWER--longpress这个参数值得说一句。它在不同 Android 版本上的支持程度不统一老版本会直接报参数错误。如果报错了用下面的替代方案连着发两次同一个键两次之间间隔很短系统会将其识别为双击或者干脆改用触摸手势的长按后面会讲。我一般不去赌--longpress的兼容性写脚本时优先用更稳的方式。4.2 input text 的转义与中文方案input text是往当前焦点输入框里塞文本的命令看着简单坑却不少。第一次用的人基本都会遇到三个问题空格不见了、特殊字符报错、中文变问号。空格的问题最常见。input text hello world里的空格会被 shell 提前拆开实际传进去的是 helloworld 被当成了额外的命令参数于是只有 hello 进去了。正确写法是用%s表示空格# 错误空格会被 shell 吃掉 adb shell input text hello world # 正确用 %s 代替空格 adb shell input text hello%sworld特殊字符是第二个坑。、、、(、)、|这些在 shell 里有特殊含义直接传会被解释成重定向或子命令轻则报错重则执行了奇怪的命令。稳妥做法是全程加引号并且对 shell 元字符做转义# 输入包含特殊符号的字符串 adb shell input text a\b\(c\)第三个坑就是中文。input text走的是按键注入通道它对非 ASCII 字符的支持非常差实际表现是中文全部丢失或者变成问号。这一点是命令本身的限制不是配置问题改什么参数都没用。那中文怎么自动化输入社区里的成熟做法是装一个专门用于注入文本的输入法这种输入法不显示界面而是通过广播接收待输入的文本再作为输入法自身把文本提交给焦点控件。流程大致是这样在模拟器里安装这个输入法并在设置里把它设为当前输入法脚本里通过广播把待输入的字符串发给它它接收到之后作为 IME 直接提交文本中文、emoji、特殊符号都没问题这个方案的好处是彻底绕开按键通道直接用输入法的提交能力。缺点是得先装东西而且每次跑之前要确认当前 IME 是它否则广播没人接。我的脚本里通常会先ime set一次做保险跑完再切回原来的输入法避免影响后续手工测试。提示如果你的场景只需要输入英文和数字别折腾输入法老老实实用input text加%s就够了稳定性最好。中文自动化再上输入法方案投入产出比才对。还有一个折中办法把文本先写进模拟器里的一个临时文件再用am broadcast或者剪贴板方案粘贴。这个路子适合批量长文本但实现比输入法方案麻烦我只在特殊场景用过。4.3 长按、滑动与连续按键的脚本化单纯发按键只能覆盖一部分场景真实测试里更多是按住不放拖一段距离连续快速点。这些命令都在input下面我把常用的几个整理在一起。# 单击某个坐标 adb shell input tap 540 1200 # 滑动从一点拖到另一点最后是持续时间毫秒 adb shell input swipe 540 1800 540 600 300 # 长按起止点相同持续时间拉长这就是最可靠的长按实现 adb shell input swipe 540 1200 540 1200 1000 # 连续点击 5 次用循环实现两次之间留 100ms for i in $(seq 1 5); do adb shell input tap 540 1200 sleep 0.1 done # 滚动轨迹球部分场景下等同于方向滚动 adb shell input roll 0 3长按那个写法我要重点推荐。input swipe的起止点相同时Android 侧收到的就是按下、保持、抬起三个事件中间的持续时间完全可控落到应用里就是标准的onLongClick或ACTION_DOWN加延时加ACTION_UP。这比赌--longpress参数兼容性可靠太多了我在各种版本的镜像上都验证过行为一致。组合键的脚本化稍微麻烦一点。input keyevent一次只处理一个按键序列如果你的应用需要Shift 按住 按方向键这种真正的组合命令行层面没有直接支持的参数。可行的路子有两条一条是进到 evdev 层直接写事件下一节讲另一条是在应用层想办法比如用测试框架的按键 API 代替 adb。日常测试里需要组合键的场景其实不多大部分是音量上 电源这种系统级组合用侧边栏点两下更快。4.4 getevent 与 sendevent直接操作输入子系统前面所有命令都工作在 Android 框架层。如果框架层的命令满足不了你比如要模拟一个系统根本不认识的按键、要产生原始的多点触控序列那就得下到 Linux 输入子系统这一层。这条路线威力大但也最容易把设备搞乱用之前务必心里有数。第一步是找设备。getevent -lp会列出所有输入设备及其能力位adb shell getevent -lp输出里你会看到一堆/dev/input/eventX每个下面有设备名、支持的按键类型、坐标范围。找名字带 keyboard 的那个记下设备节点。然后抓一次真实按键的事件流看清事件码# 监听指定设备的事件按一下电脑键盘的某个键观察输出 adb shell getevent -l /dev/input/event2 # 典型输出EV_KEY 表示按键事件DOWN/UP 表示按下抬起 # /dev/input/event2: EV_KEY KEY_VOLUMEUP DOWN # /dev/input/event2: EV_SYN SYN_REPORT 00000000 # /dev/input/event2: EV_KEY KEY_VOLUMEUP UP看懂输出之后就能反向注入了。sendevent的格式是设备节点 事件类型 事件码 值注意全部要用十六进制或十进制数值不能用 KEY_VOLUMEUP 这种常量名这是最容易出错的地方。模拟一次音量上键的完整序列# 按下EV_KEY1KEY_VOLUMEUP115值1表示按下 adb shell sendevent /dev/input/event2 1 115 1 # 同步事件EV_SYN0SYN_REPORT0值0 adb shell sendevent /dev/input/event2 0 0 0 # 抬起值0 adb shell sendevent /dev/input/event2 1 115 0 adb shell sendevent /dev/input/event2 0 0 0这套写法有个非常重要的注意点sendevent 不经过输入法也不经过框架的分发逻辑它产生的就是内核层面的事件。好处是能触发一些极其底层的响应坏处是如果你少发了同步事件SYN_REPORT事件会卡在缓冲区里表现就是发了没反应然后过一会儿突然连续生效好几下。我最早写这个脚本的时候漏了同步排查了半天最后对着getevent的输出逐行比对才发现问题。注意sendevent需要 root 权限的镜像普通 Google APIs 镜像里/dev/input/eventX的写权限是受限的。要用这条路线选带 root 的镜像或者用adb root重启 adbd。另外别拿生产设备试手注入错误的事件序列有可能让输入子系统进入奇怪状态重启才能恢复。5. 常见问题与排查实录5.1 现象、原因、动作速查表下面这张表是我这几年攒下来的基本覆盖了九成以上的按键不灵现场。遇到问题先扫一眼能省掉大量盲目试错。现象根因处理动作键盘完全无反应鼠标正常hw.keyboardno改成yes冷启动模拟器改了配置还是没反应从快照恢复硬件未重新挂载加-no-snapshot-load冷启动字母能打退格/方向键无效焦点在输入法或被系统截获换输入框测试切英文输入法中文打不出来镜像里没有中文输入法装输入法并ime set切换软键盘不弹了系统认为有物理键盘设置里打开显示虚拟键盘组合键无反应被宿主机全局快捷键抢占改模拟器快捷键或关掉宿主机占用input text空格丢失shell 分词用%s代替空格input text中文丢失命令不支持非 ASCII换用可注入文本的输入法方案--longpress报错版本不支持该参数改用同点input swipe长按sendevent无反应缺 SYN_REPORT 或多设备节点错补同步事件确认设备节点Mac 上部分键位错乱Command 键被系统占用换 Ctrl 组合或改系统快捷键Linux 上字符对不上键盘布局非 QWERTYlocalectl查看setxkbmap us切换这张表里第一行和第二行的组合是最常见的组合拳很多人改了 config.ini但模拟器是从快照恢复的于是死活不生效然后开始怀疑文件路径写错了、权限不对、版本 Bug一路排查到天荒地老。实际加一个启动参数就好了。5.2 几个印象深刻的现场记录说两个我印象最深的具体案例都是那种看文档看不出来踩过一次就永远忘不掉的类型。第一个案例是模拟器开机后前三十秒键盘正常之后就失灵。这个现象非常迷惑因为它不是完全不工作。排查的过程是这样先用getevent抓事件流发现失灵之后按键事件确实还在往内核送说明宿主机到模拟器这层没问题再看dumpsys input里的焦点窗口发现焦点落到了一个后台的系统窗口上最后定位到是某个开机自启动的应用弹了一个全屏的透明浮层抢走了焦点。按键事件确实被系统收到了只是分发给了一个看不见的窗口。这种情况的教训是没反应有时候不是没收到是收到了给错了人。以后遇到间歇性失灵先看焦点再看事件。第二个案例是用 adb 发 POWER 键屏幕黑了但再也点不亮。这个更麻烦因为按侧边栏的电源键是好的adb 发的就不行。后来搞明白了侧边栏的电源按钮发的是一个更完整的电源状态切换请求而input keyevent KEYCODE_POWER在某些版本上只做了单向下发。解决办法是发两次——第一次灭第二次亮中间加个延时确保状态机切换完成。写成脚本就是adb shell input keyevent KEYCODE_POWER sleep 1 adb shell input keyevent KEYCODE_POWER这个发两次的思路在很多地方都通用。Android 的很多系统键本质是状态切换而不是绝对设置你只发一次状态对不对取决于当前处于什么状态一旦前置状态不确定结果就不确定。写自动化脚本时宁可在前面先归零一次也不要假设当前状态。5.3 提升手感的几个小技巧最后分享几个纯经验性的东西不属于排错但能让日常用模拟器舒服很多。第一把高频操作绑到自己顺手的键上。比如我习惯用 Esc 当返回如果某个版本里 Esc 被改掉了我会去模拟器设置里把它调回来。这件事看起来很小但一天按几百次手感差异非常明显。第二做输入密集型测试时把模拟器的软键盘关掉。软键盘会占据大半个屏幕遮挡界面而且电脑键盘已经能打字了它纯属碍事。关掉之后屏幕利用率立刻上一个档次。开关位置在模拟器的 Extended controls 或者设置里找不到就搜show virtual keyboard。第三用命令行启动模拟器而不是点图标。命令行的好处是可以带参数、可以写成快捷脚本、可以在后台跑。我常用的启动脚本长这样#!/usr/bin/env bash # 冷启动 指定 GPU 模式 放大窗口日常调试够用了 emulator -avd AVD名字 \ -no-snapshot-load \ -gpu auto \ -netdelay none -netspeed full \ -scale 0.8其中-scale控制窗口缩放比例屏幕大的机器上 0.8 左右最舒服既不糊又能一屏放下。-netdelay none -netspeed full是关掉网络模拟避免本地调试时被莫名其妙的延迟干扰。这两个参数用不上可以去掉但-no-snapshot-load建议一直留着能避开大量配置改了不生效的玄学问题。第四如果你的应用需要频繁在横竖屏之间切换别每次都去点旋转按钮用 adb 一条命令搞定还能顺便锁死方向# 关闭自动旋转 adb shell settings put system accelerometer_rotation 0 # 强制横屏1 是竖屏0 是横屏 adb shell settings put system user_rotation 1这套命令的好处是状态确定。点按钮旋转是切到另一个状态发命令是设成指定状态后者在脚本里可重复执行不会因为当前是什么方向而结果不同。这个思路和前面说的先归零再操作是一脉相承的。关于物理按键那一侧我还想补一句现在越来越多的测试场景不再靠模拟器侧边栏而是把真实的 HID 设备比如带按键的耳机、遥控器、扫码枪接到宿主机上让模拟器把宿主机识别到的输入设备透传进去。这条路能测到很多侧边栏按钮测不出的东西比如某些设备特有的按键码、按键长按的时序特性。配置思路上和普通键盘完全一致核心还是hw.keyboardyes加上系统层面能正确枚举设备剩下就是确认你的应用监听的 keyCode 和实际下发的一致用getevent对一遍就知道。
阅读完成 · 觉得有帮助?