跑通第一条 Demo,听起来是开发里最简单的事:把代码下载下来,编译,运行,看到界面或者日志输出就算结束。但真做起来,很多人会卡在看起来完全不合理的地方。Android AIDL Demo 编译通过了,两个应用却连不上;EtherCAT 驱动装完了,设备列表里看不到网卡;GD32F470 的 FreeRTOS Demo 烧进开发板,串口什么都没有;WebRTC Demo 打开页面,本地画面正常,远端一直是黑屏。这类问题绝大多数不在 Demo 本身的代码逻辑,而在环境准备、依赖版本、输入条件和验证方式。下面按实际踩坑顺序拆开:先判断 Demo 类型,再准备环境,然后跑最小样例,最后处理报错和扩展。这篇文章不绑定某一个具体项目,适合刚接触嵌入式、Android、WebRTC,或者任何“照着教程下载 Demo 却跑不起来”的开发者。
1. 跑 Demo 之前,先判断它属于哪一类
拿到一个 Demo,第一件事不是打开 IDE,而是先判断它属于哪一类。不同类型的 Demo,跑通路径差别很大。把类型判错了,后面所有操作都会跑偏。
1.1 纯软件工程:依赖的是 IDE、SDK 和运行环境
纯软件型 Demo 最常见,比如 Android AIDL Demo、iOS 的文字分页排版 Demo、各种 Web 前端 Demo。它们没有特殊硬件,核心依赖是三样:正确的 SDK 版本、正确的编译工具链、正确的运行环境。
Android 项目要看 compileSdk、minSdk 和 Gradle 版本是否匹配。老项目经常遇到“明明代码没问题,但 Gradle 同步失败”的情况,多数是 JDK 版本太高或太低。iOS 项目要看 Xcode 版本、Deployment Target 和模拟器架构,M 系列芯片和 Intel 芯片在部分第三方库上表现不一样。Web 前端项目则要重点看 Node 版本和包管理器版本。
这类 Demo 跑不通,大概率是环境里某个版本对不上,不是代码本身的问题。所以拿到项目第一步不是立刻打开工程,而是先看 README 里写明的版本要求。
1.2 硬件板卡类:关键在驱动、调试器和串口
EtherCAT 驱动安装、GD32F470 FreeRTOS Demo、INA228 Demo 板,都属于硬件相关 Demo。它们的复杂点不在代码,而在硬件链路是否打通:开发板有没有供电、调试器有没有被系统识别、串口驱动装没装、下载工具版本是否支持当前芯片、EtherCAT 主站需要的是哪张网卡。
这类 Demo 的“跑通”不像软件那样显示一个窗口,而是要看串口日志、指示灯、寄存器数值或者设备列表状态。判断标准不统一,这也是很多人烧录成功却认为没成功的原因。比如 GD32F470 的工程烧进去了,但串口助手波特率设置不对,打印出来全是乱码,看着像失败,实际程序已经在跑。
还有一类是原厂工具型 Demo,比如打印设备的原厂 Demo。它们依赖厂商 SDK、设备连接状态和授权信息,很多时候不是代码问题,而是设备没连上、SDK 没有正确初始化、或者授权没有激活。
1.3 联调通信类:至少要有两端,还要有一条通路
还有一类是多个端一起工作,典型代表是 WebRTC Demo 和部分双 App 的 AIDL Demo。它们不能单机单进程验证。
WebRTC 需要两个对端通过信令服务器交换 SDP 和 ICE 候选。本地能出画面不代表信令通了,远端黑屏才是关键判断点。AIDL Demo 需要客户端和服务端两个进程,或者两台设备都安装好,并且 Service 要正确导出、包名和 Action 要匹配、权限要一致。
这类 Demo 排查要按“通路”来看,而不是按“单个程序”来看。任何一个环节断了,结果都表现为“连不上”,但真正断的地方可能和你猜的完全不一样。
| Demo 类型 | 典型例子 | 核心依赖 | 跑通标志 |
|---|---|---|---|
| 纯软件工程 | Android AIDL、iOS 分页排版 | SDK、Gradle/Xcode、Node | 编译安装,界面或日志正常 |
| 硬件板卡 | GD32F470 FreeRTOS、INA228 | 调试器、串口、驱动 | 串口打印、LED、寄存器读数 |
| 联调通信 | WebRTC | 信令服务、双端环境 | 两端画面互通,状态回调正常 |
| 原厂工具 | 打印设备 Demo | 厂商 SDK、设备连接、授权 | 连接设备并输出测试页 |
2. 环境准备阶段,把三件事做在前面
跑 Demo 前先花十分钟准备环境,比跑不起来之后花一小时排查要划算得多。环境准备不是“装个软件就行”,而是要确认版本、设备、网络三件事都处于可用状态。
2.1 工具链和依赖版本,先确认再用
环境准备最好按顺序做,不要跳。先确认当前机器上已经装了什么,再决定补什么。
Android 项目要看 JDK 版本和 Gradle 版本是否匹配。JDK 17 或 21 是当前主流配置,但老项目可能只支持 JDK 8 或 11,直接用新 JDK 会报各种奇怪的编译错误。Python 项目要看 requirements.txt 里的版本约束,Node 项目要看 package.json 里的 engines 字段。嵌入式项目要看编译工具链版本,Keil、IAR、STM32CubeMX、GCC 的版本差异经常导致工程打开后一堆报错。
可以直接用命令确认当前环境:
java -version python --version node --version cmake --version gcc --version如果 README 里写的要求和命令输出对不上,先解决版本差异,再继续。不要把报错提前归给代码。
2.2 驱动与设备连接,不要只看“安装成功”
硬件 Demo 最容易踩的坑,是驱动提示安装成功,但设备没有真正进入可用状态。
EtherCAT 主站需要特定网卡,安装驱动后要到工具的设备列表里看状态。不少工程软件会把识别到的网卡标记为类似 “Install and ready to use devices (for demo use)” 的状态。这代表当前驱动已经识别设备,可以用于跑通演示通信,但要清楚这通常属于演示模式。真正用于实时控制前,还要确认授权是否完整、网卡是否支持实时模式、是否被系统防火墙或虚拟网卡干扰。
再比如 GD32F470 烧录前要确认调试器驱动。CH340、CP210x、J-Link、DAP-Link 的驱动都不同,装错了系统识别不到设备。INA228 这类电流、电压监测 Demo 板,要确认 I2C 或 SPI 总线地址,还要检查上拉电阻、参考电压、测量模式这些配置。很多时候读数全为零,不是芯片坏了,而是地址不对或者采样配置没使能。
判断设备有没有连接成功,可以看系统设备管理器,也可以用命令行:
lsusb # Linux,查看 USB 设备 adb devices # Android 设备是否被识别注意:能看到设备不等于能用。还要看驱动有没有感叹号、串口号是否被其他程序占用、调试器固件是否太旧。Windows 下串口被占用是高频问题,经常是某个串口助手或调试工具提前占用了同一个 COM 口。
2.3 网络、仓库和文件完整性,影响很多隐性问题
很多 Demo 第一次跑,会卡在下载依赖这一步。表面上是编译或运行报错,实际是依赖文件根本没有正确下载。
常见情况有几种:网络不通、仓库地址失效、大文件下载不完整、代理环境导致证书校验失败。这类问题出现时,报错往往是 “Could not resolve”“SSL”“checksum mismatch”“Failed to download”。
处理办法是:
- 重新 clone 或下载,确认压缩包大小和官方说明基本一致。
- 检查 gradle-wrapper.properties、requirements.txt、package-lock.json 里的源地址。
- 大文件用支持断点续传的下载方式,不要只靠浏览器默认下载。
- 确认项目是否需要子模块,很多项目 clone 下来还要执行
git submodule update --init --recursive,漏掉这一步会报 “No such file or directory”。
网络问题不要死磕一个源。换个镜像、换台机器、换根网线,先确认是不是网络本身的问题,再去排查代码。
注意:这里不要一上来就把依赖重装一遍。先看是不是文件不完整或子模块缺失,再看网络和源地址,最后才考虑重装。
3. 跑通 Demo 的标准动作:从最小样例开始
环境准备好之后,正式进入跑通流程。我建议把整个过程拆成四步:读说明、编译、运行、验证。每一步都确认结果正常,再进入下一步。
3.1 先读 README,再进 example 目录,不要急着改代码
拿到任何 Demo,第一件事不是双击工程文件,而是先读 README 或官方说明。重点看三块内容:
- 环境要求:SDK、JDK、Node、Python、编译器版本,以及硬件型号。
- 运行步骤:有些项目要先初始化子模块,有些要先生成配置文件,有些要先安装依赖。
- 目录结构:哪段代码是入口,哪个目录是示例,哪个目录是核心库。
很多项目把“最小可运行示例”放在 example 目录,不会直接把你引到根目录。先跑 example,不要直接去改库代码。改库代码之后出了问题,你很难判断是 Demo 的问题还是自己改出来的问题。
3.2 编译、部署、运行、验证,四步分开看
我一般会按顺序拆成四步,每一步都确认结果再进入下一步:
- 编译:只求没有错误地生成可执行文件、APK、固件或者目标文件。
- 部署:APK 安装、固件烧录、服务启动、依赖服务拉起。
- 运行:启动程序,看界面、日志、串口输出是否出现。
- 验证:确认输出符合预期,而不只是“没报错”。
不要把四步混在一起。很多人卡在“运行没反应”,其实前面编译或部署已经失败,只是被 IDE 忽略了。比如 Android Studio 里 Build 失败,但仍然尝试安装旧 APK;比如 Keil 编译有错误,却仍然执行了 Download,最后烧进去的是上次的旧固件。
每一步都要有明确的成功标准。编译成功看 “BUILD SUCCESSFUL” 或 “0 Errors”;部署成功看设备列表里出现新应用或烧录进度条完成;运行成功看日志或输出文件出现;验证成功看数据符合预期。
3.3 不同类型 Demo 的验证标准
不同 Demo 的“跑通”标准差别很大,这里列几个常见的。
Android AIDL Demo:编译安装后,客户端调用服务端方法,Logcat 里能看到跨进程调用成功的日志,或者界面显示返回值。如果 bindService 返回 false,先看 Service 是否导出、包名和 Action 是否匹配、两个应用的签名与权限是否一致。同一个应用里直接用接口不算真正跑通 AIDL,一定要拆成两个进程验证。
GD32F470 FreeRTOS Demo:烧录后打开串口助手,波特率按工程配置设置,正常情况下能看到任务调度日志,或者 LED 按预期闪烁。如果串口没有任何输出,不要先怀疑程序,先检查串口驱动、波特率、TX/RX 接线有没有接反,再看调试器有没有烧录成功。
INA228 Demo 板:通电后通过 I2C 或 SPI 读取寄存器,能读到电压、电流、功率数值。如果读到的数据全为零或者寄存器无响应,优先查设备地址、总线接线、上拉电阻和测量配置,而不是换芯片。
EtherCAT 驱动 Demo:驱动安装后,在工程软件里能看到网卡进入 ready 状态。设备列表显示为 demo use 时,可以跑通基本通信验证,但要注意这通常不是生产授权。正式项目落地前,要确认许可证、网卡实时性能和从站配置。
WebRTC Demo:打开两个页面,允许摄像头麦克风权限,输入同一个房间号,两端都能看到远端画面。如果只有本地画面,说明信令或 ICE 穿透有问题。看 Console 里 SDP 是否交换成功、ICE candidate 是否为空。本地回环测试可以降低网络变量,先把双端在同一台机器上用两个浏览器标签页跑通,再去试跨设备。
注意:验证 WebRTC 时,不要同时开一堆占用摄像头的程序。先关掉会议软件、录屏工具,确认本机权限正常,再看双端连通状态。
4. 卡住时的排查链路:报错、输入、环境、参数
跑 Demo 卡住了,第一反应不要是“重新下载”“重装环境”或者“把参数调大”。先冷静下来,按固定顺序排查。我自己的排查链路是:现象 -> 输入 -> 环境 -> 参数 -> 工具限制。
4.1 先读报错原文,不要直接改代码
遇到问题先抄报错原文,再决定怎么处理。报错信息本身已经给了线索,直接改代码或重装环境会把真实原因掩盖掉。
报错大致分三类:
- 编译期报错:变量未定义、依赖缺失、SDK 版本不对、链接库缺失。
- 运行期报错:崩溃堆栈、端口占用、连接失败、权限拒绝、设备未找到。
- 逻辑错误:程序没报错,但输出不符合预期。
如果是编译期报错,优先看第一个报错,后面的报错通常由它引发。如果是运行期崩溃,看堆栈头部的异常类型和 cause 字段,不要只看最后一行。很多新手习惯从底部往上翻,结果找到的都是无关紧要的警告。
4.2 按输入、权限、依赖、参数逐层排查
我自己常用的顺序是:现象 -> 输入 -> 环境 -> 参数。
- 现象:是报错、卡住、无输出、还是输出异常?卡住的话,CPU、内存、磁盘有没有变化?
- 输入:文件路径对不对、编码对不对、文件名是否包含空格或中文、输入数据是否为空、文件是否被其他程序占用。
- 环境:依赖版本是否匹配、端口是否被占用、权限是否足够、设备是否在线、驱动是否正常。
- 参数:并发数、超时时间、分辨率、波特率、采样频率、输出目录是否合理。
- 工具限制:当前版本不支持某个格式,或者功能本身有边界。
按这个顺序走,大部分问题能在第 2、3 步解决,真正需要改代码参数的反而少。
比如 EtherCAT 驱动装好后设备列表里没有网卡,先不要怀疑主站软件,先到系统网络适配器里看网卡是否被禁用、有没有其他驱动抢先绑定,再看网卡是否支持实时模式。又比如 GD32F470 烧录后串口无输出,先确认串口驱动和接线,再检查烧录工具是否报告成功,然后才去看代码里的波特率和时钟配置。
4.3 常见报错分类和应对
| 报错关键词 | 常见原因 | 优先排查方向 |
|---|---|---|
| Command not found | 工具链没装,或没加到 PATH | 用 which 或 where 确认命令路径 |
| No such file or directory | 路径错误、子模块缺失、下载不完整 | 检查路径,执行 git submodule update |
| Permission denied | 设备权限、端口权限、文件权限 | 查看权限和用户组,必要时临时提权 |
| SDK location not found | Android SDK 路径未配置 | 检查 local.properties 和环境变量 |
| Address already in use | 端口被占用 | 用 netstat 或 lsof 找占用进程 |
| failed to enumerate | 驱动问题或线材、接口问题 | 换 USB 口、换线、查看设备管理器 |
| Undefined reference | 链接库缺失或路径不对 | 检查 CMakeLists、库搜索路径 |
排查时要关注日志里的时间戳和模块名。日志不是越多越好,关键信息往往藏在被大量重复日志淹没的位置。可以先提高日志级别,或者用关键词过滤,比如搜 “error”“fail”“exception”“timeout”。
如果程序没报错但输出不对,可以先看输入数据。很多“看起来像 Bug”的问题,其实是输入格式和预期不符。比如 INA228 读不到电流数据,先确认输入源是否有电流流过;比如 WebRTC 远端黑屏,先确认双方权限、房间号和网络在同一子网。
5. Demo 跑通之后,怎么从“能跑”变“有用”
跑通一条 Demo,只能说明你成功复制了别人写好的示例。真正有意义的,是把这条 Demo 变成自己能改、能扩展、能复用的东西。
5.1 改参数验证你的理解
跑通只是开始。要真正理解 Demo,改参数是最快的方式。改一个变量,看结果变化,再改回来。不要同时改多个参数,否则你不知道影响来自哪里。
比如调整 WebRTC 的分辨率或码率,观察画面卡顿和延迟变化;把 GD32F470 FreeRTOS Demo 里任务周期从 100ms 改成 500ms,看串口日志打印频率是否跟着变;把 AIDL 跨进程调用频率调高,看 Logcat 里 Binder 事务日志是否变密。
每改一个参数,记录三件事:改了什么、期望什么、实际发生了什么。这个记录习惯以后做项目排错时会非常有用。
5.2 从单条任务走向批量、联调和接口化
Demo 通常只演示单条路径,真实项目要处理的往往是批量、异常和重试。
嵌入式板卡类 Demo:从单次读取改成连续采集,要自己处理采样间隔、缓存、丢包、日志落盘。如果采集频率高,还要考虑缓冲区溢出和任务优先级。
WebRTC 类 Demo:从双端联调改成多人房间,要考虑信令服务器的并发压力、房间状态管理和断线重连。多人场景下 ICE 候选数量会大幅增加,连接建立时间会变长。
Android 类 Demo:从单个 AIDL 服务变成多模块通信,要处理进程重启、服务重连、序列化兼容,以及不同模块生命周期不一致的问题。
如果只是学习,走到单条 Demo 就够。如果要用于工作,建议额外做三件事:加日志、加失败重试、加状态恢复。
5.3 用 AI 工具快速生成新 Demo 骨架
现在不少人会用 Codex、Copilot 这类编程助手来制作 Demo。比较合理的用法是:让 AI 先生成一个最小可运行的骨架,包括项目初始化、依赖文件、入口函数、示例配置。
生成之后不要直接当成品用,要逐段检查:
- 依赖版本是否合理,是不是随便写的 latest。
- 路径是不是真实存在,配置文件和代码里引用的是否一致。
- 接口签名是否符合目标平台规范。
- 示例数据是否覆盖边界情况,比如空值、超长字符串、异常输入。
我的习惯是:让 AI 生成骨架,自己补业务逻辑和测试用例。把它当结对编程的初级助手,而不是当权威答案。AI 能帮你省掉很多写模板的时间,但环境适配和正确性判断还是要自己来。
5.4 把 Demo 整理成自己的工程模板
跑通一个 Demo 后,花一点时间把它整理成自己的模板。下次再遇到同类项目,直接从模板开始,而不是重新踩一遍环境坑。
需要整理的内容包括:
- 环境依赖清单和版本号,写清楚在什么系统上测试过。
- 一条命令或两个步骤能跑起来的脚本。
- 常见问题记录,比如驱动安装、端口占用、权限设置、串口参数。
- 验证标准,明确怎么判断跑通了。
- 输入输出样例,方便以后对照。
这些整理工作看起来琐碎,但实际价值很高。你会发现,很多 Demo 不是跑不通,而是环境、输入和验证方式没有对齐。把流程固定下来,先分类、再准备、后运行、最后排查,第二条 Demo、第三条 Demo 就会快很多。真正落地时最该盯住的,也不是功能列表,而是输入格式、资源占用和失败重试这些容易被忽略的细节。