如何在Android中通过编程解锁屏幕?

30

我正在开发一个基于JUnit的远程自动化Android测试框架(测试在Android外部运行,与其内部代码交互)。它一切正常,但有一个问题,当我自动启动一个新模拟器时,屏幕会一开始就被锁定。这似乎影响了我的测试能否运行,而且我想观察测试运行的情况(按钮点击、文本输入等)。如果我手动启动模拟器并解锁它的屏幕,一切都正常。

有没有办法在Android上以编程方式解锁屏幕?使用Java API、命令行或Shell命令等方法都可以。除此之外,也许有一种方法可以启动一个已解锁的模拟器吗?

7个回答

22

您可以通过其控制台接口与模拟器进行交互。

如果您曾经想知道为什么您的模拟器以像5554这样的数字开头 - 那是因为那是模拟器正在侦听的端口。

您可以使用adb devices命令查找运行模拟器的端口。它将输出类似于此的内容:

C:\>adb devices
List of devices attached
emulator-5554   device

所以你可以使用类似以下命令连接到模拟器:

telnet localhost 5554
如果成功连接,您将获得一个“OK”提示符,并可以开始输入命令。 有各种各样的命令,但我们感兴趣的是用event来模拟硬件事件。我们可以通过按下菜单键来解锁屏幕,使用以下命令进行模拟:
event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0

EV_KEY:KEY_MENU:1 表示按下菜单键,EV_KEY:KEY_MENU:0 表示对应的松开按键事件。请确保两者都有否则菜单键会一直被按下。

我知道编写这个脚本并不容易,但这是我能想到的解决方法。

编辑:我认为 event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0 并不能模拟 Menu 键,但如果我在启动模拟器后立即运行该命令,则可以解锁它。不确定原因,但我想这是一个开始。


1
对我没用。根据http://bit.ly/6QjamY,菜单按钮是KEY_SOFT1而不是KEY_MENU。 - Mirko N.
1
我在我的1.5 AVD上测试了它,似乎工作正常。KEY_SOFT1对你有效吗? - David Webb
在1.6镜像上再次进行测试。使用“event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0”确实可以为我解锁新启动的AVD。但是,如果您再次运行它,它将不会模拟菜单键。不确定它在做什么,但我猜这仍然是解决问题的一种方法。圣诞节后可能会更加深入地研究这个问题。 - David Webb
SOFT1 对我来说显然是菜单,但要解锁屏幕,我需要先按另一个键,比如 HOME,然后再按 SOFT1。尽管如此,它仍然不够可靠,需要进行更多的调查。 - Mirko N.
2
我曾经使用过这个,但我相信我有一个更可靠的解决方案 :) https://dev59.com/ZE7Sa4cB1Zd3GeqP8Pdx - Christopher Orr
我的模拟器似乎不认识 event 命令:未找到命令:event - Drew Stephens

18

在使用 Android SDK r18 和 r20 连接到一个 4.0.3 (API 15) 模拟器时,对我有效的一行代码:

adb shell input keyevent 82

12
我相信下面的链接有你要找的答案。 http://developer.android.com/guide/topics/testing/activity_testing.html#UnlockDevice 解锁模拟器或设备
您可能会发现,如果模拟器或设备的主屏幕被禁用了键盘锁图案,则UI测试无法正常工作。这是因为被测试的应用程序无法接收到通过sendKeys()发送的按键事件。避免此问题的最佳方法是先启动您的模拟器或设备,然后禁用主屏幕的键盘锁。
您还可以显式地禁用键盘锁。要执行此操作,您需要在清单文件(AndroidManifest.xml)中添加权限,然后在待测试的应用程序中禁用键盘锁定。请注意,在发布应用程序之前必须删除此项,或者您必须在发布的应用程序中使用代码禁用它。
要添加权限,请将元素添加为元素的子元素。要禁用KeyGuard,请在要测试的活动的onCreate()方法中添加以下代码:
mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); mLock = mKeyGuardManager.newKeyguardLock("activity_classname"); mLock.disableKeyguard(); 其中activity_classname是活动的类名。

这种情况有很多不好的地方:代码现在已经过时,还需要在测试应用程序的清单中获得许可。以下是可能省略清单中权限的解决方案:https://dev59.com/AGIj5IYBdhLWcg3wy4HH#23223142。然而,这对我来说不起作用-似乎对我来说调试/发布清单没有被注入。 - Boris Strandjev

6

试试这个脚本:

echo "event send EV_KEY:KEY_SOFT1:1" | nc -q1 localhost 5554
sleep 0.1
echo "event send EV_KEY:KEY_SOFT1:0" | nc -q1 localhost 5554
sleep 0.1
echo "event send EV_KEY:KEY_SOFT1:1" | nc -q1 localhost 5554
sleep 0.1
echo "event send EV_KEY:KEY_SOFT1:0" | nc -q1 localhost 5554
sleep 0.1

谢谢!这对我很有用,其他很多方法都没用... 我试过一个和你的类似但只有一行的方法,也没用。+1 - braden
注意:在Oracle Linux 6(基本上是RHEL 6)附带的nc副本中没有-q1选项。我将其删除后,脚本的结果对我来说并没有改变。 - braden
同样适用于macOS,去掉-q1就行了!谢谢 - Snicolas

5

如果屏幕没有密码,最简单的解锁方式是通过传递一个KEYCODE_MENU事件; 但是,如果屏幕已经解锁,这实际上会打开一个菜单,这可能不是您要查找的功能。

如果您想要一种简单的方法来确保屏幕被解锁而不会意外打开菜单,您应该首先传入一个KEYCODE_POWER事件。这将确保设备处于锁定状态,因此菜单事件只会解锁屏幕。

adb shell input keyevent KEYCODE_POWER; adb shell input keyevent KEYCODE_MENU

(注:其他响应中出现的82是KEYCODE_MENU常量。)

4

我使用shell完成了这个操作:

adb shell
#input keyevent 82

对我没用。不确定为什么。我有一个运行1.6的i7500。 - ashes999

0

您可以通过在命令提示符中运行此命令来锁定您的模拟器设备

adb shell input keyevent 26

您可以通过从命令提示符中运行此命令来解锁您的模拟器设备。
adb shell input keyevent 82

运行解锁命令后,您可能需要等待几分钟。 当您没有任何安全锁时,上述解锁命令将起作用。


除了在终端中输入,我如何将它添加到我的Java代码脚本中? - Ranjith Kasu

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