Skip to content

Commit

Permalink
Added list windows command
Browse files Browse the repository at this point in the history
- Version 2.3.13
- Added ViewClient.list()
- dump.py: added window command line option
- list.py: list windows
  • Loading branch information
dtmilano committed Apr 23, 2013
1 parent e2462b5 commit 840a7a8
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 12 deletions.
20 changes: 14 additions & 6 deletions AndroidViewClient/examples/dump.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
IGNORE_SECURE_DEVICE = 'ignore-secure-device' IGNORE_SECURE_DEVICE = 'ignore-secure-device'
FORCE_VIEW_SERVER_USE = 'force-view-server-use' FORCE_VIEW_SERVER_USE = 'force-view-server-use'
DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server' DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server'
WINDOW = 'window'
UNIQUE_ID = 'uniqueId' UNIQUE_ID = 'uniqueId'
POSITION = 'position' POSITION = 'position'
CONTENT_DESCRIPTION = 'content-description' CONTENT_DESCRIPTION = 'content-description'
Expand All @@ -43,22 +44,25 @@
'd':ViewClient.TRAVERSE_CITCD, CONTENT_DESCRIPTION:ViewClient.TRAVERSE_CITCD, 'd':ViewClient.TRAVERSE_CITCD, CONTENT_DESCRIPTION:ViewClient.TRAVERSE_CITCD,
'c':ViewClient.TRAVERSE_CITC, CENTER:ViewClient.TRAVERSE_CITC, 'c':ViewClient.TRAVERSE_CITC, CENTER:ViewClient.TRAVERSE_CITC,
} }
LONG_OPTS = [HELP, VERBOSE, IGNORE_SECURE_DEVICE, FORCE_VIEW_SERVER_USE, DO_NOT_START_VIEW_SERVER, SHORT_OPTS = 'HVIFSw:ixdc'
UNIQUE_ID, POSITION, CONTENT_DESCRIPTION, CENTER] LONG_OPTS = [HELP, VERBOSE, IGNORE_SECURE_DEVICE, FORCE_VIEW_SERVER_USE,
DO_NOT_START_VIEW_SERVER, WINDOW + '=',
UNIQUE_ID, POSITION, CONTENT_DESCRIPTION, CENTER]


def usage(exitVal=1): def usage(exitVal=1):
print >> sys.stderr, 'usage: dump.py [-H|--%s] [-V|--%s] [-I|--%s] [-F|--%s] [-S|--%s] [-i|--%s] [-x|--%s] [-d|--%s] [-c|--%s] [serialno]' % \ print >> sys.stderr, 'usage: dump.py [-H|--%s] [-V|--%s] [-I|--%s] [-F|--%s] [-S|--%s] [-w|--%s=WINDOW] [-i|--%s] [-x|--%s] [-d|--%s] [-c|--%s] [serialno]' % \
tuple(LONG_OPTS) tuple(LONG_OPTS)
sys.exit(exitVal) sys.exit(exitVal)


try: try:
opts, args = getopt.getopt(sys.argv[1:], 'HVIFSixdc', LONG_OPTS) opts, args = getopt.getopt(sys.argv[1:], SHORT_OPTS, LONG_OPTS)
except getopt.GetoptError, e: except getopt.GetoptError, e:
print >>sys.stderr, 'ERROR:', str(e) print >>sys.stderr, 'ERROR:', str(e)
usage() usage()


kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False} kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False}
kwargs2 = {'forceviewserveruse': False, 'startviewserver': True} kwargs2 = {'forceviewserveruse': False, 'startviewserver': True, 'autodump': False}
options = {WINDOW: -1}
transform = ViewClient.TRAVERSE_CIT transform = ViewClient.TRAVERSE_CIT
for o, a in opts: for o, a in opts:
o = o.strip('-') o = o.strip('-')
Expand All @@ -72,7 +76,11 @@ def usage(exitVal=1):
kwargs2['forceviewserveruse'] = True kwargs2['forceviewserveruse'] = True
elif o in ['S', DO_NOT_START_VIEW_SERVER]: elif o in ['S', DO_NOT_START_VIEW_SERVER]:
kwargs2['startviewserver'] = False kwargs2['startviewserver'] = False
elif o in ['w', WINDOW]:
options[WINDOW] = a
else: else:
transform = MAP[o] transform = MAP[o]


ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2).traverse(transform=transform) vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2)
vc.dump(window=options[WINDOW])
vc.traverse(transform=transform)
66 changes: 66 additions & 0 deletions AndroidViewClient/examples/list.py
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,66 @@
#! /usr/bin/env monkeyrunner
'''
Copyright (C) 2012 Diego Torres Milano
Created on Apr 23, 2013
@author: diego
'''


import sys
import os
import getopt

# This must be imported before MonkeyRunner and MonkeyDevice,
# otherwise the import fails.
# PyDev sets PYTHONPATH, use it
try:
for p in os.environ['PYTHONPATH'].split(':'):
if not p in sys.path:
sys.path.append(p)
except:
pass

