How to catch SocketExceptions in MonkeyRunner?

When using MonkeyRunner, each error so often occurs, for example:

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 

From what I read, sometimes the adb connection gets worse and you need to reconnect. The only problem: I cannot catch a SocketException . I will end my code like this:

 try: density = self.device.getProperty('display.density') except: print 'This will never print.' 

But the exception, apparently, does not reach the caller. I checked that MonkeyRunner / jython can catch Java exceptions as I expected:

 >>> from java.io import FileInputStream >>> def test_java_exceptions(): ... try: ... FileInputStream('bad mojo') ... except: ... print 'Caught it!' ... >>> test_java_exceptions() Caught it! 

How can I handle these socket exceptions?

+6
source share
2 answers

Below is the workaround I used. Any function that might suffer from adb crashes should just use the following decorator:

 from subprocess import call, PIPE, Popen from time import sleep def check_connection(f): """ adb is unstable and cannot be trusted. When there 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 

Since this can create a new connection, you need to wrap your current connection in the Device object so that it can be changed. Here is my device class (most classes are for convenience, the only thing needed is a connection member:

 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) 

An example of using a decorator:

 @check_connection def screenshot(device, filename): screen = device.connection.takeSnapshot() screen.writeToFile(filename + '.png', 'png') 
+2
source

You will get this error every time you run MonkeyRunner, because the monkey --port 12345 on the device does not stop when your script stops. This is a mistake in the monkey.

The best way to solve this problem is to kill the monkey when SIGINT sent to your script (when you ctrl+c ). In other words: $ killall com.android.commands.monkey .

A quick way to do this:

 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() 

Edit: as an add-on, I also found a way to spot Java errors: Monkey Runner throwing a broken pipe exception socket on touuch

+6
source

Source: https://habr.com/ru/post/924232/


All Articles