如何在仪器化测试中向无头模拟器发送按键事件?

8
我们目前正在开发一套仪器测试套件,该套件在我们的构建服务器上运行。但是,虽然使用普通的Android模拟器在开发机上测试通过,但由于我们在构建服务器上只运行一个带有-no-window标志的无头模拟器,因此构建失败。
当尝试调用InstrumentationTestCase.sendKeys()方法以编程方式打开选项菜单时,会发生错误。错误如下:

Permission denied: injecting key event from pid 646 uid 10026 to window Window{43d55100 paused=false} owned by uid 1000

我们后来发现有一个INJECT_EVENTS权限,但在清单中设置它没有效果。实际上,在日志中我们看到了这个输出:

Not granting permission android.permission.INJECT_EVENTS to package com.qype.radar (protectionLevel=2 flags=0x6644)

这是否意味着这个权限是无用的?
我们还尝试让测试应用程序和被测试的应用程序共享相同的Linux用户ID,并在同一进程中运行(android:process - 我们不确定是否已经是这种情况),但仍然没有成功。
这是否意味着目前无法在无头模拟器上运行包含按键事件的仪器测试,或者我们遗漏了什么?

2
“INJECT_EVENTS”是一个完全有效的权限,但只能由固件持有,而不是SDK应用程序。 - CommonsWare
糟糕,那我们最好的选择是什么?谷歌没有考虑在构建服务器上运行测试吗? - mxk
我刚刚使用 -wipe-data 标志重新启动了模拟器,然后构建成功了一次,但模拟器崩溃了,我又重新启动了它,现在构建再次失败了……这一切都很不稳定 :-( - mxk
2个回答

17

我在无头机器上运行模拟器时,首先启动一个Xvnc实例(即虚假的X服务器),然后在该DISPLAY中启动模拟器,而不使用-no-window选项。

更准确地说,我使用Xvnc插件Android模拟器 Jenkins插件来完成这个过程。

不幸的是,在注入UI事件之前解锁屏幕仍然是一个问题,但通过自动运行像这样的命令(类似于这个答案中提到的其他方法)可以解决这个问题:
echo "event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0" | nc -q1 localhost 5554


编辑:
我发现这种方法更可靠:
adb shell input keyevent 82

关于按键代码82的一些信息


这听起来非常有趣,我们会去看看的,谢谢! - mxk

1

嘿,太好了,我们怎么会错过这个呢?我们认为问题实际上是键盘锁 - 它阻止了sendKeys()的正确工作。 - mxk
3
解决方案是什么?那个部分已经从页面中删除了 :( - Thierry Roy
1
如果我没记错的话,解决方案是通过编程方式禁用键盘锁,因为它会在每次模拟器/手机启动后激活。看一下这个片段:http://pastebin.com/v0deQGpT 当然,你会想从生产应用程序中删除这段代码;它会永久禁用键盘锁,直到下一次启动。 - mxk
1
仅供记录,Christopher的答案更好,因为它不需要这个hack。据我所知,Hudson/Jenkins的Android插件也会自动为您禁用键盘锁定。 - mxk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接