今天想通过HierarchyViewer分析一下Android应用的布局,但是发现无法连接上真机,错误如下:

 
 
1
2
3
4
5
[hierarchyviewer]Unable to get view server version from device 00856cd5d08d2409
[hierarchyviewer]Unable to get view server protocol version from device 00856cd5d08d2409
[ViewServerDevice]Unable to debug device: lge-nexus_4-00856cd5d08d2409
[hierarchyviewer]Missing forwarded port for 00856cd5d08d2409
[hierarchyviewer]Unable to get the focused window from device 00856cd5d08d2409

原理

Android系统出于安全考虑,Hierarchy Viewer只能连接开发版手机或模拟器,我们普通的商业手机是无法连上的(老版本的Hierarchy Viewer可以),这一限制在
frameworks/base/services/java/com/android/server/wm/WindowManageService.java

 
 
 
 
 

Java

 
1
2
3
4
5
6
7
8
9
10
public boolean startViewServer(int port) {
    if (isSystemSecure()) {
        return false;
    }
 
    if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
        return false;
    }
    //……
}

我们要做的就是,修改并替换掉这个文件,使其通过判断。

检验一台手机是否开启了View Server的办法为:

 
 
 
 
 

Shell

 
1
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(没有的去装一个)

1.拷贝数据

约定当前使用的工作目录是/home/feelyou/hierarchyviewer

打开终端切换到工作目录,新建文件夹存放数据。通过usb连接上手机,执行:

 
 
 
 
 

Shell

 
1
2
3
mkdir ./system
mkdir ./system/framework
adb pull /system/framework/ ./system/framework/

2.获取bootclasspath

 
 
 
 
 

Shell

 
1
2
3
4
adb shell
echo $BOOTCLASSPATH
#将输出的内容复制出来,随意保存到一个文本文件里,后面要用到。
exit

3.反编译odex文件

这里要下载2个小工具,官方地址是https://bitbucket.org/JesusFreke/smali/downloads,下载最新版的smali-xxx.jar和baksmali-xxx.jar,比如我这里下载的是smali-2.0.3.jar和baksmali-2.0.3.jar,将这两个文件下载到工作目录。
然后在终端执行:

 
 
 
 
 
 

Shell

 
1
java -jar baksmali-2.0.3.jar -a 19 -x ./system/framework/services.odex -d ./system/framework/

注意,-a 后面的参数19,是你的手机当前的版本API Level,不知道的自己查一下。我的Nexus 4 是4.2.2,所以是19。执行成功了之后,在当前目录会有个out文件夹。

4.修改smail文件

使用文本编辑器打开out/com/android/server/wm/WindowManagerService.smali文件,搜索isSystemSecure(),第一个找到的目标,应该就是我们要的,这段代码如下(不用细看,我写这么多只是为了让你找到这个方法):

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
.method private isSystemSecure()Z
    .registers 4
 
    .prologue
    .line 6164
    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

这里注意,我们要在第41~42行之间,也就是:goto_21return v0之间加入const/4 v0, 0x0,使他变成

 
 
1
2
3
4
5
6
7
8
9
    :goto_21
    const/4 v0, 0x0
    return v0
 
    :cond_22
    const/4 v0, 0x0
 
    goto :goto_21
.end method

保存。

5.重新编译成dex文件

将out文件夹的内容编译并压缩。然后我们会得到一个叫做feelyou_services_hacked.jar的文件,后面要用到。

 
 
 
 
 

Shell

 
1
2
java -jar smali-2.0.3.jar ./out -o classes.dex
zip feelyou_services_hacked.jar ./classes.dex

6.获取/system挂载信息

这一步我们要获取/system挂载信息,并获取写入权限,因为后面要复制东西进来

 
 
 
 
 

Shell

 
1
2
3
adb shell
su
mount

然后出来一堆东西,查找一下哪个分区挂载了/system,例如我的是/dev/block/platform/msm_sdcc.1/by-name/system

