2025-10-15 14:30:00
通过 MCP (Model Context Protocol) 让 AI 助手直接调用 ADB 命令操作 Android 设备,实现日志查看、应用安装、性能分析等自动化操作。
MCP 是 Anthropic 推出的开放协议,用于连接 AI 助手与外部工具。MCP Server 将特定工具包装成标准化接口,让 AI 能够理解和调用。
架构如下:
1
|
|
1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
创建 adb-mcp-server.js
:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
|
赋予执行权限:
1
|
|
1 2 3 4 |
|
声明服务器名称、版本和支持的能力类型。
每个工具包含三个部分:
示例:
1 2 3 4 5 6 7 8 9 10 11 |
|
MCP 定义两种请求类型:
ListToolsRequest - 列出所有可用工具:
1 2 3 |
|
CallToolRequest - 执行具体工具:
1 2 3 4 |
|
使用 child_process
执行 ADB 命令:
1
|
|
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json
:
1 2 3 4 5 6 7 8 |
|
配置完成后重启 Claude Desktop。
使用 Claude Code 命令行工具添加 MCP Server:
1
|
|
参数说明:
adb
: MCP Server 名称node
: 运行命令adb-mcp-server.js
的完整路径编辑 Gemini CLI 配置文件 ~/.gemini/mcp_config.json
:
1 2 3 4 5 6 7 8 |
|
注:Gemini CLI 的 MCP 配置可能因版本而异,建议以官方文档为准。
编辑 Copilot CLI 配置文件 ~/.github-copilot/mcp_servers.json
:
1 2 3 4 5 6 |
|
注:Copilot CLI 的 MCP 配置可能因版本而异,建议以官方文档为准。
在 Claude 中直接使用自然语言:
1
|
|
1
|
|
1
|
|
1
|
|
Claude 会自动调用对应的 MCP 工具执行操作。
传统方式:
1 2 |
|
使用 MCP:
1
|
|
Claude 自动执行并分析结果。
传统方式:
1 2 |
|
使用 MCP:
1
|
|
1
|
|
Claude 自动处理设备列表和批量安装。
1 2 3 4 5 6 7 8 9 10 11 |
|
执行命令:
1
|
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
确保 ADB 已添加到系统 PATH:
1 2 |
|
使用前确认设备已连接并授权:
1
|
|
如果显示 unauthorized
,需在设备上确认 USB 调试授权。
生产环境应添加:
2025-10-13 08:00:00
最近使用 Claude Code CLI 和 GitHub Copilot CLI 时发现,虽然两者都使用 Claude Sonnet 4.5 模型,但 Claude Code 明显更智能。本文记录性能差异的技术原因。
同模型不等于同性能。Claude Sonnet 4.5 原生支持 200K tokens 上下文和 Extended Thinking,但 Copilot CLI 通过中间层大幅限制了这些能力。
Claude Sonnet 4.5 原生能力:
Copilot CLI 实际限制:
实际影响:
1 2 3 4 5 6 7 8 9 10 11 |
|
8K tokens 约等于 6000 英文单词 或 1500 行代码。Copilot CLI 的小窗口导致频繁的上下文切换和信息丢失。
什么是 Extended Thinking:
允许模型进行深度推理,配置 1K-64K tokens 的”思考预算”,在复杂任务中显著提升表现。
Claude Code CLI 配置示例:
1 2 3 4 5 6 7 |
|
Copilot CLI:
完全不支持此配置,无法启用 Extended Thinking。这是两者智能表现差异的关键原因。
Claude Code CLI:
Copilot CLI:
比喻:
Claude Code 设计用于 跑马拉松(长时间、多步骤任务),Copilot CLI 只能 跑百米(快速交互)。
1
|
|
特点:
代价:
1
|
|
中间层作用:
优点:
代价:
重构 React 前端任务(约 15 个文件):
用户反馈:Copilot CLI 比 Claude Code 慢 5 倍以上。
Claude Code 限制:
1 2 |
|
需要使用 offset 和 limit 分块读取,导致反复工具调用。
Copilot CLI 问题:
1000 行文件经常卡顿
Claude Code:
Copilot CLI:
Claude Code:
Copilot CLI:
Claude Code:
Copilot CLI:
GitHub 社区反馈:
官方承认是”已知的服务器端问题”。
使用语义索引:
1 2 |
|
主动管理上下文:
1 2 |
|
维护 CLAUDE.md:
监控配额:
1
|
|
按任务选模型:
避免大任务接近限制时启动
两者差异的根本原因:
维度 | Claude Code CLI | Copilot CLI |
---|---|---|
上下文窗口 | 200K tokens | ~8K tokens |
Extended Thinking | ✓ 支持 | ✗ 不支持 |
资源策略 | 马拉松 | 百米 |
架构 | 直接访问 | 中间层限制 |
适用场景 | 复杂重构 | 快速迭代 |
Claude Code 提供完整模型能力但速度慢,像让模型”看全局、想得久”。
Copilot CLI 功能受限但集成好,像让模型”看局部、快速答”。
用户反馈的”8K tokens 限制”并非误解,而是 Copilot CLI 的真实约束。这个限制加上 Extended Thinking 缺失,是智能表现差异的核心原因。
实际使用中,许多开发者两者并用:Claude Code 处理复杂任务,Copilot CLI 处理快速交互。
2025-10-12 08:00:00
开发中经常需要排查某个权限是由哪个依赖库引入的,本文记录通过 Gradle daemon 日志快速定位权限来源的方法。
使用以下命令在 Gradle daemon 日志中搜索权限声明:
1
|
|
-n
:显示行号-C 2
:显示匹配行前后各 2 行上下文(关于 grep 上下文参数的详细用法见这篇文章)--include="*.out.log"
:只搜索 .out.log
文件-R
:递归搜索目录~/.gradle/daemon/
:Gradle daemon 日志目录Gradle daemon 是 Gradle 构建系统的后台进程,用于加速构建过程。daemon-*.out.log
文件记录了 daemon 进程的详细输出信息,包括:
1 2 3 4 5 6 7 |
|
每个 Gradle 版本对应一个目录,每次 daemon 启动会生成新的日志文件,文件名中的数字为进程 ID。
1 2 |
|
从日志可以看出:
android.permission.INTERNET
net.butterflytv.utils:rtmp-client:3.0.1
AndroidManifest.xml
第 11 行daemon-77407.out.log
第 132336 行使用 <uses-permission tools:node="remove">
在主 Manifest 中显式移除。
~/.gradle/daemon/
目录2025-10-04 10:00:00
升级 Android targetSDK 至 35 并使用 Gradle 8.0+ 后,遇到了第三方库 namespace 配置问题。
1 2 3 4 |
|
或者类似错误:
1 2 3 4 5 |
|
Android Gradle Plugin 8.0+ 不再支持在 AndroidManifest.xml
中通过 package
属性设置 namespace,要求在 build.gradle
中显式声明。升级 targetSDK 至 35 需要使用 Gradle 8.0+,但很多第三方库(如 react-native-inappbrowser
、appcenter-analytics
等)尚未更新配置,导致构建失败。
在项目根目录的 android/build.gradle
文件中添加以下代码:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
|
此方案包含三个层次的处理:
project.group
并将点号替换为下划线作为 namespacebuildConfig
特性AndroidManifest.xml
中提取 package
属性build.gradle
作为 namespace
AndroidManifest.xml
中的 package
属性这个 task 在每次构建前(preBuild
)自动执行,确保所有第三方库都符合 Gradle 8.0+ 的要求。
build.gradle
和 AndroidManifest.xml
文件node_modules
中生效,不影响源码仓库执行以下命令重新构建项目:
1 2 3 |
|
或在 React Native 项目中:
1
|
|
构建过程中会看到类似输出:
1 2 |
|
如果只需要为缺少 namespace 的库自动设置默认值,可以使用简化版:
1 2 3 4 5 6 7 8 9 10 11 |
|
简化方案不会修改任何文件,仅在内存中设置 namespace,但可能无法解决所有第三方库的问题。
2025-09-28 08:56:00
在 Flutter 开发过程中,很多开发者遇到一个困扰的问题:当使用终端运行 flutter run
命令进行开发时,一旦关闭 Android Studio 或 IntelliJ IDEA,终端中的 flutter run
进程就会自动结束,导致应用停止运行。本文将详细分析这个问题的原因并提供解决方案。
flutter run
启动 Flutter 应用flutter run
进程自动结束,应用停止运行flutter run
进程当 Android Studio 启动时,它会自动管理 ADB(Android Debug Bridge)服务器的生命周期。默认情况下,IDE 会:
这种设计导致即使是通过终端独立启动的 flutter run
进程,也会因为 ADB 服务器的关闭而被迫结束。
1
|
|
当 Android Studio 关闭时,它管理的 ADB 服务器也会关闭,进而导致所有依赖该 ADB 连接的进程(包括终端的 flutter run
)都被终止。
最有效的解决方案是让 Android Studio 使用外部手动管理的 ADB 服务器,而不是自己管理一个实例:
Build, Execution, Deployment
→ Debugger
Android Debug Bridge (adb)
部分Adb Server Lifecycle Management
中选择 Use existing manually managed server
Existing ADB server port
为 5037
(默认端口)这样配置后,Android Studio 不会在启动时接管 ADB 服务器,也不会在关闭时终止它,从而保证终端运行的进程不受影响。
配置完成后,可以通过以下步骤验证:
flutter run
flutter run
是否依然运行如果 flutter run
进程没有被终止,说明配置成功。
通过配置 Android Studio 使用外部手动管理的 ADB 服务器,可以有效解决 IDE 关闭后终端 flutter run
进程自动结束的问题。这种方法的优势在于:
推荐所有 Flutter 开发者采用这种配置方式,特别是那些习惯在终端中运行 flutter run
的开发者。
2025-06-24 10:30:00
排查日志时,常需要定位关键字并带上一两行上下文确认语义。grep
内建的上下文选项可以直接满足需求,不必再手动 sed -n '19,21p'
。
假设想在 app.log
中找出包含 Fatal error
的行,并且同时看到上一行与下一行:
1
|
|
-n
会显示行号,便于定位。-C 1
等价于 --context=1
,表示向前向后各多带 1 行。想多看几行时调整数字即可。输出中,命中的行以冒号分隔行号与内容,上下文行则以短横线 -
连接,快速区分重点。
grep
提供三个粒度化参数:
-C <N>
:两侧各 N 行,是最常用的形式。-B <N>
:只带前 N 行(Before)。-A <N>
:只带后 N 行(After)。例如只关心关键字后面的调用栈,可使用:
1
|
|
再配合 -m 1
(匹配一次后退出)可以缩短复杂日志的搜索时间。
-i
:忽略大小写,处理大小写不一致的告警信息很方便。-E
:启用扩展正则,可直接写 grep -E "(WARN|ERROR)"
。--color=auto
:高亮命中关键字,在终端阅读更直观。将这些参数组合成 Shell 函数,后续排查直接调用。例如在 ~/.bashrc
中定义:
1 2 3 4 |
|
执行 gctx "timeout" service.log 2
,即可得到行号、关键字高亮、上下文行的结果。
-C/-A/-B
是获取上下文的核心选项,记住数字表示行数即可。-n
、--color
、-m
等参数可以提升排查效率。less -R
或 fzf
管道组合,能够在终端中进行二次筛选,让排查体验更顺滑。