Stetho 使用与扩展指南:用 Chrome DevTools 与 dumpapp 深度调试 Android 应用
2026/9/23 4:48:36 网站建设 项目流程
  • 开发工具
  • 移动开发

【免费下载链接】stetho

Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.

项目地址:https://gitcode.com/gh_mirrors/st/stetho
点击查看免费下载

Stetho 是面向 Android 应用的调试桥(debug bridge),接入后开发者可以在 Chrome 桌面浏览器的开发者工具中原生查看应用的视图层级、网络请求、SQLite 数据库、SharedPreferences 等运行时内部状态,并通过可选的dumpapp命令行工具以脚本化方式操作应用内部数据。本文以仓库根目录的 README.md 为主线,结合 Stetho.java 等核心源码与 scripts/dumpapp 等配套脚本,完整讲解从依赖接入、初始化配置到网络检查、自定义 dumpapp 插件与内存快照的实战全流程。

Stetho 是什么:Android 应用的调试桥

Stetho 是一个面向 Android 应用的调试桥。启用后,开发者可以直接使用 Chrome 桌面浏览器原生自带的 Chrome Developer Tools 功能对应用进行调试,无需在应用内集成任何自定义 UI。同时,开发者还可以选择启用可选的dumpapp工具——它提供了一个功能强大的命令行接口,用于访问应用内部状态。

完成下述设置步骤后,只需启动应用,然后在电脑浏览器中打开chrome://inspect,点击 "Inspect" 按钮即可开始调试。

Chrome 设备发现页面

从架构上看,Stetho 在应用进程内启动了一个基于 Android LocalSocket 的本地服务,其 socket 地址以_devtools_remote结尾(Chrome 识别该魔法后缀即会启动设备发现流程,见 Stetho.java)。adb 将设备端该 abstract socket 转发到宿主机后,Chrome 与 dumpapp 客户端即可通过该通道与应用的调试服务通信。

快速接入:下载与依赖配置

获取依赖

可以从发布页下载最新 JAR,也可以通过构建工具直接依赖。主模块坐标如下:

implementation 'com.facebook.stetho:stetho:1.6.0'

或使用 Maven:

<dependency> <groupId>com.facebook.stetho</groupId> <artifactId>stetho</artifactId> <version>1.6.0</version> </dependency>

只有主stetho依赖是严格必需的;根据功能需要,还可以选择引入以下网络辅助模块:

implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'

或:

implementation 'com.facebook.stetho:stetho-urlconnection:1.6.0'

如需在 Chrome 的 Console 面板中启用 JavaScript 控制台,可以额外引入:

implementation 'com.facebook.stetho:stetho-js-rhino:1.6.0'

关于如何定制 JavaScript 运行时,详见 stetho-js-rhino 说明文档。

组合使用

  • stetho+stetho-okhttp3:OkHttp 3.x 网络检查(最简路径,见下文);
  • stetho+stetho-urlconnectionHttpURLConnection网络检查(存在 gzip 相关的注意事项);
  • stetho+stetho-js-rhino:Console 面板 JavaScript 交互;
  • 全部模块可由 stetho-sample 示例项目 综合演示。

初始化:Application 类与 AndroidManifest 注册

Stetho 的接入设计为对绝大多数现有 Android 应用“无缝且直接”。集成发生在Application类的onCreate()中,最简单的初始化只需一行调用:

public class MyApplication extends Application { public void onCreate() { super.onCreate(); Stetho.initializeWithDefaults(this); } }

同时必须确保MyApplication已在AndroidManifest.xml中注册为应用入口,否则chrome://inspect/#devices中不会出现 "Inspect" 按钮:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...> <application android:name="MyApplication" ...> </application> </manifest>

需要注意,initializeWithDefaults会启用大部分默认配置,但不会启用一些额外钩子,其中最重要的是网络检查(network inspection),需要按下一节的方式单独启用。

