前期准备:
关于什么是Hierarchy Viewer,请查看官方文档:http://developer.android.com/tools/debugging/debugging-ui.html。个人理解:Hierarchy Viewer能获得当前手机实时的UI信息,给界面设计人员和自动化测试人员带来极大的便利。
 
在Android的官方文档中提到:
To preserve security, Hierarchy Viewer can only connect to devices running a developer version of the Android system.
即:出于安全考虑,Hierarchy Viewer只能连接Android开发版手机或是模拟器(准确地说,只有ro.secure参数等于0且ro.debuggable等于1的android系统)。Hierarchy Viewer在连接手机时,手机上必须启动一个叫View Server的客户端与其进行socket通信。而在商业手机上,是无法开启View Server的,故Hierarchy Viewer是无法连接到普通的商业手机。
 
Android源码实现这一限制的地方在:
ANDROID源码根目录\frameworks\base\services\java\com\android\server\wm\WindowManageService.java
中的一段:
=====================================================================================
public boolean startViewServer(int port) {
    if (isSystemSecure()) {
        return false;
    }

if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
        return false;
    }

....
=====================================================================================
 
检验一台手机是否开启了View Server的办法为:
adb shell service call window 3
若返回值是:Result: Parcel(00000000 00000000 '........')" 说明View Server处于关闭状态
若返回值是:Result: Parcel(00000000 00000001 '........')" 说明View Server处于开启状态
 
若是一台可以打开View Server的手机(Android开发版手机 、模拟器or 按照本帖步骤给系统打补丁的手机),我们可以使用以下命令打开View Server:
adb shell service call window 1 i32 4939
使用以下命令关闭View Server:
adb shell service call window 2 i32 4939
 
 
 
实现步骤:
经过一番调查和实践,我发现其实只要是root,并且装有busybox的手机,通过修改手机上/system/framework中的某些文件,就可以开启。本文参考了http://blog.apkudo.com/tag/viewserver/,以下是具体步骤(本人基于Windows,若你是Linux的操作系统,直接看原帖吧):
前提是:你的手机已经获得ROOT权限,且有BUSYBOX
另外:请仔细阅读本帖的评论,或许你会有新的收获。
 
1.将商业手机通过USB连接PC,确保adb服务运行正常
 
2.备份手机上/system/framework/中的文件至PC。备份的时候请确保PC上保存备份文件的文件夹结构与手机中的/system/framework相同
例如:新建 ANDROID_SDK_ROOT\system\framework文件夹 (本文出现的ANDROID_SDK_ROOT指你安装Android SDK的根目录)
接着在cmd中跳转至ANDROID_SDK_ROOT\platform-tools文件夹下,输入以下代码进行备份:
adb pull /system/framework  ANDROID_SDK_ROOT\system\framework
 
3.进入adb shell,输出BOOTCLASSPATH:
推荐的做法:
1. 在adb shell中echo $BOOTCLASSPATH > /sdcard/bootclasspath.txt
2. 退回到windows cmd中,输入adb pull /sdcard/bootclasspath.txt
3. bootclasspath.txt将会保存在C:\Users\你的用户名 文件夹下
在第十五步中将会用到这个txt中的内容。
 
4.下载baksmali 和smali工具。这两个工具是用来反编译和编译odex文件的。
下载地址:
假设我将这两个jar都下载到了ANDROID SDK根目录下。
 
5.运行baksmali反编译\system\framework下的services.odex文件:
java -jar ANDROID_SDK_ROOT\baksmali-1.4.2.jar -a 17 -x ANDROID_SDK_ROOT\system\framework\services.odex -d ANDROID_SDK_ROOT\system\framework
想特别说明的是“-a”后跟的数字,表示你系统的API Level(与你的系统版本有关)。系统版本和API Level的对照关系如下:
(另外,你不会连java -jar都不能运行吧?快去装jdk!)
此步成功的话,在同文件夹下(对于我,就是ANDROID_SDK_ROOT),会有个out文件夹生成
 
