- 开发工具
- 移动开发
【免费下载链接】stetho
Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.
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-urlconnection:HttpURLConnection网络检查(存在 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,分别通过DefaultDumperPluginsBuilder与DefaultInspectorModulesBuilder装配默认的 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()需要注意两点:
- OkHttp 2.x 也可以工作,但语法略有不同,且必须使用
stetho-okhttp构件(而非stetho-okhttp3)。 - 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):
- 首先发送
DUMP魔数与协议版本(大端序!l整数,当前为1); - 随后发送
enter帧:!+ 参数个数(4 字节大端序)+ 每个参数的长度与 UTF-8 内容; - 之后循环读取结果帧:
- 帧码
1:stdout 数据块; - 帧码
2:stderr 数据块; - 帧码
-:stdin 数据请求(客户端从标准输入读取指定字节数后回传); - 帧码
x:退出码,客户端以该码退出。
- 帧码
这与设备端 Stetho.java 中ProtocolDetectingSocketHandler的按魔法字节分发机制对应:DUMP魔数命中 dumpapp 处理器,GET/POST /dumpapp命中旧版 HTTP 兼容处理器,其余请求交给 DevTools socket 处理器。
默认插件
通过Stetho.initializeWithDefaults初始化时,内置的DefaultDumperPluginsBuilder.finish()会自动装配四个默认插件(见 Stetho.java):
| 插件类 | 命令名含义 | 用途 |
|---|---|---|
HprofDumperPlugin | hprof | 生成 Dalvik 格式堆转储(hprof命令) |
SharedPreferencesDumperPlugin | 查看与编辑 SharedPreferences 数据 | 对应dumpapp-prefs脚本交互 |
CrashDumperPlugin | 触发/查看崩溃信息 | 用于注入与复现崩溃场景 |
FilesDumperPlugin | 文件系统访问 | 查看应用文件目录 |
在dumpapp中执行--list可以列出当前所有可用插件。
dumpapp 查看 SharedPreferences 的运行效果
DumperPlugin接口本身非常轻量(见 DumperPlugin.java):实现getName()返回命令名,实现dump(DumperContext)完成具体输出。接口注释给出了命名建议——命令名属于 CLI 一部分,应易于输入与记忆,避免下划线、大写字母和复数,倾向使用network、logging这类简短名称。
编写自定义 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):
Console、Debugger、Runtime(默认使用RhinoDetectingRuntimeReplFactory,自动探测是否引入了stetho-js-rhino);DOM、CSS:基于Document模型,默认文档提供者为 Android View 层级(AndroidDocumentProviderFactory,要求 API 级别达到 AndroidDocumentConstants.MIN_API_LEVEL);DOMStorage、Network、Page、HeapProfiler、Inspector、Profiler、Worker;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 一键式堆转储脚本,其完整流程为:
- 在设备上调用
dumpapp hprof -生成 Dalvik 格式的 hprof 并通过 stdout 流式下载到本地临时文件; - 使用
hprof-conv将 Dalvik 格式转换为标准 hprof 格式; - 默认输出到当前目录的
out.hprof(可通过第一个参数自定义输出文件名); - 生成的 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()、importClass、importPackage等内建能力,也可以通过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.
相关推荐
MNN MnnLlmChat dumpapp 命令指南:基于 Stetho 的 Android LLM 应用调试工具箱
MNN MnnLlmChat dumpapp 命令指南:基于 Stetho 的 Android LLM 应用调试工具箱 dumpapp 是 MnnLlmChat
人工智能大模型推理引擎深度学习本地部署模型量化模型优化多模态计算机视觉嵌入式stetho-js-rhino:为 Stetho 注入 Rhino JavaScript 控制台,在 Chrome DevTools 里实时调试 Android 应用
stetho js rhino:为 Stetho 注入 Rhino JavaScript 控制台,在 Chrome DevTools 里实时调试 Android
开发工具移动开发Boostnote 调试实战指南:使用 Chrome DevTools 与 VS Code 调试 Electron 应用
Boostnote 调试实战指南:使用 Chrome DevTools 与 VS Code 调试 Electron 应用 导读 Boostnote 是一款基于
知识管理桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考