接着,输入以下命令重新挂载/system,并更改/system权限(请将/dev/block/platform/msm_sdcc.1/by-name/system替换成你的/system挂载分区):

 
 
 
 
 

Shell

 
1
2
mount -o rw,remount -t yaffs2 /dev/block/platform/msm_sdcc.1/by-name/system
chmod -R 777 /system

这样我们就可以修改/system的内容了。

7.复制所需文件到手机

首先需要下载dexopt-wrapper,连接为https://dl.dropboxusercontent.com/u/5055823/dexopt-wrapper(英文原文章的连接已经失效),下载后依然放到当前工作目录。

将feelyou_services_hacked.jar和dexopt-wrapper复制到手机的/data/local/tmp文件夹中

 
 
 
 
 

Shell

 
1
2
adb push ./feelyou_services_hacked.jar /data/local/tmp
adb push ./dexopt-wrapper /data/local/tmp

给dexopt-wrapper运行权限

 
 
 
 
 

Shell

 
1
2
3
adb shell
su
chmod 777 /data/local/tmp/dexopt-wrapper

8.生成odex文件

注意!关键步骤!在adb shell中cd到/data/local/tmp文件夹下,运行:

 
 
 
 
 
 

Shell

 
1
./dexopt-wrapper ./feelyou_services_hacked.jar ./feelyou_services_hacked.odex [这里替换成之前获取到的BOOTCLASSPATH路径,但是注意!删除其中的":/system/framework/services.jar",当然,不包括中括号]

比如最后我的是这样:

 
 
 
 
 
 

Shell

 
1
./dexopt-wrapper ./feelyou_services_hacked.jar ./feelyou_services_hacked.odex /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/framework2.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/apache-xml.jar:/system/framework/webviewchromium.jar

这样就生成了一个feelyou_services_hacked.odex文件,等下我们要用它来替换系统原有的odex文件。

执行完了是这样的显示:

9.给生成的odex文件签名

还是在adb shell,su,执行:

 
 
 
 
 
 

Shell

 
1
busybox dd if=/system/framework/services.odex of=/data/local/tmp/feelyou_services_hacked.odex bs=1 count=20 skip=52 seek=52 conv=notrunc

10.替换系统odex

最后一步,将/system/framework里的services.odex替换成我们自己制作的feelyou_services_hacked.odex。

 
 
 
 
 

Shell

 
1
dd if=/data/local/tmp/feelyou_services_hacked.odex of=/system/framework/services.odex

替换完成后手机会立刻重启。如果执行这一步,这个时候提示是只读,说明/system没有获取到写入权限,请重复第6步。

11.打开服务

成功重启后,用以下命令打开View Server:
adb shell service call window 1 i32 4939
用以下命令查看View Server是否打开:
adb shell service call window 3
返回的值若是Result: Parcel(00000000 00000001 '........'),那就搞定了!

参考文章:

解决HierarchyViewer不能连接真机的问题的更多相关文章

  1. Android配置----DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹的解决办法

    Android DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹,问题在于data文件夹没有权限,用360手机助手或豌豆荚也是看不见的. 有以下两种解决方法: ...

  2. android DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹的解决办法

    android DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹的解决办法 问题是没有权限,用360手机助手或豌豆荚也是看不见的. 简单的办法是用RE文件管理 ...

  3. XE6 & IOS开发之免证书真机调试(2):连接真机并运行App(有图有真相)

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 连接真机前,请先确保真机 ...

  4. Appium 小白从零安装 ,Appium连接真机测试。

    以下是我个人在初次安装使用Appium时的过程,过程中遇到了一些问题,在这里也一一给出解决办法. Appium安装过程 先安装了 Node.js.在node的官网上下载的exe安装文件. 在node的 ...

  5. Android Studio软件技术基础 —Android项目描述---1-类的概念-android studio 组件属性-+标志-Android Studio 连接真机不识别其他途径

    学习android对我来说,就是兴趣,所以我以自己的兴趣写出的文章,希望各位多多支持!多多点赞,评论讨论加关注. 最近有点忙碌,对于我来说,学习Android开发,是对于我的考验,最近一位大佬发给我一 ...

  6. APPium连接真机输入框中输入的内容与代码中不一致

    今天解决了上一个问题,又碰到了一个新的问题. 问题:连接真机输入框中输入的内容与代码中不一致. 描述: 想实现登录页面输入用户名和密码自动登录,可是在输入用户名和密码的框中输入的内容总是与代码中的不一 ...

  7. Python+Appium自动化测试(2)-appium连接真机启动app

    app自动化测试的第一步,是启动被测app.appium环境搭建好后,我们就可以连接真机启动app了.环境为windows,Appium1.18.0,Android手机,被测app为今日头条app,让 ...

  8. Unity3D连接真机调试教程,可抓断点

    源地址:http://www.unity蛮牛.com/thread-19586-1-1.html <ignore_js_op> 未标题-1.jpg (52.33 KB, 下载次数: 0) ...

  9. appium通过WiFi连接真机进行测试

    http://www.th7.cn/Program/Android/201507/514602.shtml appium通过WiFi连接真机进行测试   2015-07-24 19:43:07CSDN ...

随机推荐

  1. 【转】javascript中this的四种用法

    在函数执行时,this 总是指向调用该函数的对象.要判断 this 的指向,其实就是判断 this 所在的函数属于谁. 在<javaScript语言精粹>这本书中,把 this 出现的场景 ...

  2. Android之Dialog详解

    Android中的对话框形式大致可分为五种:分别是一般对话框形式,列表对话框形式,单选按钮对话框,多选按钮对话框,自定义对话框. 在实际开发中,用系统的对话框会很少,因为太丑了,美工不愿意,多是使用自 ...

  3. Qt设置系统时间(使用SetSystemTime API函数)

    大家都知道Qt中有QDateTime等有关时间与日期的类,类中包含很多成员函数,可以很方便的实现有关时间与日期的操作,比如:想要获得系统当前的时间与日期,可以调用currentDateTime();  ...

  4. mvc EF 数据保存时,报错:”对一个或多个实体的验证失败……“之解决

    在EF5.0添加实体数据到数据库的时候,出现“对一个或多个实体的验证失败.有关详细信息,请参见“EntityValidationErrors”属性这个错误 解决: SaveChanges前先关闭验证实 ...

  5. python和pywin32实现窗口查找、遍历和点击

    Pywin32是一个Python库,为python提供访问Windows API的扩展,提供了齐全的windows常量.接口.线程以及COM机制等等. 1.通过类名和标题查找窗口句柄,并获得窗口位置和 ...

  6. JS之toString方法

    1.JS中几乎每个值都有toString方法,null和undefined除外 2.对于字符串形式的值也可以使用toString()方法,返回该字符串的一个副本 3.toString(radix)方法 ...

  7. centos 6.4 安装视频解码器

    cd /etc/yum.repos.d/ wget http://mirrors.163.com/.help/CentOS6-Base-163.repo yum update rpm -Uhv htt ...

  8. SQL Server 2008 R2[ALTER]列属性修改

    1:向表中添加字段 Alter table [表名] add [列名] 类型 2:  删除字段 Alter table [表名]  drop column [列名] 3:  修改表中字段类型 (可以修 ...

  9. iOS block里的self

    block是可以捕捉上下文的特殊代码块. block可以访问定义在block外的变量,当在block中使用时,它就会为其在作用域内的每个标量变量创建一个副本. 如果通过self拥有一个block,然后 ...

  10. BIND_MISMATCH导致过多VERSION COUNT的问题

    并不是用了绑定变量就一定都会游标共享,下面我们介绍的就是一种例子.BIND_MISMATCH导致VERSION COUNT过多的原因解释: This is due to the bind buffer ...