var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-333696-1']); _gaq.push(['_trackPageview']); _gaq.push(['_trackPageLoadTime']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();
  • 2012年07月21日

    Hierarchy Viewer 揭秘

    分类:

    关于Android SDK里面自带的工具Hierarchy Viewer在前面的两篇文章Robotium 使用Android 基于屏幕坐标的录制回放工具中都有过介绍,下面就其原理做些补充。

     

    其能获取View上的层级和层里的元素属性,来自于/platform/sdk/hierarchyviewer/src/com/android/hierarchyviewer/scene源文件目录,其最最核心在文件ViewHierarchyLoader.java中的函数loadScene,它连接到本地设备向其发送“DUMP”命令,而支持“DUMP”命令的函数又来自于哪呢?搜索整个Android 4.1.1源码发现/platform/frameworks/base/core/java/android/view/ViewDebug.java中有一系列相关的定义:

        private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";

        private static final String REMOTE_COMMAND_DUMP = "DUMP";

        private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";

        private static final String REMOTE_PROFILE = "PROFILE";

        private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS";

    同样在此文件函数dispatchCommand接到REMOTE_COMMAND_DUMP后调用函数dump(view, clientStream)进行处理,dump函数又调用dumpViewHierarchyWithProperties对每个View中元素属性进行列举,dumpViewHierarchyWithProperties函数调用dumpViewWithProperties进行递归,至此整个过程结束。

     

    此外,文件ViewDebug.java我们找到了一个废弃的变量TRACE_HIERARCHY,它初始值为false,为了找到其真正的作用我们向前回溯查看上个版本4.0.4源码,发现其还没被废弃其在函数startHierarchyTracingstopHierarchyTracing(这两个函数连同startRecyclerTracingstopRecyclerTracingtrace4.1.1同被弃用)中被使用,当其为false时这两函数什么也不做立即返回,阅读同一版本中的ViewDebugTest.java中的使用不难发现这个变量就是启用hierarchy跟踪的开关,再而对比4.1.1上的ViewDebugTest.java就更加坚定了我们的信心。前两篇文章都有介绍Hierarchy Viewer只能连上开发版的Android,当时猜测的原因是因为安全,但Hierarchy Viewer需要启动View Server以加载窗口在文件ViewServer,它需要ro.secure=0(表示root用户运行,见ppt ADB(Android Debug Bridge): How it works?), ro.debuggable=1(能用adb root重启adb;如果不是虚拟机、secure1并且service.adb.rootadb root设置为1,表示adbd可以root用户运行)Manifest.permission.DUMP权限(如果不是自己在调用)才能启用,逻辑见WindowManagerService.java中的函数startViewServer。对此,Android工程师Romain解释ViewServer不是一个公开的API并且不会在生产设备上启用,它并不设计用来交互并且它是很慢的。为了解决这个很慢的问题(实际使用Hierarchy Viewer工具”Load View Hierarchy”就能感觉到速度较慢),android-app-testing-patches为其做了补丁,其wiki上说引入了一个新命令” DUMPQ”,它不再获取每个ViewDebug标记而用成员方法” dumpClass”,比原有命令快20~40倍。

    分享到:

    历史上的今天:

    安装 Android SDK 2011年07月21日
    多音字排序 2010年07月21日
    控制CPU使用率 2007年07月21日
    互联网地狱 2006年07月21日