利用ADB命令高效管理手机蓝牙、热点与WiFi状态的实用指南

📅 发布时间:2026/7/2 20:09:43 👁️ 浏览次数:
利用ADB命令高效管理手机蓝牙、热点与WiFi状态的实用指南
1. 为什么你需要掌握ADB管理手机状态如果你是一名移动应用开发者或者经常需要批量管理一堆手机设备那你肯定遇到过这样的场景测试一个需要蓝牙连接的功能结果发现几十台测试机的蓝牙状态五花八门有开的有关的手动一台台去点简直要了老命。又或者在做自动化测试时脚本跑着跑着就断了一查才发现是手机的热点或WiFi被意外关闭了。这些看似琐碎的状态管理问题其实非常影响效率。这时候ADBAndroid Debug Bridge就是你最好的朋友。它就像一把万能钥匙能让你通过电脑命令行直接对手机“发号施令”。原始文章里提到的方法比如用adb shell svc wifi enable来开关WiFi或者用adb shell settings get global bluetooth_on来查蓝牙状态都是非常实用的起点。但说实话光知道这几个命令是远远不够的。在实际操作中你会遇到各种坑不同手机品牌命令不通用、没有Root权限命令执行失败、命令执行了但状态没立即生效等等。我在这行摸爬滚打这么多年用ADB管理过的设备少说也有上千台。踩过的坑多了也就总结出了一套更高效、更稳定、兼容性更好的方法。这篇文章我就打算把这些实战经验毫无保留地分享给你。咱们不聊那些深奥的原理就聚焦在“怎么用”和“怎么用好”上让你看完就能上手真正解决工作中的痛点。无论你是想写个脚本一键配置所有测试机还是想在自动化流程里精准控制网络状态这里都有你需要的答案。2. 动手之前搭建你的ADB环境与基础认知工欲善其事必先利其器。在开始对着手机“施法”之前我们得先把ADB这个工具准备好并且理解一些基本概念这样才能避免很多低级错误。2.1 快速搞定ADB环境安装对于Windows用户最省事的方法就是去安卓开发者官网下载一个独立的“SDK平台工具”包。解压后你会得到一个包含adb.exe的文件夹。为了能在任何命令行窗口里直接使用adb命令你需要把这个文件夹的路径添加到系统的“环境变量”Path里。具体步骤是右键“此电脑”-“属性”-“高级系统设置”-“环境变量”在“系统变量”里找到Path编辑新建一条把刚才的文件夹路径粘贴进去就完成了。Mac和Linux用户则更简单通常用包管理器就能安装。比如在Mac上如果你安装了Homebrew只需要打开终端输入brew install android-platform-tools就行了。装好后同样建议把安装路径加到你的shell配置文件比如.bashrc或.zshrc里。环境搭好后用USB线连接手机和电脑。关键一步来了在手机上进入“开发者选项”通常在“关于手机”里连续点击“版本号”7次可以开启找到并开启“USB调试”开关。这时在电脑命令行输入adb devices手机上会弹出一个授权对话框点击“允许”。如果一切顺利你会在命令行窗口看到一串设备序列号后面跟着device字样这就表示连接成功了。如果只看到unauthorized那就是没点授权如果什么都没看到检查一下线缆和驱动吧。2.2 理解ADB命令的“权限世界”这是新手最容易栽跟头的地方。ADB命令的执行权限大致分三个等级权限不同能做的事情天差地别。普通ADB权限这是默认状态。你通过adb shell进入的是一个受限制的shell环境可以执行很多查询命令如dumpsys、settings get和部分修改命令如svc wifi enable。但很多涉及系统核心设置的操作它会返回“killed”或者直接没反应。原始文章里提到svc wifi enable输出killed就是因为这个。Root权限su这是“超级用户”权限。在已经解锁并Root了的设备上你在adb shell之后再输入su命令提示符通常会从$变成#。这时你几乎可以执行任何命令包括直接调用底层服务如service call connectivity来开关热点。但Root有风险会破坏系统完整性很多厂商手机和公司测试机并不允许这么做。Shell用户权限这是一个中间地带。有些命令比如通过am启动系统设置界面不需要Root但需要当前ADB Shell具有较高的用户权限。这通常取决于你连接电脑时手机上的用户账户状态。所以在你开始写脚本前一定要先搞清楚你的目标设备处于哪种权限状态。我的建议是优先寻找不需要Root的解决方案这样脚本的通用性最强。如果实在绕不开再考虑针对已Root设备编写特定分支。接下来我们就分别看看在有限权限下如何巧妙地搞定蓝牙、WiFi和热点。3. 蓝牙状态查询与切换的实战技巧蓝牙的管理相对独立方法也比较清晰。我们先从最可靠的查询方法开始。3.1 如何准确获取蓝牙的开关状态原始文章给出了两个方法我都用过但它们各有优劣。第一个是adb shell settings get global bluetooth_on。这个命令非常快直接读取系统全局设置数据库里的一个键值。输出就是0或1干净利落非常适合用在脚本里做条件判断。但这里有个细节这个值反映的是用户设置的意图而不是蓝牙硬件当前的真实状态。什么意思呢有时候你通过这个命令看到是1开但蓝牙可能因为省电策略或其他原因并没有真正启动并广播。所以我通常会搭配第二个命令一起使用adb shell dumpsys bluetooth_manager | grep -i “state”。注意我这里不用enabled而用state因为dumpsys输出的信息更丰富。你可能会看到STATE_ON、STATE_TURNING_ON、STATE_OFF等。这个状态更接近硬件底层的真实情况。在脚本里我会先检查settings get的值如果为1但功能异常再去查dumpsys的状态这样排查问题更精准。3.2 无Root环境下切换蓝牙的几种姿势直接修改设置数据库是最优雅的方式adb shell settings put global bluetooth_on 1。把末尾的1换成0就是关闭。这个命令在绝大多数Android设备上只要系统版本不是太老都能立即生效不需要Root权限蓝牙会立刻开始扫描或被关闭。这是我最推荐的首选方法稳定又直接。原始文章里提到的svc bluetooth enable方法我实测下来问题比较多。正如文中所述它经常“输入命令后并不立即生效重启设备才生效”。这是因为svc命令的机制在不同厂商的ROM里差异很大依赖度不高不建议在自动化脚本中作为主要手段。那么如果需要弹窗确认才能开启蓝牙怎么办比如一些金融类App的安全要求。这时可以用adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE。这个命令会像用户手动操作一样弹出系统级的“开启蓝牙”请求对话框。但这带来了新问题自动化脚本如何点击那个“允许”按钮你可以用adb shell input tap来模拟点击屏幕坐标但不同手机分辨率不同坐标会变非常不可靠。更优的做法是结合UI自动化测试框架如UIAutomator2来通过控件ID定位并点击但这就把事情搞复杂了。我的经验是对于后台静默管理优先使用settings put命令。只有在必须模拟用户交互流程的特定测试场景下才考虑使用会触发弹窗的方法并且要准备好处理弹窗的后继操作。4. WiFi状态的高效管理与兼容性处理WiFi的管理比蓝牙更常用也更容易遇到兼容性问题。我们分查询和操作两步走。4.1 判断WiFi是否开启的可靠方法原始文章提到了看进程和dumpsys两种方法。adb shell ps | grep wpa_supplicant这个思路是对的wpa_supplicant是Android管理WiFi连接的核心进程。如果它存在通常意味着WiFi功能是活跃的。但注意有些手机在WiFi关闭但位置信息采用“高精度模式”需要扫描WiFi时这个进程也可能存在。所以它是个充分非必要条件。更准确的方法是查询WiFi服务的状态adb shell dumpsys wifi | grep -i “wifienabled”。你会看到一行类似Wi-Fi is enabled或Wi-Fi is disabled的输出这个判断非常直接。另一个更结构化的方法是adb shell cmd wifi get-wifi-enabled需要Android 10及以上它会明确返回enabled或disabled非常适合脚本解析。对于热点状态的判断原始文章说查看hostapd进程。这确实是热点服务进程但和wpa_supplicant一样依赖进程存在与否有时不保险。更推荐的方法是adb shell dumpsys wifi | grep -i “hotspot”或者adb shell cmd wifi get-softap-enabled。后者会返回热点是否启用同样清晰明了。4.2 开启/关闭WiFi的兼容性命令大全这里就是体现经验价值的地方了。原始文章列出了三种方法我根据实战给你补充和排序一下。方法一svc命令-adb shell svc wifi enable/disable。简单粗暴但在很多没有Root权限的设备上你会看到Killed的输出意味着命令被系统拒绝了。所以这个方法仅适用于已取得Root权限adb shell su -c “svc wifi enable”的设备在普通设备上成功率很低。方法二模拟按键操作- 通过am start打开系统WiFi设置界面然后用input keyevent模拟按键去打开开关。这个方法听起来很“黑科技”但实际是兼容性最差的一种。不同手机的设置界面布局、开关控件顺序千差万别KEYCODE_DPAD_DOWN代码20和KEYCODE_ENTER代码66按几次能点到开关完全没准。一个脚本可能在这台小米上能用换台OPPO就完全失效了。除非你只为某一款特定型号的手机写脚本否则强烈不推荐依赖这种方法。方法三使用Appium Settings广播-adb shell am broadcast -a io.appium.settings.wifi --es setstatus enable。这是一个非常聪明的“曲线救国”方法。它利用了Appium自动化框架里的一个特殊组件Appium Settings App来接收广播并修改系统设置。前提是你的手机上必须提前安装好这个App通常在初始化Appium环境时会自动安装。命令执行后手机屏幕可能会有弹窗取决于系统权限设置这又回到了需要处理弹窗的问题。但它的优点是不需要Root且原理相对通用。我最推荐的第四种方法Android 9cmd命令-adb shell cmd wifi set-wifi-enabled enabled。这是Android系统在后续版本中提供的更正规的“服务调用”接口。它不需要Root命令执行后WiFi状态会立即改变而且没有弹窗干扰。当然它的限制是要求系统版本较高。在写脚本时我们可以做一个判断如果系统版本 Android 9就优先使用cmd命令如果版本较低再尝试回退到svc命令需Root或 Appium 广播方案。5. 个人热点的精准控制与权限破解控制热点是三个功能里最难的一个因为它直接涉及网络共享系统权限管控最严格。原始文章里提到需要Root权限的方法确实是目前最有效的但我们也可以探索一些边界。5.1 检测热点状态的进阶手段除了看hostapd进程更稳定的方法是查询网络共享服务adb shell dumpsys connectivity | grep -A5 -B5 “Tethering”。在输出信息里你会看到各个接口WiFi、USB、蓝牙的网络共享状态。例如mUsbTethering: DISABLEDmWifiTethering: ACTIVE这样的字段一目了然。对于Android 10以上的设备可以尝试adb shell cmd wifi get-softap-enabled这个命令专门用于查询WiFi热点开关状态输出简洁。5.2 开启/关闭热点的实战方案剖析原始文章的方法一模拟点击设置界面同样面临巨大的兼容性问题不同品牌手机的“个人热点”设置入口和开关位置差异极大自动化脚本几乎无法通用这里不再赘述。核心方法service call接口。命令如下开启WiFi热点adb shell service call connectivity 24 i32 0关闭WiFi热点adb shell service call connectivity 25 i32 0这里的24和25是系统ITethering接口中startTethering和stopTethering方法的代码。末尾的i32 0是参数0代表使用WiFi进行网络共享1是USB2是蓝牙。但是这个命令几乎百分之百需要Root权限。在普通ADB Shell下执行通常会返回Result: Parcel(00000000 00000001 ‘………’)之类的错误码表示权限拒绝。这是Android系统出于安全考虑做的严格限制。所以如果你管理的设备是已Root的测试机那么这就是你的终极武器。那么无Root真的就无解了吗也不完全是但都是“野路子”。一种思路是如果你的App本身是系统应用拥有android.permission.TETHER_PRIVILEGED权限你可以通过ADB发送广播来触发你App内的代码去开启热点。但这对于大多数开发者来说条件太苛刻。另一种思路是利用一些系统漏洞或辅助功能AccessibilityService来模拟点击但这极其不稳定且随着系统更新随时会失效。因此对于热点管理我的结论很明确如果你需要批量、静默地开关热点请确保你的设备拥有Root权限并使用service call命令。如果设备未Root那么通过自动化脚本去控制热点在当前Android版本下是一个尚未完美解决的难题通常需要引导用户手动操作或者将热点功能测试与设备状态准备分开进行。6. 编写健壮的自动化脚本思路与范例知道了单个命令怎么用最终我们要把它们组合起来写成能应对各种情况的脚本。这里我分享一些架构思路和一个简单的Shell脚本范例。首先脚本一定要有状态检查。不要盲目地去执行一个“打开”操作。先检查当前状态如果已经是开启的就跳过。这能避免不必要的操作和潜在的错误。其次做好异常处理和日志记录。每条命令执行后检查其返回值$?在Shell中为0表示成功。如果失败记录下错误信息并尝试备选方案。第三考虑设备兼容性。在脚本开头可以尝试获取设备的Android版本号adb shell getprop ro.build.version.release和品牌信息adb shell getprop ro.product.brand根据这些信息选择不同的命令分支。下面是一个简单的Shell脚本示例用于安全地开启WiFi优先尝试高版本方法#!/bin/bash # 函数检查WiFi是否已开启 is_wifi_enabled() { # 方法1: 使用 cmd 命令 (Android 10) local result$(adb shell cmd wifi get-wifi-enabled 2/dev/null | tr -d \r) if [[ $result enabled ]]; then echo WiFi is already enabled (via cmd). return 0 elif [[ $result disabled ]]; then return 1 fi # 方法2: 回退到 dumpsys 检查 local dumpsys_result$(adb shell dumpsys wifi | grep -i Wi-Fi is enabled) if [[ -n $dumpsys_result ]]; then echo WiFi is already enabled (via dumpsys). return 0 else return 1 fi } # 函数尝试开启WiFi enable_wifi() { echo Attempting to enable WiFi... # 1. 尝试 Android 9 的 cmd 方式 adb shell cmd wifi set-wifi-enabled enabled /dev/null 21 if [ $? -eq 0 ]; then sleep 2 # 等待状态更新 if is_wifi_enabled; then echo Successfully enabled WiFi via cmd command. return 0 fi fi echo Fallback: cmd method failed or unavailable. # 2. 尝试 svc 方式 (可能需要root) adb shell svc wifi enable /dev/null 21 sleep 2 if is_wifi_enabled; then echo Successfully enabled WiFi via svc command. return 0 fi # 3. 如果以上都失败尝试Appium广播方式假设已安装Appium Settings echo Trying Appium broadcast method... adb shell am broadcast -a io.appium.settings.wifi --es setstatus enable /dev/null 21 sleep 3 # 给弹窗和操作留出时间 # 这里可以添加自动点击弹窗的代码如果需要且可能 # adb shell input tap x y if is_wifi_enabled; then echo Successfully enabled WiFi via Appium broadcast. return 0 else echo All methods failed to enable WiFi. return 1 fi } # 主逻辑 echo Checking WiFi status... if is_wifi_enabled; then echo No action needed. else enable_wifi fi这个脚本体现了分层尝试和状态验证的思想。你可以根据这个模式将蓝牙和热点管理的命令也封装成函数构建一个更全面的设备状态管理工具。记住好的脚本不是一次写成的而是在不同设备、不同系统版本上反复测试和调整出来的。每次遇到不兼容的情况就为你的脚本增加一个新的判断分支或回退方案久而久之你的脚本就会变得无比强大和鲁棒。