这里顺便解释一下odex文件和dex文件。
dex文件:Dex是Dalvik VM executes的全称,即Android Dalvik执行程序,并非Java的字节码而是Dalvik字节码,16进制机器指令。
odex文件:将dex文件依据具体机型而优化,形成的optimized dex文件,提高软件运行速度,减少软件运行时对RAM的占用。
smali文件:将dex文件变为可读易懂的代码形式,反编译出文件的一般格式。
 
6.用Eclipse打开out\com\android\server\wm\WindowManagerService.smali文件
查找.method private isSystemSecure()Z这个函数
================================================================
.method private isSystemSecure()Z
    .registers 4
 
    .prologue
    .line 5965
    const-string v0, "1"
 
    const-string v1, "ro.secure"
 
    const-string v2, "1"
 
    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 
    move-result-object v1
 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
 
    move-result v0
 
    if-eqz v0, :cond_22
 
    const-string v0, "0"
 
    const-string v1, "ro.debuggable"
 
    const-string v2, "0"
 
    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 
    move-result-object v1
 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
 
    move-result v0
 
    if-eqz v0, :cond_22
 
    const/4 v0, 0x1
 
    :goto_21
    return v0
 
    :cond_22
    const/4 v0, 0x0
 
    goto :goto_21
.end method
================================================================
在这段代码的倒数7,8行“:goto_21”和“return v0”之间加入"const/4 v0, 0x0"一行.这样,就使得v0返回的值永远为0x0,即false,这样就跳过了WindowManagerService.java里对isSystemSecure的判断。
.method private isSystemSecure()Z函数最后变为:
================================================================
.method private isSystemSecure()Z
    .registers 4
 
    .prologue
    .line 6276
    const-string v0, "1"
 
    const-string v1, "ro.secure"
 
    const-string v2, "1"
 
    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 
    move-result-object v1
 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
 
    move-result v0
 
    if-eqz v0, :cond_22
 
    const-string v0, "0"
 
    const-string v1, "ro.debuggable"
 
    const-string v2, "0"
 
    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 
    move-result-object v1
 
    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
 
    move-result v0
 
    if-eqz v0, :cond_22
 
    const/4 v0, 0x1
 
    :goto_21
    const/4 v0, 0x0
    return v0
 
    :cond_22
    const/4 v0, 0x0
 
    goto :goto_21
.end method
=====================================================================================
 
7. 现在运行smali,重新编译:
java -jar smali-1.4.2.jar -o classes.dex
这时候,应该在ANDROID_SDK_ROOT文件夹中出现了classes.dex文件
 
8. 下载windows下的zip工具:
假设,我也把zip.exe放进了ANDROID_SDK_ROOT文件夹
 
9.确认当前cmd命令行运行目录为ANDROID_SDK_ROOT,运行:
zip.exe services_hacked.jar ./classes.dex
这时候在ANDROID_SDK_ROOT文件夹下,出现了打包好的services_hacked.jar
 
10.进入adb shell,输入su获得ROOT权限
 
11.重新挂载/system,并更改/system权限
参考步骤(仅供参考,请确保使用相适应于自己手机的正确方法。请参考下面的"galfordq的blog"用户的回复):
  a. 输入mount,查看哪个分区挂载了/system,例如我的是:
  b. 输入以下命令重新挂载/system,并更改/system权限(请将“/dev/block/mmcblk0p25”替换成你的/system挂载分区):
   mount -o rw,remount -t yaffs2 /dev/block/mmcblk0p25
   chmod -R 777 /system 使得/system 可以被我们任意修改
 
这一步的作用,主要是为了第17步能够将/system/framework里的services.odex替换掉。这一步若不成功,在第17步的时候可能出现权限不够,无法替换的错误(Read-Only File System)
 
