dump 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #!C:\tools\Python27\python.exe
  2. '''
  3. Copyright (C) 2012-2015 Diego Torres Milano
  4. Created on Feb 3, 2012
  5. @author: diego
  6. '''
  7. __version__ = '10.3.0'
  8. import sys
  9. import os
  10. import getopt
  11. try:
  12. sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
  13. except:
  14. pass
  15. from com.dtmilano.android.viewclient import ViewClient, View
  16. HELP = 'help'
  17. VERBOSE = 'verbose'
  18. VERSION = 'version'
  19. IGNORE_SECURE_DEVICE = 'ignore-secure-device'
  20. IGNORE_VERSION_CHECK = 'ignore-version-check'
  21. FORCE_VIEW_SERVER_USE = 'force-view-server-use'
  22. DO_NOT_START_VIEW_SERVER = 'do-not-start-view-server'
  23. DO_NOT_IGNORE_UIAUTOMATOR_KILLED = 'do-not-ignore-uiautomator-killed'
  24. WINDOW = 'window'
  25. ALL = 'all'
  26. UNIQUE_ID = 'uniqueId'
  27. POSITION = 'position'
  28. BOUNDS = 'bounds'
  29. CONTENT_DESCRIPTION = 'content-description'
  30. TAG = 'tag'
  31. CENTER = 'center'
  32. SAVE_SCREENSHOT = 'save-screenshot'
  33. SAVE_VIEW_SCREENSHOTS = 'save-view-screenshots'
  34. DO_NOT_DUMP_VIEWS = 'do-not-dump-views'
  35. DEVICE_ART = 'device-art'
  36. DROP_SHADOW = 'drop-shadow'
  37. SCREEN_GLARE = 'glare'
  38. MAP = {
  39. 'a':View.__str__, ALL:View.__str__,
  40. 'i':ViewClient.TRAVERSE_CITUI, UNIQUE_ID:ViewClient.TRAVERSE_CITUI,
  41. 'x':ViewClient.TRAVERSE_CITPS, POSITION:ViewClient.TRAVERSE_CITPS,
  42. 'b':ViewClient.TRAVERSE_CITB, BOUNDS:ViewClient.TRAVERSE_CITB,
  43. 'd':ViewClient.TRAVERSE_CITCD, CONTENT_DESCRIPTION:ViewClient.TRAVERSE_CITCD,
  44. 'g':ViewClient.TRAVERSE_CITG, TAG:ViewClient.TRAVERSE_CITG,
  45. 'c':ViewClient.TRAVERSE_CITC, CENTER:ViewClient.TRAVERSE_CITC,
  46. 'W':ViewClient.TRAVERSE_CITCDS, SAVE_VIEW_SCREENSHOTS:ViewClient.TRAVERSE_CITCDS,
  47. 'D':ViewClient.TRAVERSE_S, DO_NOT_DUMP_VIEWS:ViewClient.TRAVERSE_S
  48. }
  49. USAGE = 'usage: %s [OPTION]... [serialno]'
  50. SHORT_OPTS = 'HVvIEFSkw:aixbdgcf:W:DA:ZB'
  51. LONG_OPTS = [HELP, VERBOSE, VERSION, IGNORE_SECURE_DEVICE, IGNORE_VERSION_CHECK, FORCE_VIEW_SERVER_USE,
  52. DO_NOT_START_VIEW_SERVER, DO_NOT_IGNORE_UIAUTOMATOR_KILLED, WINDOW + '=',
  53. ALL, UNIQUE_ID, POSITION, BOUNDS, CONTENT_DESCRIPTION, TAG, CENTER,
  54. SAVE_SCREENSHOT + '=', SAVE_VIEW_SCREENSHOTS + '=',
  55. DO_NOT_DUMP_VIEWS,
  56. DEVICE_ART + '=', DROP_SHADOW, SCREEN_GLARE,
  57. ]
  58. LONG_OPTS_ARG = {WINDOW: 'WINDOW', SAVE_SCREENSHOT: 'FILE', SAVE_VIEW_SCREENSHOTS: 'DIR', DEVICE_ART: 'MODEL'}
  59. OPTS_HELP = {
  60. 'H': 'prints this help',
  61. 'V': 'verbose comments',
  62. 'I': 'ignore secure device',
  63. 'F': 'force view server use (even if UiAutomator present)',
  64. 'S': 'don\'t start ViewServer',
  65. 'k': 'don\'t ignore UiAutomator killed',
  66. 'w': 'dump WINDOW content (default: -1, all windows)',
  67. 'a': 'dump all information about Views',
  68. 'i': 'dump View unique IDs',
  69. 'x': 'dump View positions',
  70. 'b': 'dump View bounds',
  71. 'd': 'dump View content descriptions',
  72. 'g': 'dump View tags',
  73. 'c': 'dump View centers',
  74. 'f': 'save screenshot to file',
  75. 'W': 'save View screenshots to files in directory',
  76. 'E': 'ignores ADB version check',
  77. 'D': 'don\'t dump views, only useful if you specified -f or -W',
  78. 'A': 'device art model to frame screenshot (auto: autodetected)',
  79. 'Z': 'drop shadow for device art screenshot',
  80. 'B': 'screen glare over screenshot',
  81. }
  82. def shortAndLongOptions():
  83. '''
  84. @return: the list of corresponding (short-option, long-option) tuples
  85. '''
  86. short_opts = SHORT_OPTS.replace(':', '')
  87. if len(short_opts) != len(LONG_OPTS):
  88. raise Exception('There is a mismatch between short and long options')
  89. t = tuple(short_opts) + tuple(LONG_OPTS)
  90. l2 = len(t)/2
  91. sl = []
  92. for i in range(l2):
  93. sl.append((t[i], t[i+l2]))
  94. return sl
  95. def usage(exitVal=1):
  96. print >> sys.stderr, USAGE % progname
  97. print >> sys.stderr, "Try '%s --help' for more information." % progname
  98. sys.exit(exitVal)
  99. def help():
  100. print >> sys.stderr, USAGE % progname
  101. print >> sys.stderr
  102. print >> sys.stderr, "Options:"
  103. for so, lo in shortAndLongOptions():
  104. o = ' -%c, --%s' % (so, lo)
  105. if lo[-1] == '=':
  106. o += LONG_OPTS_ARG[lo[:-1]]
  107. try:
  108. o = '%-34s %-45s' % (o, OPTS_HELP[so])
  109. except:
  110. pass
  111. print >> sys.stderr, o
  112. sys.exit(0)
  113. def version():
  114. print progname, __version__
  115. sys.exit(0)
  116. # __main__
  117. progname = os.path.basename(sys.argv[0])
  118. try:
  119. opts, args = getopt.getopt(sys.argv[1:], SHORT_OPTS, LONG_OPTS)
  120. sys.argv[1:] = args
  121. except getopt.GetoptError, e:
  122. print >>sys.stderr, 'ERROR:', str(e)
  123. usage()
  124. kwargs1 = {VERBOSE: False, 'ignoresecuredevice': False, 'ignoreversioncheck': False}
  125. kwargs2 = {'forceviewserveruse': False, 'startviewserver': True, 'autodump': False, 'ignoreuiautomatorkilled': True}
  126. options = {WINDOW: -1, SAVE_SCREENSHOT: None, SAVE_VIEW_SCREENSHOTS: None, DO_NOT_DUMP_VIEWS: False,
  127. DEVICE_ART: None, DROP_SHADOW: False, SCREEN_GLARE: False}
  128. transform = ViewClient.TRAVERSE_CIT
  129. for o, a in opts:
  130. o = o.strip('-')
  131. if o in ['H', HELP]:
  132. help()
  133. elif o in ['V', VERBOSE]:
  134. kwargs1[VERBOSE] = True
  135. elif o in ['v', VERSION]:
  136. version()
  137. elif o in ['I', IGNORE_SECURE_DEVICE]:
  138. kwargs1['ignoresecuredevice'] = True
  139. elif o in ['E', IGNORE_VERSION_CHECK]:
  140. kwargs1['ignoreversioncheck'] = True
  141. elif o in ['F', FORCE_VIEW_SERVER_USE]:
  142. kwargs2['forceviewserveruse'] = True
  143. elif o in ['S', DO_NOT_START_VIEW_SERVER]:
  144. kwargs2['startviewserver'] = False
  145. elif o in ['k', DO_NOT_IGNORE_UIAUTOMATOR_KILLED]:
  146. kwargs2['ignoreuiautomatorkilled'] = False
  147. elif o in ['w', WINDOW]:
  148. options[WINDOW] = a
  149. elif o in ['f', SAVE_SCREENSHOT]:
  150. options[SAVE_SCREENSHOT] = a
  151. elif o in ['W', SAVE_VIEW_SCREENSHOTS]:
  152. options[SAVE_VIEW_SCREENSHOTS] = a
  153. transform = MAP[o]
  154. elif o in ['A', DEVICE_ART]:
  155. options[DEVICE_ART] = a
  156. elif o in ['Z', DROP_SHADOW]:
  157. options[DROP_SHADOW] = True
  158. elif o in ['B', SCREEN_GLARE]:
  159. options[SCREEN_GLARE] = True
  160. elif o in ['D', DO_NOT_DUMP_VIEWS]:
  161. options[DO_NOT_DUMP_VIEWS] = True
  162. transform = MAP[o]
  163. else:
  164. transform = MAP[o]
  165. if options[DO_NOT_DUMP_VIEWS]:
  166. transform = MAP[DO_NOT_DUMP_VIEWS]
  167. vc = ViewClient(*ViewClient.connectToDeviceOrExit(**kwargs1), **kwargs2)
  168. if options[SAVE_SCREENSHOT]:
  169. vc.device.reconnect = True #(not options[DO_NOT_DUMP_VIEWS])
  170. vc.writeImageToFile(options[SAVE_SCREENSHOT], deviceart=options[DEVICE_ART], dropshadow=options[DROP_SHADOW], screenglare=options[SCREEN_GLARE])
  171. if not options[DO_NOT_DUMP_VIEWS] or options[SAVE_VIEW_SCREENSHOTS]:
  172. vc.dump(window=options[WINDOW])
  173. ViewClient.imageDirectory = options[SAVE_VIEW_SCREENSHOTS]
  174. vc.traverse(transform=transform)