1. 短信备份之后为什么还要单独补一条短信做 Android 短信备份恢复的同学大概率都遇到过这种需求备份文件已经生成好了但用户反馈“我那条验证码短信没进去”“我手动删掉的那条想补回来”。这时候你不可能让用户重新全量备份一遍最合理的做法就是在备份流程之外单独往系统短信库里插入一条记录然后再把它同步写进备份 XML。这个场景的核心链路其实就三件事用ContentResolver拿到短信库的操作入口用ContentValues组装一条短信的字段用insert把数据写进content://sms。听起来简单但真正动手时会发现字段名写错、date单位搞混、插入后查询读不回来、备份 XML 结构和数据库字段对不上各种小坑。这篇就围绕“短信备份后如何插入一条新短信”这个具体动作展开把ContentResolver、ContentValues、Uri和XmlSerializer的配合讲清楚。适合已经能跑通短信读取备份、现在要补录单条短信的 Android 开发者。下面给的字段骨架、insert 示例和 XML 结构都可以直接复制改。2. 前置准备权限、Uri 与 TaoToken 接入2.1 短信读写权限与运行时申请短信库属于系统敏感数据AndroidManifest.xml里至少要声明读取和写入权限uses-permission android:nameandroid.permission.READ_SMS / uses-permission android:nameandroid.permission.WRITE_SMS / uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE /注意WRITE_SMS在部分高版本系统上对普通应用已经收紧实际能不能写入取决于系统策略和你的应用角色。如果你只是做本地备份恢复的演示或内部工具建议在真机上验证如果是上架应用要提前确认目标系统的短信权限政策。运行时申请用标准写法即可if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) ! PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS, Manifest.permission.WRITE_SMS}, 1001); }2.2 短信库的 Uri 到底写哪个content://sms/是短信会话的总入口查询时能拿到所有短信。插入单条时用content://sms或content://sms/inbox都可以区别在于Uri含义插入后归属content://sms全部短信由 type 字段决定content://sms/inbox收件箱强制为收件content://sms/sent发件箱强制为已发送如果你要补录的是一条收到的短信用content://sms/inbox更省心不用自己填type。要精确控制就用content://sms并显式带上type。2.3 用 TaoToken 辅助调试与模型验证在写插入逻辑之前我习惯先把字段结构和备份 XML 的对应关系理清楚避免写完才发现字段名对不上。这种“字段映射 结构校验”的活用 TaoToken 的模型对话快速过一遍很省时间把数据库字段和 XML 标签贴进去让它帮你核对。如果你在做长期的 Android 编码或 Agent 类项目需要稳定调用模型能力可以看 Coding Plan适合持续性的编码场景。接入前先在 API Keys 页面生成密钥具体调用方式参考接入文档。地址统一走 API 入口https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。3. 可复制配置ContentValues 字段骨架与 insert 调用3.1 一条短信最少要填哪些字段短信库的列很多但插入一条能正常显示、能被备份读回的记录核心字段就这几个ContentValues values new ContentValues(); values.put(address, 110); // 号码 values.put(body, 马上过来一趟); // 正文 values.put(date, System.currentTimeMillis()); // 时间戳毫秒 values.put(type, 1); // 1收件 2发件 values.put(read, 1); // 0未读 1已读 values.put(seen, 1); // 是否已查看几个容易踩的点date必须是毫秒级时间戳。如果你从备份 XML 里读回来的是字符串记得Long.parseLong转换别直接塞字符串否则查询排序会乱。type不填的话用content://sms插入可能落到默认分类回读时筛选条件对不上。补录收件短信就填 1。read和seen建议都填 1否则插入后短信在系统里显示为未读用户会以为出了 bug。3.2 insert 调用与返回值判断ContentResolver resolver getContentResolver(); Uri target Uri.parse(content://sms/inbox); Uri result resolver.insert(target, values); if (result ! null) { Toast.makeText(this, 插入成功: result.toString(), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, 插入失败, Toast.LENGTH_SHORT).show(); }insert返回的是新记录的 Uri形如content://sms/inbox/123末尾的数字就是_id。拿到这个_id非常有用后面回读验证、写进备份 XML 都靠它。如果返回 null基本就是权限不够或字段非法先查权限再查字段名。3.3 把新短信同步写进备份 XML插入成功后如果这条短信也要进备份文件就用XmlSerializer追加一个节点。备份 XML 的结构建议和数据库字段一一对应?xml version1.0 encodingutf-8 standaloneyes ? smss sms address110/address body马上过来一趟/body date1730000000000/date type1/type /sms /smss追加写入的代码骨架FileOutputStream fos new FileOutputStream( new File(Environment.getExternalStorageDirectory(), smsbackup.xml), true); XmlSerializer serializer Xml.newSerializer(); serializer.setOutput(fos, utf-8); serializer.startTag(null, sms); serializer.startTag(null, address); serializer.text(110); serializer.endTag(null, address); serializer.startTag(null, body); serializer.text(马上过来一趟); serializer.endTag(null, body); serializer.startTag(null, date); serializer.text(String.valueOf(System.currentTimeMillis())); serializer.endTag(null, date); serializer.startTag(null, type); serializer.text(1); serializer.endTag(null, type); serializer.endTag(null, sms); serializer.flush(); fos.close();注意这里用FileOutputStream(file, true)的追加模式别把原来的备份覆盖了。XmlSerializer追加节点时不要再调startDocument和endDocument否则会生成两个 XML 声明解析时直接报错。4. 验证请求查询回读确认插入结果插入完不能只看 Toast必须回读确认。用ContentResolver.query按_id或按date倒序查最新一条Cursor cursor resolver.query( Uri.parse(content://sms/inbox), new String[]{_id, address, body, date, type}, date ?, new String[]{String.valueOf(System.currentTimeMillis() - 60000)}, date desc); if (cursor ! null cursor.moveToFirst()) { String id cursor.getString(cursor.getColumnIndexOrThrow(_id)); String address cursor.getString(cursor.getColumnIndexOrThrow(address)); String body cursor.getString(cursor.getColumnIndexOrThrow(body)); long date cursor.getLong(cursor.getColumnIndexOrThrow(date)); Log.d(SMS, id id address address body body date date); cursor.close(); }预期结果是日志里能看到你刚插入的号码、正文和时间戳_id和insert返回的 Uri 末尾数字一致。如果查不到先确认查询的 Uri 和插入的 Uri 是不是同一个分类再确认date过滤条件有没有把记录排除掉。回读通过后再打开备份 XML 检查节点是否完整。可以用一个简单的解析循环把 XML 里的address、body、date读出来和数据库对比两边一致才算真正闭环。5. 本篇常见错排查5.1 insert 返回 null最常见的原因是权限没给全尤其是WRITE_SMS。其次是ContentValues里字段名拼错比如把address写成addr系统不会报错直接返回 null。排查方法把values的 key 打印出来和官方列名逐个核对。5.2 插入成功但查询查不到大概率是 Uri 分类不一致。你用content://sms/inbox插入却用content://sms/sent查询自然查不到。统一用content://sms查询最稳再按type过滤。5.3 date 显示成 1970 年说明你塞进去的是秒级时间戳或者字符串。System.currentTimeMillis()是毫秒从 XML 读回来时用Long.parseLong转换别用Integer.parseInt会溢出。5.4 备份 XML 解析报错追加节点时多写了startDocument导致文件里出现两个 XML 声明。检查追加逻辑只保留startTag到endTag的部分。另外XmlSerializer用完要flush否则缓冲区数据可能没落盘。5.5 高版本系统写入被拒部分系统对短信写入做了额外限制普通应用即使有权限也可能被拦截。这种情况先确认应用角色必要时改用系统签名或走用户手动导入的路径不要硬刚权限。6. 继续把链路跑通插入单条短信这件事拆开看就是ContentValues组装字段、ContentResolver.insert写入、query回读验证、XmlSerializer同步备份四步。真正容易翻车的地方不在 API 本身而在字段名、时间戳单位、Uri 分类和 XML 追加这几个细节上。如果你在核对字段映射或者调试备份 XML 结构时想快速验证思路可以用模型对话把字段和标签贴进去让它帮你比对。需要长期在 Android 编码和 Agent 场景里稳定调用模型走 Coding Plan 更合适。密钥在 API Keys 页面生成调用细节看接入文档接口入口统一用https://taotoken.net/api。把插入、回读、备份这三步串成一个小工具方法以后补录短信就是一次调用的事。
企业数字化 ERP 产品动态
相关推荐
OpenClaw 3.1.0 Windows 安装教程:TaoToken 统一 Key 接入本地 AI 智能体 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 15:22:05
手机网站设计作品欣赏多少钱?看完这份报价单再掏钱 手机网站设计作品欣赏多少钱?看完这份报价单再掏钱 网站上线了,服务器跑着,代码也写完了,结果后台看了一周,UV(独立访客)只有个位数,连自家亲戚都没几个。这种“网站做好了没人访问”的窘境,比没做网站更让人焦虑。很多山东的老板或者项目对接人这… · 2026/9/27 15:21:59
乾安网站建设保姆级教程:解决没人访问的服务器部署避坑指南 乾安网站建设保姆级教程:解决没人访问的服务器部署避坑指南 网站上线了三个月,后台数据还是零?别急着怪SEO没做好,八成是地基没打牢。很多乾安的中小企业老板花了几千块做个站,结果因为服务器配置不当、DNS解析混乱,导致百度爬虫根本抓不到页面,… · 2026/9/27 15:21:46
具身智能创新设计方案(10):三层架构标准化接口体系协同创新 前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&… · 2026/9/27 21:44:44
具身智能创新设计方案(14):标准化精准落地技术体系协同创新 前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&… · 2026/9/27 21:44:44
具身智能创新设计方案(13):彻底打通三层协同的语义与物理壁垒 前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&… · 2026/9/27 21:44:44
具身智能创新设计方案(16):破解单一技术栈的结构性能力天花板 前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”)是依托Transformer架构与“因式智能体”理论构建的新型工业视觉系统,也是当前最具代表性的具身视觉技术之一。它有机融合深度强化学习&… · 2026/9/27 21:44:44
5步搞定wordpress页面可视化编辑器避坑指南 5步搞定wordpress页面可视化编辑器避坑指南 很多新手朋友刚接手网站,看着后台那个花花绿绿的界面,心里直打鼓: 域名服务器搞不懂,怕点错地方把站搞崩。 别慌,这种焦虑我太懂了。以前我也这么干,后来发现,只要搞对了… · 2026/9/27 21:44:44
用Kindel看微信读书(1)---越狱篇 因为经常使用微信读书,但手机屏幕太小,太亮,对眼睛不好。结合自己的Kindle PaperWhite(第七代)越狱,实现Kindle阅读微信读书的过程记录下来,与需要的朋友共同分享。
我是在Kindle PaperWhite&a… · 2026/9/27 21:44:38
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01