12.下载dexopt-wrapper文件
我们也将dexopt-wrapper文件放在ANDROID_SDK_ROOT文件夹中
 
13.将services_hacked.jar和dexopt-wrapper复制到手机的/data/local/tmp文件夹中
adb push ANDROID_SDK_ROOT/services_hacked.jar /data/local/tmp
adb push ANDROID_SDK_ROOT/dexopt-wrapper /data/local/tmp
 
14.进入adb shell,输入su后,将dexopt-wrapper的权限改为777
chmod 777 /data/local/tmp/dexopt-wrapper
 
15.在adb shell中cd到/data/local/tmp文件夹下,运行:
./dexopt-wrapper ./services_hacked.jar ./services_hacked.odex <本帖第三步存的地址,但是要删除其中的":/system/framework/services.jar">
这一步就是将第七部生成dex文件最终优化成了odex文件。
===================================================================================================
例如我的命令是:./dexopt-wrapper ./services_hacked.jar ./services_hacked.odex /system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/
framework.jar:/system/framework/framework2.jar:/system/framework/android.policy.jar:/system/
framework/apache-xml.jar:/system/framework/HTCDev.jar:/system/framework/HTCExtension.jar:/system/
framework/filterfw.jar:/system/framework/com.htc.android.bluetooth.jar:/system/framework/wimax.jar:
/system/framework/usbnet.jar:/system/framework/com.orange.authentication.simcard.jar
===================================================================================================
 
这样,便在/data/local/tmp文件夹中生成了我们自己的odex:services_hacked.odex
 
16.给我们自己生成的services_hacked.odex签名:
busybox dd if=/system/framework/services.odex of=/data/local/tmp/services_hacked.odex bs=1 count=20 skip=52 seek=52 conv=notrunc
参数解释:
if = input file
of = output file
bs = block size (1 byte)
count = number of blocks
skip = input file offset
seek = output file offset
conv=notrunc – don’t truncate the output file.
 
17.将/system/framework里的services.odex替换成我们自己制作的services_hacked.odex吧!
dd if=/data/local/tmp/services_hacked.odex of=/system/framework/services.odex
这一步运行后,过一小会儿(1分钟以内)手机就自动重启了!稍等片刻吧!
 
18.成功重启后,用以下命令打开View Server:
adb shell service call window 1 i32 4939
用以下命令查看View Server是否打开:
adb shell service call window 3
返回的值若是Result: Parcel(00000000 00000001   '........'),那么你就起了!
 
