

WebView 是一个客户端浏览器控件，可以实现加载并渲染网页的逻辑。但是这个控件并不能完全同等于浏览器，而且我们页面的一些行为会依赖客户端的交互所以我们需要在 WebView 环境中进行调试。下面我就来说一说简单的 WebView 调试方法。

## 抓包

抓包即我们查看下 WebView 中的所有网络请求，在很多无法获取到机器的时候非常有用。通常页面行为不正常往往是接口请求的参数不正确，或者是接口返回的数据有异常。甚至于页面行为存在打点，根据打点请求来判断行为是否正常。通过这种“望闻问切”的方式，有些问题能够浮出水面。市面上抓包软件很多，Windows 上大家一般都是用 [Fiddler][1], Mac 上则使用 [Charles][2]，还有其它的这里就不一一列举了。不过软件很多原理确实一样，简单的说来则是使用 HTTP 代理将所有的请求转发到软件记录本次 HTTP 请求的相关数据。

首先我们需要保证手机和电脑在同一个局域网中，软件中开启 Proxy 配置，这里以 Charles 为例，如图勾选"Enable transparent HTTP Proxying"即可。然后手机 WiFi 上配置 HTTP 代理 IP 为你的电脑 IP，端口为刚才软件中配置的端口（默认8888）。配置完后如无问题就可以在软件中看到请求流了。我们可以类似于 Chrome 开发者工具中的 Network 一样详细的查看请求的请求报文和响应报文。

![Charles Enable Proxy][3]

<!-- m o r e -->

由于代理的方式本质上属于中间人劫持，所以这里还有一个需要注意的是如果是 HTTPS 的网站抓包的话需要在手机端安装抓包软件的 SSL 证书。以 Charles 为例，连接上 Charles 后访问 http://chls.pro 即可获取 SSL 证书。iOS 会自动进入安装步骤，大部分 Android 机需要进入设置内的安全选项中从SD卡上安装证书。证书安装 OK 之后我们就可以正常的对 HTTPS 的请求进行抓包了。

## 调试

当抓包的数据无法定位问题的时候，我们就需要使用更强力的 debug 方法了。本方法的原理是通过一定的方法获取到类似 Chrome 开发者工具的能力，可以查看并修改所有日志的输出、DOM 的结构与样式等功能。根据环境和客户端情况，实现的方法有很多种，下面我来一一说明。

### Android Chrome

如果你需要调试的 Android 手机版本 >= 4.4，则推荐使用 `chrome://inspect` 的方式进行调试，它能为 WebView 带来原生的开发者工具，可以方便的对代码进行断点调试。该方法需要满足一下三个条件才能使用：

1. Android 4.4+
2. 手机上开启允许 USB 连接设备进行调试
3. 客户端开启 WebView debug 模式

```java
//开启 webview 的 debug 模式
webview.setWebContentsDebuggingEnabled(true);
```

当满足以上要求之后，访问 `chrome://inspect`，页面将显示您的设备上已启用调试的 WebView 列表。要开始调试，请点击您想要调试的 WebView 下方的 inspect。像使用远程浏览器标签一样使用开发者工具。

![Chrome Inspect Webview][4]  

图片来自[远程调试 Webview][5]

本方法需要注意的是有同学可能第一次访问的时候会白页，这是因为开发者工具本质上是一个网页，会加载 Google 相关的资源，这些资源被大陆屏蔽，需要翻墙解决。

### iOS Safari


如果你手机上安装的是 DEBUG 版应用，那么推荐使用 Safari 来调试，它能为 WebView 带来原生的开发者工具，可以方便的对代码进行断点调试。该方法需要满足一下三个条件才能使用：

1. Mac: Safari -> 偏好设置 -> 高级 -> 在菜单栏中显示“开发”菜单勾选
2. iOS: 设置 -> Safari -> 高级 -> Web检查器打开
3. 最重要的是 App 必须开启 DEBUG 模式

由于iOS有签名校验机制，真机正式包不允许Safari Debug，所以安装在真机上的包必须是测试签名打的包。需要联系客户端将我们 iOS 设备的 ID 写入到可信任设备列表中，然后使用 iTunes 安装客户端提供的测试包即可。当满足以上要求后，就可以在 Safari -> 开发中看到自己的设备以及 WebView 中网页，点击后即可开启对应页面的 Inspector，可以用来进行断点调试。

![Safari Develper][6]

![Safari Inspector][7]

图片来自[使用 Safari 对 WebView 进行调试][8]

### weinre

当系统版本或者未开启 debug 模式导致上面的方法不可用时，可以考虑使用 [weinre][9]。weinre 通过在页面中插入一段脚本，将页面的所有行为发送到服务上。首先我们需要安装并启动服务：