从源码看,Stetho.initializeWithDefaults(Context)内部构造了一个Initializer,分别通过DefaultDumperPluginsBuilderDefaultInspectorModulesBuilder装配默认的 dumpapp 插件与 DevTools 协议模块(见 Stetho.java)。Stetho.initialize(...)会先尝试通过ActivityTracker自动追踪 Activity(在较低 API 级别上不可用时会在日志中提示需要手动调用ActivityTracker方法,见 Stetho.java),随后启动本地监听服务。服务的创建采用了懒加载机制(LazySocketHandler),大部分初始化工作延迟到第一个 socket 连接到达时才执行,因此即使低端机型也能安全地用于 debug 构建而不明显影响性能(见 Stetho.java 的类注释)。

启用网络检查

方式一:OkHttp 3.x(推荐)

如果使用 OkHttp 3.x 系列,可以通过 Interceptors 机制自动挂接现有请求栈。这是当前最简单直接的网络检查开启方式:

new OkHttpClient.Builder() .addNetworkInterceptor(new StethoInterceptor()) .build()

需要注意两点:

  1. OkHttp 2.x 也可以工作,但语法略有不同,且必须使用stetho-okhttp构件(而非stetho-okhttp3)。
  2. Interceptor 添加顺序:由于拦截器可以修改请求与响应,请将 Stetho 拦截器放在所有其他拦截器之后,以获得对网络流量的准确视图。

从 StethoInterceptor.java 的源码可以看到它的工作方式:每次请求生成唯一requestId,调用NetworkEventReporter.requestWillBeSent(...)上报请求;请求完成后通过responseHeadersReceived(...)上报响应头,再用interpretResponseStream(...)包装响应体并配合DefaultResponseHandler将响应体内容(含解压后的实体)上报给 DevTools 端(见 StethoInterceptor.java)。源码中还显式检查了chain.connection()是否为 null——如果为 null 会抛出IllegalStateException并提示 “did you use addInterceptor instead of addNetworkInterceptor?”,这正是必须使用addNetworkInterceptor而非addInterceptor的原因(见 StethoInterceptor.java)。

Chrome DevTools 网络面板中的 Stetho 网络检查

方式二:HttpURLConnection

如果使用HttpURLConnection,可以通过StethoURLConnectionManager辅助完成集成,但这种方式存在一些注意事项:

  • 必须显式在请求头中添加Accept-Encoding: gzip,并手动处理压缩响应,Stetho 才能正确上报压缩后的负载大小。

StethoURLConnectionManager的核心实现StethoURLConnectionManagerImpl提供了preConnect(...)postConnect()httpExchangeFailed(...)interpretResponseStream(...)四个关键钩子,分别对应请求发送前、响应头接收、交换失败与响应体解析等阶段(见 StethoURLConnectionManagerImpl.java)。源码注释特别指出:现代 Android 上的HttpURLConnection(底层由 OkHttp 驱动)在透明处理解压时会剥掉Content-Encoding头,此时将无法正确上报压缩后的大小;调用方可以禁用该透明行为,让 Stetho 重新拿到原始Content-Encoding以正确处理。

更完整的网络集成示例参见 stetho-sample 示例项目。

使用 dumpapp 命令行工具

dumpapp是 Stetho 提供的命令行接口,通过 adb 转发通道与应用内运行的 dumpapp 服务通信。仓库内置了配套的 Python 客户端脚本 scripts/dumpapp,可直接运行:

./scripts/dumpapp

常用参数与环境变量