(若某一步失败,需要恢复系统,请参考http://blog.apkudo.com/tag/viewserver/中的Step 16或联系我的邮箱进一步讨论:czxttkl@gmail.com)
 
接下来,就在Eclipse下编译运行HierarchyViewer来查看手机实时的UI树吧。

如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接(转)的更多相关文章

  1. 如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接

    前期准备: 关于什么是Hierarchy Viewer,请查看官方文档:http://developer.android.com/tools/debugging/debugging-ui.html.个 ...

  2. 如何在 Android 安卓手机上运行 Node.js 应用 | 如何在安卓手机配置node开发环境

    最近在学习js,由于没法随身携带笔记本电脑,在手机翻阅<JavaScript高级程序设计>时,时常想调试一下书中的代码.于是就有了,能否在手机上配置一个js开发环境.考虑到手机上的Chro ...

  3. 如何在Windows2008 Server服务器上开启Ping或者禁PING

    方法1:命令行模式 进入服务器后 点击 开始--运行 输入命令: netsh firewall set icmpsetting 8 这样就可以在外部ping到服务器了 非常简单实用! 同样道理,如果想 ...

  4. 如何在iPhone与iPad上开启firebug

    原文: MARTIN KOOL games - web - dad - sarien.net - q42 - livejs - handcraft How to use Firebug on your ...

  5. 如何在 Android 手机上实现抓包?

    如何在 Android 手机上实现抓包? http://www.zhihu.com/question/20467503 我想知道某个应用究竟在数据提交到哪里,提交了什么.网上的教程太复杂,不想麻烦.有 ...

  6. 如何在Android手机上进行自动化测试(上)

    版权声明:允许转载,但转载必须保留原链接:请勿用作商业或者非法用途 前言 通过阅读本节教程,你将了解到以下内容: 如何在脚本代码中.运行脚本时指定手机 如何填写--device Android:/// ...

  7. 如何在Android手机上进行自动化测试(下)

    版权声明:允许转载,但转载必须保留原链接:请勿用作商业或者非法用途 前言 通过阅读本篇教程,你将会了解到: 如何使用Poco对Android原生应用进行测试 Poco支持直接对任何Android原生应 ...

  8. Android 手机上安装并运行 Ubuntu 12.04

    ubuntu.sh脚本的原地址变动了,导致下载不了,现在更新了网盘地址.小技巧:遇到一些下载失效的时候可以试一试p2p下载工具(如 easyMule.迅雷等)试一试,说不定有人分享过~* —————— ...

  9. 如何在 Ubuntu 和 CentOS 上启用 Nginx 的 HTTP/2 协议支持

    HTTP/2 是 HTTP 网络协议的主要修订版本,其专注于 HTTP 协议的性能改进.HTTP/2 协议的目标是减少延迟,并且允许在 Web 浏览器和服务器之间的一个连接上并行发起多个请求,因此 W ...

随机推荐

  1. 第12月第2天 uiscrollview _adjustContentOffsetIfNecessary 圆角

    1. uiscrollview在调用setFrame,setBounds等方法的时候会默认调用稀有api: _adjustContentOffsetIfNecessary 这个方法会改变当前的cont ...

  2. Thinkpad X220 升级 Windows 10 后无线网卡消失问题

    11年购买的Thinkpad X220从Win7升级到Win10后,用着还是挺顺手的,网络显示等一切正常,直到今天合上盖子电脑睡眠以后再次打开,wifi消失不见.重启,关机再开机,都没用,只显示有线网 ...

  3. JAVA中Collection接口和Map接口的主要实现类

    Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些Collection允许相同的元素 ...

  4. linux命令中which、whereis、locate有什么区别?

    1.find find是最常用和最强大的查找命令.它能做到实时查找,精确查找,但速度慢. find的使用格式如下: #find [指定目录] [指定条件] [指定动作] 指定目录:是指所要搜索的目录和 ...

  5. Java基本数据类型装箱的127临界点

    package wrapper.demo; public class WrapperDemo { /** * @param args */ public static void main(String ...

  6. 【Python】【持续项目】Python-安全项目搜集

    1.前言 Python发展以来,除了web安全方向,二进制方向也早已经积累有很多用Python写的项目.作为搜集者当然不能错过! 2.项目分类 安全编程 多功能Python键盘记录工具:Radium ...

  7. 如何对xilinx FPGA进行bit文件加密

    记录背景:最近在用Vivado评估国外一个公司所提供的ISE所建的工程时,由于我并没有安装ISE工程,因此将其提供的所有v文件导入到Vivado中,对其进行编译.添加完之后成功建立顶层文件,但奇怪的是 ...

  8. mysql high availability 概述

    一.什么是高可用性 1.可用性是指服务不间断运转的时间,通常用百分比来表示,例如 99.999%表示每年最多允许5分钟的宕机时间 2.可用性的效果和开销比例呈线性增长 3.可用性的意义往往也不尽相同, ...

  9. mitmproxy实践

    首先附上github地址:https://github.com/mitmproxy/mitmprox,上面的内容永远是最新的 作为一名测试穿戴设备相关app的工程师,与数据打交道是常事,那么,如果想要 ...

  10. AngularJS里面$emit, $broadcast,$on,$http.Jsonp,constant是使用笔记

    本片主要介绍$emit, $broadcast,$on经常开发的用法!