```shell
npm install -g weinre
weinre --httpPort 8000
```

![weinre][10]

图片来自[用Weinre远程调试移动网页][11]

访问 `http://localhost:8000` 按照页面提示将 debug 脚本插入到页面中。访问页面后就会发现 winere 页面中出现了对应的请求记录，点击该记录即可跳到如下页面。可以看到这个就是一个网页版的开发者工具，可以方便的查看网络请求，控制台执行代码以及样式修改等。不过受限于原理，断点调试功能无法提供。

![weinre][12]

图片来自[用Weinre远程调试移动网页][13]

### eruda

如果启动服务不方便的话，也可以采用 eruda 等方式。类似于 weinre 方法，该方法也是在页面内插入 JS 脚本将所有的数据输出到页面内的一个迷你版开发者工具中。目前市面上类似的工具非常多，不过方法都差不多，这里以 [eruda][14] 为例。页面插入脚本后点击页面中的工具按钮即可在当前页弹出 mini DevTool，可以看到所有的请求和日志等。

![eruda][15]

## 微信 WebView 调试

由于微信内查看网页的需求特别大，所以这里将微信 WebView 的调试方法单列了出来。正常来说你可以使用[微信开发者工具][16]来在电脑端进行网页与微信的调试。当这种情况无法满足，你需要在真机上排查问题时，你需要使用腾讯 x5开发的 [TBS Studio][17] 进行调试。它本质上和 `chrome://inspect` 方法类似，只是它为线上的微信包提供了 debug 模式，并将操作简单化。具体的使用方法可以参考官方文档：https://x5.tencent.com/tbs/guide/debug/season1.html

![TBS Studio][18]

## 总结

目前市面上常见的 WebView 调试的方法大概就这些，还有一些是基于以上方法的集成和进化。如果 `chrome://inspect` 和 Safari 方式可以使用，这无疑是最优解，不过其它几种也不是没有使用场景，大家针对自己的需求选择对应的调试方式即可。

另外有时候用户的环境我们以上所有方法都没办法使用，而问题又不太好排查的时候，我们可以考虑记录用户交互后的页面 HTML 并发送给服务端根据 HTML 页面的情况来调试。因为用户能感知到的不正常都会在 HTML 中表现出来，通过记录用户也可以获取到用户的交互逻辑，后续通过回放用户行为方便我们排查问题。

**扩展阅读：**

- [《远程调试 WebView》][19]
- [《weinre入门手册》][20]
- [《移动端开发调试》][21]


  [1]: https://www.telerik.com/fiddler
  [2]: https://www.charlesproxy.com/
  [3]: https://imnerd.org/assets/migration/p0.ssl.qhimgs4.com/t01db4f4976265327d5.jpg
  [4]: https://imnerd.org/assets/migration/404.png?url=https%3A%2F%2Fdevelopers.google.cn%2Fweb%2Ftools%2Fchrome-devtools%2Fremote-debugging%2Fimgs%2Fwebview-debugging.png?hl=zh-cn
  [5]: https://developers.google.cn/web/tools/chrome-devtools/remote-debugging/webviews?hl=zh-cn
  [6]: https://imnerd.org/assets/migration/p4.ssl.qhimg.com/t01e52f17dca3319444.png
  [7]: https://imnerd.org/assets/migration/p4.ssl.qhimg.com/t01f236b19778f1ce74.png
  [8]: http://www.saitjr.com/ios/ios-user-safari-debug-webview.html
  [9]: http://people.apache.org/~pmuellr/weinre/
  [10]: https://imnerd.org/assets/migration/st.imququ.com/static/uploads/2012/03/2012-03-14_22-59-28.png
  [11]: https://imququ.com/post/remote-debugging-with-weinre.html
  [12]: https://imnerd.org/assets/migration/st.imququ.com/i/webp/static/uploads/2012/03/m_2012-03-14_23-06-21.png.webp
  [13]: https://imququ.com/post/remote-debugging-with-weinre.html
  [14]: https://github.com/liriliri/eruda
  [15]: https://camo.githubusercontent.com/20daebfb92bbd00c24ecb5e3b7e295f0ca7fea6f/687474703a2f2f37786e327a792e636f6d312e7a302e676c622e636c6f7564646e2e636f6d2f65727564615f73637265656e73686f74342e6a7067
  [16]: https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html
  [17]: https://x5.tencent.com/tbs/guide/debug/season1.html
  [18]: https://imnerd.org/assets/migration/x5.tencent.com/tbs/img/article/debug2.png
  [19]: https://developers.google.cn/web/tools/chrome-devtools/remote-debugging/webviews?hl=zh-cn
  [20]: https://github.com/nupthale/weinre
  [21]: http://yujiangshui.com/multidevice-frontend-debug/