参数 / 环境变量作用说明
-p <process>/--process <process>指定目标进程对应应用包名,脚本会将其格式化为stetho_<process>_devtools_remote的 abstract socket 名称并连接(见 stetho_open.py)
STETHO_PROCESS指定目标进程(环境变量形式)未传-p时的回退方案,见 scripts/dumpapp
ANDROID_SERIAL指定目标设备未设置时回退到 adb 的任意传输(host:transport-any
ANDROID_ADB_SERVER_PORT/ADB_SERVER_SOCKET指定 adb 服务端口默认端口5037;仅支持tcp:形式的 socket 规范,见 stetho_open.py

与 dumpapp 服务的协议交互

dumpapp客户端与设备端服务采用帧协议通信(见 scripts/dumpapp):

  1. 首先发送DUMP魔数与协议版本(大端序!l整数,当前为1);
  2. 随后发送enter帧:!+ 参数个数(4 字节大端序)+ 每个参数的长度与 UTF-8 内容;
  3. 之后循环读取结果帧:
    • 帧码1:stdout 数据块;
    • 帧码2:stderr 数据块;
    • 帧码-:stdin 数据请求(客户端从标准输入读取指定字节数后回传);
    • 帧码x:退出码,客户端以该码退出。

这与设备端 Stetho.java 中ProtocolDetectingSocketHandler的按魔法字节分发机制对应:DUMP魔数命中 dumpapp 处理器,GET/POST /dumpapp命中旧版 HTTP 兼容处理器,其余请求交给 DevTools socket 处理器。

默认插件

通过Stetho.initializeWithDefaults初始化时,内置的DefaultDumperPluginsBuilder.finish()会自动装配四个默认插件(见 Stetho.java):

插件类命令名含义用途
HprofDumperPluginhprof生成 Dalvik 格式堆转储(hprof命令)
SharedPreferencesDumperPlugin查看与编辑 SharedPreferences 数据对应dumpapp-prefs脚本交互
CrashDumperPlugin触发/查看崩溃信息用于注入与复现崩溃场景
FilesDumperPlugin文件系统访问查看应用文件目录

dumpapp中执行--list可以列出当前所有可用插件。

dumpapp 查看 SharedPreferences 的运行效果

DumperPlugin接口本身非常轻量(见 DumperPlugin.java):实现getName()返回命令名,实现dump(DumperContext)完成具体输出。接口注释给出了命名建议——命令名属于 CLI 一部分,应易于输入与记忆,避免下划线、大写字母和复数,倾向使用networklogging这类简短名称。

编写自定义 dumpapp 插件

自定义插件是扩展 dumpapp 系统的首选方式,可以在配置阶段轻松加入。将初始化步骤替换为:

Stetho.initialize(Stetho.newInitializerBuilder(context) .enableDumpapp(new DumperPluginsProvider() { @Override public Iterable<DumperPlugin> get() { return new Stetho.DefaultDumperPluginsBuilder(context) .provide(new MyDumperPlugin()) .finish(); } }) .enableWebKitInspector(Stetho.defaultInspectorModulesProvider(context)) .build())

其中enableDumpapp传入自定义的DumperPluginsProvider,返回的插件集合会替换/扩展默认插件——DefaultDumperPluginsBuilder.provide(...)是在默认四个插件基础上追加,而remove(name)可以移除指定插件(见 Stetho.java)。enableWebKitInspector则负责启用 Chrome DevTools 协议侧的模块集合。

一个真实的插件示例

stetho-sample 示例项目 中的 HelloWorldDumperPlugin.java 完整展示了插件的编写规范:

public class HelloWorldDumperPlugin implements DumperPlugin { private static final String NAME = "hello"; @Override public String getName() { return NAME; } @Override public void dump(DumperContext dumpContext) throws DumpException { PrintStream writer = dumpContext.getStdout(); Iterator<String> args = dumpContext.getArgsAsList().iterator(); String helloToWhom = ArgsHelper.nextOptionalArg(args, null); if (helloToWhom != null) { doHello(dumpContext.getStdin(), writer, helloToWhom); } else { doUsage(writer); } } // ... }

要点总结:

  • 通过dumpContext.getStdout()向调用方输出结果;
  • 通过dumpContext.getArgsAsList()获取命令行参数,配合ArgsHelper解析可选参数;
  • 参数缺失时输出用法说明;<name>-时从 stdin 读取名字,演示了标准输入的交互;
  • 遇到非法输入抛出DumpUsageException,其消息会直接展示给用户且脚本以非零码退出;
  • 插件名hello遵循“简短、小写、易输入”的命名约定。

该示例工程还提供了APODDumperPlugin以及通过ContentProviderDatabaseDriver将系统日历 ContentProvider 暴露到 Chrome Database 面板的扩展用法(见 SampleDebugApplication.java)。

深入:Stetho 的默认初始化装配

Stetho.initializeWithDefaults背后的默认装配可以从 Stetho.java 的源码确认。

默认 DevTools 模块

DefaultInspectorModulesBuilder.finish()会按顺序装配以下 Chrome DevTools 协议域模块(见 Stetho.java):

  • ConsoleDebuggerRuntime(默认使用RhinoDetectingRuntimeReplFactory,自动探测是否引入了stetho-js-rhino);
  • DOMCSS:基于Document模型,默认文档提供者为 Android View 层级(AndroidDocumentProviderFactory,要求 API 级别达到 AndroidDocumentConstants.MIN_API_LEVEL);
  • DOMStorageNetworkPageHeapProfilerInspectorProfilerWorker
  • Database:在满足最低 API 级别时启用,默认注入SqliteDatabaseDriver(数据库文件定位默认使用DefaultDatabaseFilesProvider,连接管理使用DefaultDatabaseConnectionProvider),并通过provideDatabaseDriver(...)支持追加自定义驱动(如示例中的ContentProviderDatabaseDriver),通过excludeSqliteDatabaseDriver(true)可禁用默认 SQLite 驱动。

Chrome DevTools 中查看应用 SQLite 数据库

进程与 socket 命名

初始化时创建的 LocalSocketServer 使用AddressNameHelper.createCustomAddress("_devtools_remote")构造地址,最终形式为stetho_<process>_devtools_remote(见 stetho_open.py 中对该格式的正则解析与拼接逻辑)。这也解释了 dumpapp 脚本为什么需要-p <包名>:adb 通过localabstract:stetho_<包名>_devtools_remote精确转发到目标进程的调试服务(见 stetho_open.py)。

内存快照:hprof 转储脚本

仓库还提供了 scripts/hprof_dump.sh 一键式堆转储脚本,其完整流程为:

  1. 在设备上调用dumpapp hprof -生成 Dalvik 格式的 hprof 并通过 stdout 流式下载到本地临时文件;
  2. 使用hprof-conv将 Dalvik 格式转换为标准 hprof 格式;
  3. 默认输出到当前目录的out.hprof(可通过第一个参数自定义输出文件名);
  4. 生成的 hprof 可以用 Eclipse MAT 等标准内存分析工具深入分析。
./scripts/hprof_dump.sh [OUTFILE]

JavaScript 控制台(stetho-js-rhino)

引入stetho-js-rhino依赖后,Stetho 会自动检测并在 Console 面板启用 JavaScript 运行时(基于 Mozilla Rhino 的解释执行模式,因为 Android 运行 Dalvik 字节码,无法使用 Rhino 的 JVM 字节码即时生成优化)。默认作用域包含console.log()importClassimportPackage等内建能力,也可以通过JsRuntimeReplFactoryBuilder绑定变量、类、包与函数,详见 stetho-js-rhino/README.md。

参与贡献与许可

Stetho 遵循 MIT 许可证(见 LICENSE)。如果希望为项目贡献力量,请参阅 CONTRIBUTING.md 中的贡献指南。

小结

本文以 README.md 为骨架,完整梳理了 Stetho 的接入路径:通过一行Stetho.initializeWithDefaults(this)即可获得 Chrome DevTools 对视图、数据库、网络等维度的原生调试能力;通过Stetho.newInitializerBuilder(...)可以按需装配 dumpapp 自定义插件与 DevTools 模块;通过 scripts/dumpapp 与 scripts/hprof_dump.sh 可以在命令行完成状态查看、数据注入与堆转储等操作。无论是快速接入还是深度定制,stetho-sample 示例项目 都是最直接的参考实现。

  • 开发工具
  • 移动开发

【免费下载链接】stetho

Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.

项目地址:https://gitcode.com/gh_mirrors/st/stetho
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询