ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

中兴F50短信转发到微信:ADB+PushPlus保姆级教程

中兴F50短信转发到微信:ADB+PushPlus保姆级教程 这台中兴F50放在车里当热点已经用了很久说实话我一开始完全没把它的“短信功能”当回事。直到有一次抢票手机里死活收不到银行验证码我才意识到一台常年插电、塞在角落里的随身WiFi短信是最容易被忽略的盲区。既然F50本身跑的是安卓底层又支持ADB调试那完全可以自己动手做一条“收到短信→实时转发到微信”的链路而且门槛没有想象中那么高。这篇保姆级教程就是干这个的从ADB开关开始到PushPlus配置再到一个能长期挂着跑的转发脚本我会把每一步怎么操作、为什么这么操作、踩过哪些坑都写清楚。适合完全没接触过ADB的新手也适合想把手头安卓设备短信能力盘活的朋友。1. 先说清楚这条链路到底怎么工作的1.1 F50值得折腾短信转发的几类场景中兴F50这类随身WiFi本质是一台带蜂窝网络的安卓设备。它插上SIM卡之后能发WiFi、能上网但大多数人都忽略了它其实也能收短信。放在车里、工位上、甚至老家当“固定热点”长期插电使用时短信就成了一个没人看的盲区。我见过最典型的几个场景一是车载WiFi车停在地库SIM卡收的验证码、通知全堆在设备里二是双卡用户把副卡塞进F50副卡绑定的银行、App验证码根本收不到三是把F50当“公网IP代理工具”用的朋友更需要第一时间知道SIM卡是否欠费、是否被运营商限制。这些场景下一个能自动把短信推到微信的方案价值就体现出来了。1.2 整条链路的技术原理拆解这条链路不复杂核心就三段F50系统收到短信之后短信会写入系统自带的短信数据库电脑或小主机通过ADBAndroid Debug Bridge连接F50定期查询短信数据库脚本把新增短信提取出来调用PushPlus的HTTP接口推送到你的微信。很多人一听“ADB”就觉得是搞机党才碰的东西其实ADB就是一个调试通道安卓系统都内置支持。你要做的无非是把设备上的调试开关打开让电脑能通过命令行访问它然后执行一条查询短信的命令。PushPlus更简单它是一个微信公众号推送服务注册之后拿到一个token往它的接口发一个请求微信就能收到消息。整体思路和“用爬虫监控网页变化”是同一个套路只是把监控对象换成了F50的短信数据库。之所以选ADB而不是在F50上装App主要原因是F50这类设备的系统是精简过的想装一个安卓App反而麻烦而且官方固件也不一定开放安装入口。ADB是系统级能力不需要在设备上装任何东西稳定性更高也更符合“长期无人值守”的需求。整个方案的维护成本基本只有那一台负责跑脚本的电脑或NAS。2. 环境准备与ADB工具安装2.1 下载ADB Platform-ToolsADB不是Windows自带的需要单独下载Google官方的Platform-Tools。打开Android开发者官网的Platform-Tools下载页面developer.android.com/tools/releases/platform-tools选Windows版本解压到一个路径比如D:\platform-tools。解压之后你会看到一堆exe和dll文件其中adb.exe就是核心程序。可以先进目录打开命令行输入adb version验证一下能不能跑。这一步不需要安装任何东西解压即用但要注意路径里别带中文和空格后续写脚本调用时省心很多。2.2 配置环境变量让系统全局认识adb如果不配环境变量每次使用ADB都得cd到解压目录或者写全路径很容易出问题。配环境变量是为了让Windows在任何目录下都能直接执行adb命令。操作步骤是右键“此电脑”选“属性”点“高级系统设置”在“高级”标签页里点“环境变量”在下方的“系统变量”里找到Path双击编辑新建一行填D:\platform-tools确定保存。然后重新打开一个cmd窗口执行adb version如果能看到版本号就说明配置成功。这里有个小坑环境变量改完之后之前已经打开的cmd窗口不会生效必须新开窗口。2.3 安装Python用什么跑脚本后面的转发脚本我会用Python写因为语法简单、轮询和HTTP调用都很方便Windows、Linux都能跑。去python.org下载Python 3.x版本安装时务必勾选“Add Python to PATH”不然命令行里python会提示找不到命令。装完后新开cmd执行python --version确认。如果你手头已经有Node.js或者其他语言环境脚本逻辑也可以移植但没必要折腾。教程里的脚本是完整可跑的直接用Python最稳妥。跑脚本的机器可以是普通电脑、旧笔记本、软路由、NAS只要能和F50处在同一个局域网、能访问外网就行。3. 中兴F50开启ADB调试的完整操作3.1 进入开发者选项找到ADB开关中兴F50的ADB开关不在默认菜单里一般藏在开发者选项里。先把电脑或手机连上F50的WiFi浏览器打开它的管理后台常见地址是http://192.168.0.1部分固件版本是http://192.168.1.1以设备背面的标签为准。后台登录进去之后找“设置”或者“系统设置”菜单里面一般能看到“开发者选项”。如果找不到别急着放弃很多中兴设备需要连续点击“固件版本号”或者“关于本机”里的版本号5到7次才会解锁开发者选项这招和手机解锁开发者模式是一个逻辑。部分固件还会把“ADB调试”和“USB调试”分开命名本质上都是同一个开关把它打开就行。如果后台实在找不到也可以试一下中兴官方的“中兴智联”App工具箱里偶尔会有调试相关入口但不同固件差异较大以你手头那台的界面为准。3.2 USB连接电脑与驱动处理开启ADB开关之后用USB数据线把F50连到电脑上。这里强烈建议先试USB连接因为无线连接经常因为F50没配对码而卡住USB是最直接的通道。连接后打开cmd执行adb devices。如果列表里出现设备的序列号状态是device那就是连接成功可以直接跳到下一节开无线ADB。如果提示adb不是内部或外部命令是你环境变量没配好如果设备列表为空优先考虑换一根数据线——很多线只能充电不能传数据。再不行就右键“此电脑”进设备管理器看有没有带黄色感叹号的未知设备有的话需要装中兴的USB驱动或者手动更新驱动指向你解压的Platform-Tools目录里的驱动文件。F50一般没有屏幕所以插上USB后不会像手机那样弹出“允许USB调试吗”的对话框它会默认允许这一点和手机不太一样。3.3 用tcpip模式开启无线ADBUSB能连上之后要长期跑脚本总不能每次都插着线。ADB支持通过WiFi连接也就是无线调试模式把设备转到TCP/IP监听模式就行。USB连接状态下先执行adb tcpip 5555这条命令告诉F50在5555端口上监听ADB。然后拔掉USB数据线让电脑连上F50的WiFi热点或者路由器下同一局域网执行adb connect 192.168.0.1:5555这里的IP是F50的局域网IP一般就是管理后台那个地址。执行完再adb devices能看到类似192.168.0.1:5555 device的输出就说明无线ADB已经通了。需要注意一点如果F50的系统版本是Android 11以上“无线调试”功能可能会有配对码机制直接用adb connect可能报错。但F50这类精简设备通常用adb tcpip 5555的方式就能绕开配对限制这也是为什么建议先用USB连接。如果遇到cannot connect先确认电脑和F50在同一个WiFi下再试试重启ADB服务端adb kill-server然后adb start-server。4. 验证ADB能读到短信4.1 常用ADB命令速查连上ADB之后先用几条常用命令确认设备状态和系统环境顺便也能排查后续问题。这里整理了一个速查表都是整个方案里最常用的命令作用adb devices查看已连接的ADB设备列表adb connect 192.168.0.1:5555无线连接指定设备adb shell content query --uri content://sms/inbox查询收件箱短信adb shell dumpsys telephony.registry查看SIM卡状态、信号等adb logcat -d抓取系统日志排错很常用adb shell uiautomator dump导出当前界面UI层级后面权限受限时会用到dumpsys和logcat在正常运行时不需要但一旦遇到“读不到短信”“设备连不上”这类问题它们就是排查利器。完整命令记不住也没关系先把adb devices和content query这两条记住就够用了。4.2 核心读取命令与输出解析验证能不能读到短信直接执行adb -s 192.168.0.1:5555 shell content query --uri content://sms/inbox --projection _id,address,body,date这条命令的意思是查询系统短信数据库的收件箱只取_id短信ID、address发件号码、body短信内容、date时间戳四个字段。如果F50里已经收到了短信输出会是类似这样的格式row: 0 _id12, address10086, body您的验证码是123456, date1700000000000 row: 1 _id11, address95588, body消费提醒支出58元, date1699999999000每行是一条短信row: 0表示第0条后面的键值对就是字段内容。注意date是毫秒级Unix时间戳需要除以1000才能转换成正常时间。只要能看到这类输出说明ADB权限没问题可以进入下一步。4.3 一个必须绕开的坑命令传参与中文乱码如果你是在Windows的cmd里直接手敲这条命令大概率会遇到两个问题。第一个问题是--sort_order参数。很多人想用date DESC按时间倒序排列但直接在命令行里写--sort_order date DESCadb会把date和DESC当成两个独立参数传给设备的shell查询会直接报错。正确姿势是加反斜杠转义空格--sort_order date\ DESC。但这里不建议用排序参数后面Python脚本里改成只按ID增量判断新短信反而更简单可靠。第二个问题是中文乱码。F50的短信内容默认是UTF-8编码Windows的cmd默认是GBK编码直接打印很容易显示成乱码。临时解决办法是在cmd里执行chcp 65001切换到UTF-8代码页治本的办法是用Python脚本读取运行时指定UTF-8编码。后面脚本部分会专门处理这个问题手敲命令时看到乱码别慌不代表数据坏了。5. PushPlus配置与测试5.1 注册获取tokenPushPlus是一个微信公众号消息推送服务它的逻辑是你扫码关注它的公众号然后它给你一个token你调用它的HTTP接口消息就会通过公众号推送到你的微信。对个人来说这就是最简单的“免费服务器推送通知”方案不需要自己搭公众号也不需要考虑微信接口的签名算法。打开PushPlus官网pushplus.plus用微信扫码登录登录后控制台首页就能看到你的token一串字符复制保存好。整个教程只需要一对一推送功能也就是把消息推给你自己不需要建群组。其实PushPlus还支持一对多群组、微信模板消息等高级功能但对短信转发场景来说一对一token就完全够用了。5.2 用浏览器直接测试推送拿到token之后先不要急着写脚本用浏览器手动测一次确认推送链路通不通。把下面URL里的token换成你自己的直接粘贴到浏览器地址栏访问https://www.pushplus.plus/send?token你的tokentitle测试短信contentHelloWorld如果一切正常页面会返回一串JSON类似{code:200,msg:请求成功,data:发送成功}同时你的微信会收到一条来自PushPlus公众号的消息。这一步的目的是把故障范围缩小只要推送通后面脚本出问题就只可能是读取短信或传参环节。5.3 关于推送频率和参数格式的提醒PushPlus免费版是有调用频率限制的具体限流策略会动态调整但长期高频请求确实有被限的风险。短信转发场景本身频率很低一天撑死几十条完全在合理范围内。但如果脚本逻辑有bug比如把同一批历史短信反复推送就可能触发限制。还有一点要注意content参数里如果有中文或换行在URL里直接拼接可能出问题需要做URL编码。浏览器手动测试时内容简单无所谓Python脚本里会用urllib.parse.urlencode自动处理这属于“代码帮你避坑”的部分。另外每次调用后检查返回的code字段是否等于200这是判断推送是否成功的标准。6. 用Python脚本实现自动转发6.1 脚本整体逻辑与轮询策略脚本的思路很直接每隔几秒用ADB查一次短信数据库把新出现的短信ID和之前见过的ID做对比有变化就推送最后把最新ID保存下来。为什么用ID判断而不是时间因为同一秒内可能收到多条短信只用时间戳对比会漏掉短信数据库的_id是单调递增的用ID做增量判断最可靠。轮询间隔我建议设置成3到5秒。太短会频繁唤醒ADB通道增加设备功耗和通道不稳定风险太长又会明显延迟短信到达微信的时间验证码场景会急死人。3到5秒基本是“感受不到延迟”的平衡点。初次运行时的历史短信处理也是个关键点。F50里可能已经存了几十条甚至上百条旧短信如果脚本启动时一股脑全部推送微信会炸。这里用一个配置项SKIP_EXISTING控制第一次运行时自动把当前数据库里所有短信ID都标记为“已读”从下一次轮询开始才推送新增短信。这个细节很重要第一次跑脚本之前一定要确认开关是打开的状态。6.2 完整可运行的转发脚本下面这个脚本可以直接保存为sms_forward.py运行。我尽量把注释写详细配置项都集中在最上面方便你根据自己的环境改。# -*- coding: utf-8 -*- import subprocess import time import re import json import os import urllib.request import urllib.parse from datetime import datetime # 配置区 DEVICE_IP 192.168.0.1 # F50的局域网IP改成你实际的 ADB_PORT 5555 TOKEN 你的pushplus_token # pushplus.plus 后台复制 POLL_INTERVAL 5 # 轮询间隔单位秒 SKIP_EXISTING True # True启动时跳过历史短信只推新增 STATE_FILE seen_ids.txt # 已处理短信ID的存档文件 # SEEN_IDS set() if os.path.exists(STATE_FILE): with open(STATE_FILE, r, encodingutf-8) as f: for line in f: line line.strip() if line.isdigit(): SEEN_IDS.add(int(line)) # 正则解析 content query 输出 LINE_RE re.compile(r_id(\d),\s*address([^,]*),\s*body(.*),\s*date(\d)) def run_adb(args, timeout10): cmd [adb, -s, f{DEVICE_IP}:{ADB_PORT}] args try: res subprocess.run( cmd, capture_outputTrue, textTrue, encodingutf-8, errorsreplace, timeouttimeout, ) return res.stdout except subprocess.TimeoutExpired: return except FileNotFoundError: print([错误] 找不到 adb 命令请检查环境变量) return def is_connected(): try: out subprocess.run( [adb, devices], capture_outputTrue, textTrue, timeout5 ).stdout except Exception: return False return f{DEVICE_IP}:{ADB_PORT} in out def query_sms(): out run_adb([ shell, content, query, --uri, content://sms/inbox, --projection, _id,address,body,date, ], timeout15) return out def parse_sms(text): events [] blocks re.split(rrow: \d , text) for block in blocks: m LINE_RE.search(block) if not m: continue sms_id int(m.group(1)) address m.group(2).strip() body m.group(3).strip() date_ms int(m.group(4)) events.append((sms_id, address, body, date_ms)) return events def send_pushplus(title, content): params urllib.parse.urlencode({ token: TOKEN, title: title, content: content, }) url https://www.pushplus.plus/send? params try: with urllib.request.urlopen(url, timeout10) as resp: data resp.read().decode(utf-8) obj json.loads(data) if obj.get(code) 200: return True, return False, data except Exception as e: return False, str(e) def save_state(): with open(STATE_FILE, w, encodingutf-8) as f: for sid in sorted(SEEN_IDS): f.write(str(sid) \n) def mark_existing_sms(): # 首次运行时把当前所有短信ID都标记为已读不推送历史记录 out query_sms() for sms_id, _addr, _body, _date in parse_sms(out): SEEN_IDS.add(sms_id) save_state() print(f[初始化] 已标记 {len(SEEN_IDS)} 条历史短信为已读) def poll_once(): out query_sms() if row: not in out: print(f[{datetime.now():%H:%M:%S}] 未读短信为空或ADB连接异常) return False events parse_sms(out) new_events [e for e in events if e[0] not in SEEN_IDS] if not new_events: return True # 按ID升序推送避免同批次多条短信顺序错乱 for sms_id, address, body, date_ms in sorted(new_events, keylambda x: x[0]): title fF50短信 {address} content f来自 {address} 的短信\n{body} ok, err send_pushplus(title, content) if ok: print(f[{datetime.now():%H:%M:%S}] 已推送短信 {sms_id} 来自 {address}) else: print(f[{datetime.now():%H:%M:%S}] 推送失败 {sms_id}: {err}) SEEN_IDS.add(sms_id) time.sleep(0.5) # 多条短信之间稍作间隔避免触发限流 save_state() return True def main(): if SKIP_EXISTING and not os.path.exists(STATE_FILE): mark_existing_sms() print(开始监控短信...) while True: try: if not is_connected(): print(设备不在线尝试重连...) run_adb([connect, f{DEVICE_IP}:{ADB_PORT}]) time.sleep(3) continue poll_once() time.sleep(POLL_INTERVAL) except KeyboardInterrupt: print(\n手动退出) save_state() break except Exception as e: print(发生异常:, e) time.sleep(POLL_INTERVAL * 2) if __name__ __main__: main()直接运行之前先把你自己的DEVICE_IP和TOKEN替换进去。在项目目录执行python sms_forward.py正常启动后控制台会先提示已标记历史短信然后每隔几秒静默轮询。此时给F50里的SIM卡发一条短信几秒钟内微信就会被推送。6.3 部署成后台服务让它长期挂着跑如果你只是想试一下开着cmd窗口跑就行。但长期用总不能让电脑一直挂着窗口。这里给几种简单的部署思路。Windows用户最简单的做法是写一个start.bat内容只有两行chcp 65001 python D:\sms_forward\sms_forward.py把这个bat放进开机启动文件夹shell:startup开机就自动跑。想更规范的话可以用nssm把Python注册成Windows服务故障自动重启但说实话对个人场景有点杀鸡用牛刀了。家里有NAS或者软路由的话把脚本和Python环境放到机器上用systemd管理就够了示例单元文件和脚本同名即可路径按自己环境改典型的守护配置是Restartalways。关键逻辑都一样让脚本进程在后台持续运行断了能自动拉起。7. 常见问题与排错实录7.1 adb devices 为空或一直显示 unauthorizedadb devices什么都没输出先想三件事线是不是数据线、驱动装没装、F50的ADB开关是不是真的开了。线的问题我前面强调过很多Type-C线只能充电换根数据线瞬间就好。驱动的问题去设备管理器看有没有未知设备有就装官方ADB驱动。F50这类随身WiFi没有屏幕一般不会出现手机上那种需要点“允许调试”的弹窗但如果你的固件比较特殊连上USB后还是需要确认那只能找一台有显示器的环境解决。unauthorized状态是授权没通过主要是设备端拒绝了调试请求。但F50精简系统里授权弹窗可能被隐藏了这时候可以尝试adb kill-server再adb start-server重启ADB服务端或者关掉开发者选项里的ADB开关再重新打开。如果还是不行检查一下F50系统时间是否准确时间偏差过大会导致授权证书校验失败。7.2 无线连接被拒绝或掉线adb connect 192.168.0.1:5555返回cannot connect大概率是设备没在监听5555端口。有些固件重启之后会恢复成默认状态USB调试开关和tcpip监听都会失效需要重新插一次USB执行adb tcpip 5555。所以脚本里我加了断线自动重连逻辑但connect命令对“端口没监听”的情况是无效的该插线重来还是得来一次。还有一种情况是F50开启了休眠省电导致WiFi/ADB断掉。随身WiFi为了续航空闲时会进入低功耗状态ADB通道自然就断了。解决思路是尽量保持充电状态同时在后台设置里把“自动休眠”关掉或者把省电模式关掉。这个坑在长时间挂机场景下很常见我一度以为脚本写错了后来才发现是设备自己睡着了。7.3 读不到短信提示Permission Denial终端输出类似SecurityException: Permission Denial的时候说明当前shell用户没有访问短信ContentProvider的权限。中兴F50原厂固件我实测大多数能直接读但个别定制固件确实锁了这块。如果遇到先检查命令里的uri是不是content://sms/inbox有时精简固件把收件箱uri改成了content://sms去掉/inbox再试一次。兜底方案就是之前提到的adb shell uiautomator dump。原理很简单通过ADB把系统短信App当前界面的UI层级导出来然后从XML文本里匹配短信内容。前提是F50上有短信App界面而且你得先把界面切到短信列表页操作起来相对笨重但面对权限锁死的固件这可能是唯一不刷机的路子。我的建议是优先折腾固件里的开发者选项权限兜底方案只作为备选。7.4 短信内容解析乱码或字段错位脚本读取短信时用encodingutf-8处理adb输出Windows控制台用chcp 65001这两步做到位基本不会乱码。如果短信body里本身包含逗号我的正则解析用的是贪婪匹配只要date字段在行尾body里的逗号不会影响结果。但万一某条短信正文里也含有, date这种字符串就会截断概率极低真遇到可以在正则上继续加限制。字段错位多半是因为某些短信的address为空比如一些运营商服务短信发送号码显示为null命令行输出可能直接省略这个字段导致正则没匹配上。所以脚本里如果看到某条短信没推先打开ADB手动查一次原始输出看看是哪一行字段缺失。7.5 PushPlus收不到消息或返回异常浏览器测试推送成功但脚本推送失败最常见原因是你改了token之后脚本没重启还拿着旧token在跑。另一个坑是content参数没编码脚本里用urlencode已经处理了但如果你手写curl测试记得对中文内容做URL编码。返回400或429则表示请求参数错误或触发频率限制先看返回的msg字段具体内容再针对性调整。从PushPlus服务器到微信完成展示会有几秒延迟这是正常现象只要脚本没报错耐心等一会儿就行。如果长时间收不到去PushPlus公众号的推送记录里翻一下能看到历史推送详情这个功能排查很管用。7.6 一定要留意的安全底线ADB调试是一个高权限通道开启后局域网内的其他设备理论上都能尝试连接你的F50。虽然连接ADB通常需要授权但adb tcpip 5555模式下如果设备端宽松授权风险还是存在的。建议只在可信内网里开启不要为了远程管理把F50放到公网可达的环境更不要把5555端口映射出去。PushPlus的token等同于是你的“微信推送钥匙”任何人拿到都能往你微信发消息不要上传到公开的代码仓库。脚本里保存的短信内容可能包含验证码、账单、个人隐私运行脚本的机器要做好基本的安全防护不用的历史短信数据定期清理。这套方案的本质是把设备的私密信息转发到你的私人微信安全这根弦绷紧一点没坏处。最后聊一点我自己的实际体会。这套转发方案跑起来之后最大的感受是“存在感极低”它不会像微信通知那样频繁打扰你只在真正有短信的时候响一下这一点非常符合我的预期。但折腾过程中真正花掉我最多时间的不是脚本逻辑而是排查F50无线连接掉线的问题——设备一休眠所有自动化都白搭所以后来我把F50固定插电又关掉省电模式才算真正稳定下来。如果你也打算长期依赖这套方案我的建议是第一次部署多花一点时间把状态保存、断线重连、历史短信跳过这几个环节测透后面就真的可以做到“忘了它的存在”了。
返回列表