//获取window_dump.xml
public String getWindowInfo() {
        try {
            Object bridge = ReflectionUtils.invokeMethod(this.getUiDevice(),
                    "getAutomatorBridge", new Class[] {}, new Object[] {});
            if (bridge == null) {
                return "AutomatorBridge is Null";
            }
            Object queryController = ReflectionUtils.invokeMethod(bridge,
                    "getQueryController", new Class[] {}, new Object[] {});
            if (queryController == null) {
                return "queryController is Null.";
            }
            Object rootNode = ReflectionUtils
                    .invokeMethod(queryController, "getAccessibilityRootNode",
                            new Class[] {}, new Object[] {});
            AccessibilityNodeInfo root = (AccessibilityNodeInfo) rootNode;
            if (root != null) {
                return Utils.getWindowInfo(root, this.getUiDevice()
                        .getDisplayWidth(), this.getUiDevice()
                        .getDisplayHeight());
            } else {
                return "Root Node is Null";
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(tag, "Error", e);
            return e.getMessage();
        }
    }
//根据root获取控件数信息
    public static String getWindowInfo(AccessibilityNodeInfo root, int screenW, int screenH) {
        if (root == null) {
            return "";
        }
        final long startTime = SystemClock.uptimeMillis();
        try {          
            XmlSerializer serializer = Xml.newSerializer();
            StringWriter stringWriter = new StringWriter();
            serializer.setOutput(stringWriter);
            serializer.startDocument("UTF-8", true);
            serializer.startTag("", "hierarchy");
            dumpNodeRec(root, serializer, 0, screenW, screenH);
            serializer.endTag("", "hierarchy");
            serializer.endDocument();
            return stringWriter.toString();
        } catch (IOException e) {
            Log.e("UITestin", "failed to dump window to file", e);
        }
        final long endTime = SystemClock.uptimeMillis();
        Log.w("UITestin", "Fetch time: " + (endTime - startTime) + "ms");
        return "";
    }
//参考uiautomator部分源码
    private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer,
            int index, int screenW, int screenH) throws IOException {
        serializer.startTag("", "node");
        if (!nafExcludedClass(node) && !nafCheck(node))
            serializer.attribute("", "NAF", Boolean.toString(true));
        serializer.attribute("", "index", Integer.toString(index));
        serializer.attribute("", "text", safeCharSeqToString(node.getText()));
        serializer.attribute("", "class", safeCharSeqToString(node.getClassName()));
        serializer.attribute("", "package", safeCharSeqToString(node.getPackageName()));
        serializer.attribute("", "content-desc", safeCharSeqToString(node.getContentDescription()));
        serializer.attribute("", "checkable", Boolean.toString(node.isCheckable()));
        serializer.attribute("", "checked", Boolean.toString(node.isChecked()));
        serializer.attribute("", "clickable", Boolean.toString(node.isClickable()));
        serializer.attribute("", "enabled", Boolean.toString(node.isEnabled()));
        serializer.attribute("", "focusable", Boolean.toString(node.isFocusable()));
        serializer.attribute("", "focused", Boolean.toString(node.isFocused()));
        serializer.attribute("", "scrollable", Boolean.toString(node.isScrollable()));
        serializer.attribute("", "long-clickable", Boolean.toString(node.isLongClickable()));
        serializer.attribute("", "password", Boolean.toString(node.isPassword()));
        serializer.attribute("", "selected", Boolean.toString(node.isSelected()));
        serializer.attribute("", "bounds",
                AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node, screenW, screenH).toShortString());
        int count = node.getChildCount();
        for (int i = 0; i < count; i++) {
            AccessibilityNodeInfo child = node.getChild(i);
            if (child != null) {
                if (child.isVisibleToUser()) {
                    dumpNodeRec(child, serializer, i, screenW, screenH);
                    child.recycle();
                } else {
//                    Log.i(tag, String.format("Skipping invisible child: %s", child.toString()));
                }
            } else {
//                Log.i(tag, String.format("Null child %d/%d, parent: %s",
//                        i, count, node.toString()));
            }
        }
        serializer.endTag("", "node");
    }
//反射相关方法
    public static Object invokeMethod(Object object, String methodName,
            Class<?>[] parameterTypes, Object[] parameters) {
        // 根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象
        Method method = getDeclaredMethod(object, methodName, parameterTypes);
        // 如果Method为空,则肯定没有结果,直接返回null即可。
        if (method == null){
            return null;
        }
        // 抑制Java对方法进行检查,主要是针对私有方法而言
        method.setAccessible(true);
        try {
            if (null != method) {
                // 调用object 的 method 所代表的方法,其方法的参数是 parameters
                return method.invoke(object, parameters);
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static Method getDeclaredMethod(Object object, String methodName,
            Class<?>... parameterTypes) {
        Method method = null;
        for (Class<?> clazz = object.getClass(); clazz != Object.class; clazz = clazz
                .getSuperclass()) {
            try {
                method = clazz.getDeclaredMethod(methodName, parameterTypes);
                return method;
            } catch (Exception e) {
                // 这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。
                // 如果这里的异常打印或者往外抛,则就不会执行clazz =
                // clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }
        return null;
    }