当使用MonkeyRunner,每隔一段时间,我得到这样的错误:
120830 18:39:32.755:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice] Unable to get variable: display.density
120830 18:39:32.755:S [MainThread] [com.android.chimpchat.adb.AdbChimpDevice]java.net.SocketException: Connection reset
从我读过的东西,有时ADB连接变坏,你需要重新连接。 唯一的问题是,我没能赶上SocketException
。 我会换,像这样我的代码:
try:
density = self.device.getProperty('display.density')
except:
print 'This will never print.'
但例外显然不会引发一路给调用者。 我已验证MonkeyRunner / Jython会赶上Java异常我所希望的方式:
>>> from java.io import FileInputStream
>>> def test_java_exceptions():
... try:
... FileInputStream('bad mojo')
... except:
... print 'Caught it!'
...
>>> test_java_exceptions()
Caught it!
我该如何处理这些插座例外?
你会得到这个错误每个奇数一次启动MonkeyRunner因为monkey --port 12345
脚本停止时在设备上的命令不会停止。 这是猴子的错误。
在解决这个问题一个更好的办法是杀猴SIGINT
被发送到你的脚本(当你ctrl+c
)。 换句话说: $ killall com.android.commands.monkey
。
快速的方法来做到这一点:
from sys, signal
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = None
def execute():
device = MonkeyRunner.waitForConnection()
# your code
def exitGracefully(self, signum, frame):
signal.signal(signal.SIGINT, signal.getsignal(signal.SIGINT))
device.shell('killall com.android.commands.monkey')
sys.exit(1)
if __name__ == '__main__'
signal.signal(signal.SIGINT, exitGracefully)
execute()
编辑:作为附录,我也找到了一种方法注意到了Java错误: 猴子赛跑者touuch抛出异常插座水管坏了
下面是我最终使用的解决方法。 可以从亚行的失败遭受任何功能只需要使用下面的装饰:
from subprocess import call, PIPE, Popen
from time import sleep
def check_connection(f):
"""
adb is unstable and cannot be trusted. When there's a problem, a
SocketException will be thrown, but caught internally by MonkeyRunner
and simply logged. As a hacky solution, this checks if the stderr log
grows after f is called (a false positive isn't going to cause any harm).
If so, the connection will be repaired and the decorated function/method
will be called again.
Make sure that stderr is redirected at the command line to the file
specified by config.STDERR. Also, this decorator will only work for
functions/methods that take a Device object as the first argument.
"""
def wrapper(*args, **kwargs):
while True:
cmd = "wc -l %s | awk '{print $1}'" % config.STDERR
p = Popen(cmd, shell=True, stdout=PIPE)
(line_count_pre, stderr) = p.communicate()
line_count_pre = line_count_pre.strip()
f(*args, **kwargs)
p = Popen(cmd, shell=True, stdout=PIPE)
(line_count_post, stderr) = p.communicate()
line_count_post = line_count_post.strip()
if line_count_pre == line_count_post:
# the connection was fine
break
print 'Connection error. Restarting adb...'
sleep(1)
call('adb kill-server', shell=True)
call('adb start-server', shell=True)
args[0].connection = MonkeyRunner.waitForConnection()
return wrapper
因为这可能会创建一个新的连接,你需要这样它可以改变包装的设备对象的当前连接。 这是我的设备类(大多数类是为了方便,这是必要的唯一的事情就是connection
件:
class Device:
def __init__(self):
self.connection = MonkeyRunner.waitForConnection()
self.width = int(self.connection.getProperty('display.width'))
self.height = int(self.connection.getProperty('display.height'))
self.model = self.connection.getProperty('build.model')
def touch(self, x, y, press=MonkeyDevice.DOWN_AND_UP):
self.connection.touch(x, y, press)
关于如何使用装饰的一个例子:
@check_connection
def screenshot(device, filename):
screen = device.connection.takeSnapshot()
screen.writeToFile(filename + '.png', 'png')