try:
sys.path.append(os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
pass

from com.dtmilano.android.viewclient import ViewClient

HELP = 'help'
VERBOSE = 'verbose'
IGNORE_SECURE_DEVICE = 'ignore-secure-device'
FORCE_VIEW_SERVER_USE = 'force-view-server-use'
DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server'
# -u,-s,-p,-v eaten by monkeyrunner
SHORT_OPTS = 'HVIFS'
LONG_OPTS = [HELP, VERBOSE, IGNORE_SECURE_DEVICE, FORCE_VIEW_SERVER_USE, DO_NOT_START_VIEW_SERVER]

def usage(exitVal=1):
print >> sys.stderr, 'usage: list.py [-H|--%s] [-V|--%s] [-I|--%s] [-F|--%s] [-S|--%s] [serialno]' % \
tuple(LONG_OPTS)
sys.exit(exitVal)

try:
opts, args = getopt.getopt(sys.argv[1:], SHORT_OPTS, LONG_OPTS)
except getopt.GetoptError, e:
print >>sys.stderr, 'ERROR:', str(e)
usage()

kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False}
kwargs2 = {'forceviewserveruse': False, 'startviewserver': True, 'autodump': False}
for o, a in opts:
o = o.strip('-')
if o in ['H', HELP]:
usage(0)
elif o in ['V', VERBOSE]:
kwargs1[VERBOSE] = True
elif o in ['I', IGNORE_SECURE_DEVICE]:
kwargs1['ignoresecuredevice'] = True
elif o in ['F', FORCE_VIEW_SERVER_USE]:
kwargs2['forceviewserveruse'] = True
elif o in ['S', DO_NOT_START_VIEW_SERVER]:
kwargs2['startviewserver'] = False

print ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2).list()
80 changes: 74 additions & 6 deletions AndroidViewClient/src/com/dtmilano/android/viewclient.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@author: diego @author: diego
''' '''


__version__ = '2.3.12' __version__ = '2.3.13'


import sys import sys
import subprocess import subprocess
Expand Down Expand Up @@ -1511,15 +1511,18 @@ def traverse(self, root="ROOT", indent="", transform=View.__str__, stream=sys.st
for ch in root.children: for ch in root.children:
self.traverse(ch, indent=indent+" ", transform=transform, stream=stream) self.traverse(ch, indent=indent+" ", transform=transform, stream=stream)


def dump(self, windowId=-1, sleep=1): def dump(self, window=-1, sleep=1):
''' '''
Dumps the window content. Dumps the window content.
Sleep is useful to wait some time before obtaining the new content when something in the Sleep is useful to wait some time before obtaining the new content when something in the
window has changed. window has changed.
@type windowId: int @type window: int or str
@param windowId: the window id of the window to dump or -1 to dump all windows @param window: the window id or name of the window to dump.
The name is the package name or the window name (i.e. StatusBar) for
system windows.
Use -1 to dump all windows.
@type sleep: int @type sleep: int
@param sleep: sleep in seconds before proceeding to dump the content @param sleep: sleep in seconds before proceeding to dump the content
Expand Down Expand Up @@ -1556,19 +1559,32 @@ def dump(self, windowId=-1, sleep=1):
print >>sys.stderr print >>sys.stderr
self.setViewsFromUiAutomatorDump(received) self.setViewsFromUiAutomatorDump(received)
else: else:
if type(window).__name__ == 'str':
self.list(sleep=0)
found = False
for wId in self.windows:
if window == self.windows[wId]:
window = wId
found = True
break
if not found:
raise RuntimeError("ERROR: Cannot find window '%s'" % window)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try:
s.connect((VIEW_SERVER_HOST, self.localPort)) s.connect((VIEW_SERVER_HOST, self.localPort))
except socket.error, ex: except socket.error, ex:
raise RuntimeError("ERROR: Connecting to %s:%d: %s" % (VIEW_SERVER_HOST, self.localPort, ex)) raise RuntimeError("ERROR: Connecting to %s:%d: %s" % (VIEW_SERVER_HOST, self.localPort, ex))
s.send('dump %d\r\n' % windowId) cmd = 'dump %x\r\n' % window
if DEBUG:
print >>sys.stderr, "executing: '%s'" % cmd
s.send(cmd)
received = "" received = ""
doneRE = re.compile("DONE") doneRE = re.compile("DONE")
while True: while True:
received += s.recv(1024) received += s.recv(1024)
if doneRE.search(received[-7:]): if doneRE.search(received[-7:]):
break break

s.close() s.close()
if DEBUG: if DEBUG:
self.received = received self.received = received
Expand All @@ -1584,6 +1600,58 @@ def dump(self, windowId=-1, sleep=1):


return self.views return self.views


def list(self, sleep=1):
'''
List the windows.
Sleep is useful to wait some time before obtaining the new content when something in the
window has changed.
This also sets L{self.windows} as the list of windows.
@type sleep: int
@param sleep: sleep in seconds before proceeding to dump the content
@return: the list of windows
'''

if sleep > 0:
MonkeyRunner.sleep(sleep)

if self.useUiAutomator:
raise Exception("Not implemented yet")
else:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((VIEW_SERVER_HOST, self.localPort))
except socket.error, ex:
raise RuntimeError("ERROR: Connecting to %s:%d: %s" % (VIEW_SERVER_HOST, self.localPort, ex))
s.send('list\r\n')
received = ""
doneRE = re.compile("DONE")
while True:
received += s.recv(1024)
if doneRE.search(received[-7:]):
break
s.close()
if DEBUG:
self.received = received
if DEBUG_RECEIVED:
print >>sys.stderr, "received %d chars" % len(received)
print >>sys.stderr
print >>sys.stderr, received
print >>sys.stderr

self.windows = {}
for line in received.split('\n'):
if not line:
break
if doneRE.search(line):
break
(wid, package) = line.split()
self.windows[int('0x' + wid, 16)] = package
return self.windows


def findViewById(self, viewId, root="ROOT", viewFilter=None): def findViewById(self, viewId, root="ROOT", viewFilter=None):
''' '''
Finds the View with the specified viewId. Finds the View with the specified viewId.
Expand Down

0 comments on commit 840a7a8

Please sign in to comment.