利用ADB命令操控测试机:短信、电话、定位全攻略

📅 发布时间:2026/7/8 19:36:51 👁️ 浏览次数:
利用ADB命令操控测试机:短信、电话、定位全攻略
1. 为什么你需要掌握ADB操控测试机如果你是一名移动应用开发者或者经常和安卓设备打交道那么“测试”这个词对你来说一定不陌生。我们开发一个App尤其是涉及通讯、地图、社交这些功能时免不了要反复测试短信接收、电话接听、位置变化这些场景。手动操作那太痛苦了。想象一下为了测试一个“根据位置推送附近商家”的功能你需要抱着手机满大街跑或者为了验证短信验证码的接收逻辑你得找另一部手机不停地给自己发短信。效率低不说还很难模拟一些边界情况比如在信号极差的地方收到短信或者突然接到一个国际长途。这时候ADBAndroid Debug Bridge就是你手中的“瑞士军刀”。它远不止是用来安装应用或者查看日志的。通过它你可以像魔法师一样远程操控你的测试机精准地发送短信、模拟来电、甚至让手机“瞬间移动”到世界任何一个角落。我刚开始接触自动化测试时也是手动点点点直到有一次需要测试一个涉及大量地理位置切换的场景差点跑断腿才痛定思痛深入研究ADB的这些“隐藏技能”。掌握了它们你就能把重复、枯燥的测试任务交给脚本自己则专注于更核心的逻辑和体验优化。这不仅仅是提升效率更是让测试过程变得可重复、可编程、甚至可集成到CI/CD流水线中的关键一步。所以无论你是想提升个人开发效率还是为团队搭建自动化测试框架学会用ADB命令操控测试机都是一个性价比极高的投资。接下来我就把自己这些年踩过坑、验证过的方法掰开揉碎了讲给你听保证小白也能轻松上手。2. 环境准备搭好你的“操作台”工欲善其事必先利其器。在开始“施法”之前我们得先把“魔法杖”——ADB环境给准备好。这个过程不复杂但一步错可能步步错我见过不少新手在这里卡住。2.1 安装与配置ADB首先你得把ADB工具弄到你的电脑上。最常见的方式是通过安卓SDK。你可以去安卓开发者官网下载“Command line tools only”版本解压后找到platform-tools文件夹里面就有adb这个可执行文件。我更推荐一个更简单的方法对于Mac用户直接用Homebrew安装brew install android-platform-tools对于Windows用户可以下载独立的ADB工具包网上有很多整理好的绿色版本。安装好后关键一步是配置环境变量。你需要把adb命令所在的目录路径比如C:\Users\YourName\platform-tools或/Users/YourName/Library/Android/sdk/platform-tools添加到系统的PATH环境变量里。这样你才能在终端或命令行的任意位置直接输入adb命令。验证是否成功很简单打开你的终端Windows是CMD或PowerShell输入adb version然后回车。如果能看到一串版本号信息恭喜你第一步成功了如果提示“不是内部或外部命令”那就回头检查一下环境变量设置得对不对路径有没有写错。2.2 连接测试机并开启调试环境搭好了接下来要让电脑和手机“握手”。你需要一部安卓手机作为测试机。在手机的“设置”里找到“关于手机”连续点击“版本号”7次这会激活“开发者选项”。然后进入新出现的“开发者选项”找到并开启“USB调试”。这个开关是ADB连接手机的钥匙。用USB数据线把手机连上电脑。此时手机屏幕上可能会弹出一个对话框询问“是否允许USB调试”一定要勾选“始终允许”并点击确定。第一次连接时这个步骤必不可少。回到电脑的终端输入adb devices并回车。这个命令会列出所有已连接的设备。如果你看到类似List of devices attached下面有一行设备ID后面跟着device字样比如abc123def device那就表示连接成功了。如果显示的是unauthorized说明手机上的授权对话框你没点确定如果什么都没显示检查一下数据线、USB端口或者试试重启ADB服务adb kill-server然后adb start-server。这里有个小技巧无线连接。有时候拖着根线很不方便特别是测试多台设备时。你可以先用USB线连接一次然后执行adb tcpip 5555命令这个命令会让手机在5555端口监听TCP/IP连接。接着拔掉USB线确保手机和电脑在同一个Wi-Fi网络下执行adb connect 手机IP地址:5555比如adb connect 192.168.1.100:5555就能实现无线调试了非常方便。我自己的测试机就常年开着无线ADB随时可以远程操作。3. 发送短信模拟消息接收的利器测试短信相关功能比如验证码登录、营销消息推送、会话列表刷新如果每次都靠真手机发成本高且不可控。用ADB模拟发送短信就能完美解决这个问题。3.1 基础命令sms send最直接的方法是使用adb shell am命令来启动一个发送短信的Intent。命令格式如下adb shell am start -a android.intent.action.SENDTO -d sms:目标手机号 --es sms_body “短信内容”例如你想给号码13800138000发送内容为“您的验证码是123456”的短信命令就是adb shell am start -a android.intent.action.SENDTO -d sms:13800138000 --es sms_body “您的验证码是123456”执行后你的测试机会自动跳转到短信应用并且收件人和内容都已经填好处于待发送状态。注意这个方法只是帮你填充了信息最后一步“发送”按钮需要你手动点击或者结合UI自动化工具如UiAutomator来完成点击。这对于需要观察发送界面UI变化的测试很有用。但更多时候我们希望在后台“静默”地接收一条短信完全模拟真实基站发来的效果。这就需要用到你原始资料里提到的telnet方式但那是针对安卓模拟器的。对于真机我们有一个更通用的“黑科技”使用service call命令直接调用系统的短信服务。不过这个命令因手机系统和版本差异很大一个相对稳定的方法是借助一个隐藏的广播接收器。我们可以发送一个特定的广播来模拟短信到达adb shell am broadcast -a android.provider.Telephony.SMS_RECEIVED --es sender “13800138000” --es message “您的验证码是654321”这个命令会广播一条短信接收事件很多短信应用都会捕获这个广播并显示出来就像真的收到短信一样。我在测试一些拦截骚扰短信的App时就经常用这个方法来构造测试数据。3.2 进阶技巧与实战坑点掌握了基础命令我们来看看怎么玩出花来。首先发送超长短信或特殊字符。短信有长度限制通常70个汉字或160个英文字符为一条超长会自动分割。用ADB发送时直接写入长文本即可手机会自动处理分割。对于特殊字符比如emoji或者换行符\n在命令行中需要正确转义。我建议把短信内容写在一个文本文件里然后用命令读入避免转义麻烦。其次模拟不同发件人号码和短信中心。有时候测试需要验证对银行短信号码如95588的识别或者测试国际号码8613800138000的格式。在service call或广播方法中修改sender参数即可。你甚至可以模拟一个不存在的号码来测试App的容错性。这里我踩过一个坑短信发送的时序问题。在自动化测试脚本中如果你连续快速发送多条短信可能会因为系统处理不及而导致后一条覆盖前一条或者顺序错乱。我的经验是在两条发送命令之间加上一点延迟sleep比如1-2秒。在Shell脚本中可以这样写adb shell “命令1” sleep 2 adb shell “命令2”另一个实战场景是测试短信轰炸和拦截。你可以写一个简单的Shell脚本循环快速向测试机发送大量内容相似的短信来测试手机自带或第三方安全软件的拦截功能是否生效。这比找一堆真手机来发要高效得多。最后记得测试完成后清理测试数据。模拟发送的短信会留在手机的收件箱里可能会影响后续测试判断。你可以手动删除或者更酷一点写脚本用adb shell content命令直接操作系统的短信数据库需要权限来删除指定条件的短信。不过操作数据库风险较高建议仅在专门的测试机上进行。4. 模拟电话让测试机“响”起来测试来电接听、挂断、通话界面、通话状态监听等功能总不能老麻烦同事给你打电话吧用ADB模拟电话想什么时候响就什么时候响想是谁打来就是谁打来。4.1 呼入电话模拟和短信类似模拟来电也有多种方式。对于安卓模拟器尤其是AVD可以使用古老的telnet方式连接控制台端口如5554然后输入gsm call 13800138000。但这对于真机不适用。对于真实安卓设备最有效的方法是发送模拟电话呼入的广播。核心命令是adb shell am broadcast -a android.intent.action.PHONE_STATE --es incoming_number “13800138000”但是光发送这个广播手机可能只会更新状态栏不会弹出完整的来电界面。要触发完整的来电界面需要更精确地模拟电话服务Telecom Service的状态。这通常需要更高的权限系统级或使用adb shell pm grant给测试App授权。一个更简单粗暴且有效的方法是直接使用adb shell input命令来“欺骗”系统启动拨号界面并模拟来电但这需要结合一些UI状态判断。我常用的一个稳定方法是在测试机上安装一个辅助App可以自己写一个简单的这个App监听特定的广播比如com.example.TEST_CALL_IN当收到广播时就在App内使用TelecomManager的API来模拟一个来电。然后通过ADB发送自定义广播来触发它adb shell am broadcast -a com.example.TEST_CALL_IN --es phone_number “9501380000”这种方式虽然多了一步安装App但稳定性和可控性最高可以模拟来电振动、铃声、甚至不同的通话状态响铃、接通、挂断。4.2 呼出电话与通话状态控制模拟拨出电话相对简单。你可以直接启动系统的拨号Intent并填充号码adb shell am start -a android.intent.action.CALL -d tel:13800138000执行这个命令手机会直接跳转到拨号界面并开始呼叫指定号码注意在真机上可能需要授予“拨打电话”权限并且会真的拨出去请谨慎使用最好在无SIM卡或飞行模式的测试机上操作。更安全的方式是使用ACTION_DIAL它只打开拨号盘并填充号码而不直接呼叫adb shell am start -a android.intent.action.DIAL -d tel:13800138000这对于测试拨号盘UI、号码格式化等功能足够了。控制通话状态是高级玩法。模拟接听电话你可以通过adb shell input命令模拟一个“滑动接听”或“点击接听按钮”的操作。这需要你先知道接听按钮在屏幕上的坐标或者使用 accessibility 的节点信息。命令类似adb shell input tap 500 1200。模拟挂断电话同理找到挂断按钮的坐标进行点击。在自动化测试中我经常将这一系列操作写成脚本先模拟来电 - 等待2秒 - 模拟滑动接听 - 保持通话30秒 - 模拟点击挂断。这样就可以完整地测试一个通话生命周期内你的App比如音乐播放器是否会暂停录音App是否会中断的表现如何。这里有个非常重要的注意事项测试机的状态。确保测试机在测试通话相关功能时处于一个合适的模式。如果插着SIM卡模拟来电可能会和真实来电冲突甚至可能产生实际通话费用。我的做法是专门准备一台旧手机作为测试机拔掉SIM卡连接Wi-Fi进行测试。这样既能完成所有网络功能测试又完全不用担心误操作产生费用或干扰。5. 模拟GPS定位让手机“环游世界”对于地图、打车、外卖、运动健身等所有基于位置服务的App测试不同地理位置下的功能表现是核心。ADB可以让你在几秒钟内把手机的GPS定位从北京天安门“瞬移”到纽约时代广场。5.1 单点定位geo fix最常用的命令是adb shell geo fix。这个命令会向系统注入一个虚拟的GPS位置信息。基本格式是adb shell geo fix 经度 纬度例如把定位设置到杭州西湖附近adb shell geo fix 120.155 30.274执行后你打开测试机上的任何地图App如谷歌地图、百度地图都会发现自己的位置已经变成了西湖边。geo fix命令还可以附加两个可选参数海拔高度单位米和精度单位米。比如adb shell geo fix 120.155 30.274 50 10表示在西湖上空50米精度10米的位置。这个命令的生效需要满足一个关键前提测试机的“位置信息”设置中必须允许“模拟位置信息”或“允许模拟地点”。这个选项通常在“开发者选项”里。同时你用来测试的App也需要有定位权限。我遇到过很多次命令执行成功但地图不更新的情况一查都是忘了开“允许模拟位置”。5.2 轨迹模拟与动态更新单点定位满足了大部分静态场景测试。但像测试导航、跑步轨迹记录、行车路径这些功能我们需要模拟一个连续移动的位置。这就需要连续发送一系列geo fix命令。你可以写一个简单的Shell脚本或Python脚本来实现。思路是先设定一条路径比如一组经纬度坐标序列然后循环遍历这些坐标每间隔一段时间如1秒执行一次adb shell geo fix。例如用Python实现import subprocess import time coordinates [ (120.155, 30.274), # 起点西湖 (120.158, 30.276), (120.162, 30.279), (120.165, 30.282) # 终点西湖另一侧 ] for lon, lat in coordinates: cmd f“adb shell geo fix {lon} {lat}” subprocess.run(cmd, shellTrue) time.sleep(1) # 每秒移动一次运行这个脚本你的测试机在地图上的位置就会沿着设定的路径“走”起来。你可以调整time.sleep的参数来控制移动速度模拟步行、骑车或开车的不同速度感。除了geo fix原始资料里还提到了geo nmea。NMEA是一种标准的GPS数据格式它包含的信息比单纯的经纬度更丰富比如速度、方向、时间、卫星状态等。通过adb shell geo nmea命令可以直接注入一段NMEA语句这对于测试那些需要解析原始GPS数据的专业应用非常有用。不过NMEA语句格式比较复杂一般我们可以从真实的GPS记录设备中导出或者在网上找到样例数据。对于绝大多数App测试geo fix加上轨迹模拟已经完全够用。5.3 定位测试中的常见问题模拟定位听起来很美好但实际使用中坑也不少。第一个大坑是权限和模式冲突。除了前面提到的要开启“允许模拟位置”还要注意手机本身的定位模式。如果手机同时开启了“高精度模式”使用GPS、Wi-Fi和移动网络那么真实的网络定位信号可能会干扰甚至覆盖你模拟的GPS信号导致位置跳回真实地点。我建议在测试时将手机定位模式切换到“仅设备”或“仅GPS”模式这样系统会优先使用你注入的GPS信号。第二个是应用缓存问题。有些地图App为了节省流量和提升体验会对位置信息进行缓存。你可能已经通过ADB更新了位置但App显示的还是几秒钟前的位置。解决办法通常是稍微移动一下模拟位置或者强制关闭App再重新打开。在编写测试脚本时可以在位置更新后加入一个等待时间或者触发一下App的刷新机制。第三个是模拟高度和室内场景。geo fix可以模拟海拔但很多民用地图对海拔数据不敏感。如果你测试的是登山或飞行类应用需要更精确的高度模拟可能需要寻找更专业的工具或直接使用真机在真实环境中测试。对于室内定位如蓝牙Beacon、Wi-Fi指纹的模拟ADB的GPS命令无能为力这需要其他技术手段。我在测试一个外卖App的配送员轨迹功能时就曾用轨迹模拟脚本完美复现了配送员从取餐点到送餐点的完整路径包括等红灯在某个点停留一段时间、抄近道突然改变坐标序列等各种情况极大地提升了测试场景的覆盖率和真实感。6. 综合实战构建自动化测试脚本学会了各项单项技能是时候把它们组合起来打造一个自动化测试流水线了。这才是ADB命令操控测试机的威力所在——将重复劳动彻底自动化。6.1 脚本编写思路与框架一个好的测试脚本应该像导演剧本一样清晰定义每一个场景和步骤。我们以测试一个“打车App”的下单流程为例这个流程可能涉及用户定位 - 选择目的地 - 发单 - 司机接单 - 司机来电确认位置 - 行程开始 - 行程结束支付。我们可以用ADB命令模拟其中多个环节。脚本框架可以选用你熟悉的任何语言Bash Shell、Python、甚至Node.js都可以。我个人更喜欢用Python因为它的库丰富处理字符串、循环、条件判断更灵活。脚本的基本结构包括初始化检查ADB连接确认设备在线。前置条件设置例如确保测试机定位模式正确关闭无关通知。测试场景执行按顺序执行一系列ADB命令模拟用户操作和系统事件。结果验证与断言通过adb shell logcat抓取日志或者adb shell dumpsys检查组件状态来判断测试是否通过。环境清理测试结束后恢复模拟定位到真实位置可以发一个geo fix 0 0然后关闭模拟位置选项清理测试产生的短信、通话记录等。6.2 一个完整的场景案例假设我们要自动化测试“收到验证码短信后自动填充”这个功能。我们可以编写一个Python脚本import subprocess import time import re def run_adb(cmd): “”“执行ADB命令并返回结果。”“” result subprocess.run(cmd, shellTrue, capture_outputTrue, textTrue) return result.stdout # 1. 初始化检查 print(“检查设备连接...”) devices run_adb(“adb devices”) if “device” not in devices: print(“未找到已授权的设备请检查连接”) exit(1) # 2. 启动待测App假设包名为 com.example.app print(“启动待测App...”) run_adb(“adb shell am start -n com.example.app/.MainActivity”) time.sleep(3) # 等待App启动 # 3. 导航到登录界面这里简化实际可能需要模拟点击 # 假设我们通过模拟点击“登录”按钮的坐标来实现 run_adb(“adb shell input tap 300 600”) # 点击登录按钮坐标 time.sleep(2) # 4. 在输入框输入手机号假设输入框焦点已在此 phone_number “13800138000” run_adb(f“adb shell input text {phone_number}”) # 输入手机号 time.sleep(1) run_adb(“adb shell input keyevent 66”) # 模拟按下回车键触发发送验证码请求 time.sleep(2) # 等待后端发送短信 # 5. 模拟收到验证码短信 sms_code “123456” print(f“模拟发送验证码短信: {sms_code}”) # 使用广播方式模拟短信接收 sms_command f“adb shell am broadcast -a android.provider.Telephony.SMS_RECEIVED --es sender ‘10690000’ --es message ‘【Example】您的验证码是{sms_code}5分钟内有效。’” run_adb(sms_command) time.sleep(3) # 给App一点时间接收并处理短信 # 6. 验证结果检查当前界面或日志看验证码是否被自动填充 # 方法一截屏保存便于人工复查 run_adb(“adb exec-out screencap -p screen_after_sms.png”) print(“已截屏保存为 screen_after_sms.png”) # 方法二通过UI Automator获取当前界面文本判断是否包含验证码 # 这里需要更复杂的解析作为思路展示 # ui_dump run_adb(“adb shell uiautomator dump /sdcard/window_dump.xml”) # run_adb(“adb pull /sdcard/window_dump.xml .”) # ... 解析XML文件查找验证码 ... print(“测试步骤执行完毕请检查截图和日志。”)这个脚本只是一个简单示例真实场景会更复杂需要处理网络延迟、弹窗、权限申请等各种情况。但核心思想是一致的用ADB命令模拟外部事件短信用input命令模拟用户操作用logcat或screencap来验证结果。6.3 集成到CI/CD流程当你的脚本稳定后就可以考虑把它集成到团队的持续集成/持续部署CI/CD流水线中了比如Jenkins、GitLab CI、GitHub Actions。在CI服务器上连接一台或多台固定的测试机可以是实体手机也可以是云测平台提供的真机每次代码提交后自动运行你的ADB自动化测试脚本。这样做的好处是巨大的它能在第一时间发现因代码变更导致的回归问题比如新修改的短信解析库导致验证码提取失败或者地图SDK升级后对模拟定位的兼容性问题。把测试从“人肉手动”变成“自动触发”是保障应用质量、提升发布信心的关键一步。我自己的经验是一开始可以从一两个核心场景的脚本开始慢慢补充。过程中肯定会遇到各种奇怪的失败比如设备突然断开连接、命令执行超时、不同手机型号的兼容性问题。把这些异常情况都考虑到你的脚本里做好错误处理和重试机制。自动化测试不是一个一蹴而就的事情而是一个不断迭代、不断完善的过程但一旦跑起来它给你带来的时间节省和信心提升绝对是超值的。