Skip to content

Latest commit

 

History

History
339 lines (223 loc) · 11.6 KB

File metadata and controls

339 lines (223 loc) · 11.6 KB

功能说明

短信筛选

关键词筛选

  • 在短信内容中进行 LIKE 模糊搜索
  • 支持部分匹配,输入即搜索
  • 应用筛选后自动保存到筛选历史

号码筛选

  • 按发送/接收号码进行 LIKE 模糊搜索
  • 支持部分号码匹配

日期范围筛选

提供以下预设选项:

选项 说明
全部 不限制日期
今天 当天的短信
最近 7 天 7 天内的短信
最近 30 天 30 天内的短信
最近 90 天 90 天内的短信
自定义 自定义起止日期,通过 customStartDatecustomEndDate 指定时间戳

已读状态筛选

  • 全部:不限制已读状态
  • 已读:仅显示已读短信
  • 未读:仅显示未读短信

锁定状态筛选

  • 全部:不限制锁定状态
  • 已锁定:仅显示被锁定的短信
  • 未锁定:仅显示未锁定的短信

消息类型筛选

  • 全部:不限制消息类型
  • 收件箱(INBOX):接收到的短信
  • 已发送(SENT):已发送的短信
  • 草稿(DRAFT):保存的草稿
  • 发件箱(OUTBOX):等待发送的短信

SIM 卡筛选

  • 按 SIM 卡的订阅 ID(simSubscriptionId)筛选
  • 支持筛选特定 SIM 卡收发的短信

联系人筛选

  • 通过 contactId 按联系人筛选短信
  • 从通讯录选择联系人后自动应用筛选

筛选条件组合

所有筛选条件使用 AND 逻辑组合,可以同时应用多个条件。FilterState.hasFilters() 方法判断是否有任何筛选条件处于激活状态。

批量操作

多选模式

  • 进入方式:长按列表中的某条短信进入多选模式
  • 切换选中:在多选模式下点击列表项切换其选中状态
  • 退出方式:调用 exitMultiSelectMode() 退出多选模式

全选与反选

  • 全选:基于数据库级别选中所有匹配当前筛选条件的短信(不仅仅是当前页面加载的条目),选中数量等于 filteredCount
  • 反选:在当前已加载的消息列表中反转选中状态
  • 取消全选:清空所有选中状态

批量删除

支持三种删除模式:

模式 说明
单条删除 通过侧滑触发,删除单条短信
多选删除 删除用户手动选中的多条短信
按条件全删 全选状态下删除,按当前筛选条件删除所有匹配短信

删除流程:

  1. 检查是否为默认短信应用,若不是则弹出设置引导对话框
  2. 显示删除确认对话框,附带预览消息(最多 5 条)
  3. 用户确认后执行删除
  4. 显示删除结果(成功删除 N 条短信)

滑动删除

  • 左滑列表项显示删除按钮
  • 点击删除按钮触发单条删除流程
  • 自动检查默认短信应用状态

导出功能

CSV 格式规范

  • 遵循 RFC 4180 标准
  • 使用 UTF-8 with BOM 编码(字节序 0xEF 0xBB 0xBF
  • 行尾使用 CRLF(\r\n
  • 包含表头行

导出字段

字段 说明 示例值
ID 短信数据库 ID 12345
号码 发送/接收号码 10086
内容 短信正文 您的话费余额...
时间 格式化时间 2024-01-01 12:00:00
类型 消息类型名称 收件箱已发送草稿发件箱
已读状态 已读/未读 已读
锁定状态 锁定/未锁定 未锁定
SIM 卡 SIM 卡标识 SIM 1
发送状态 发送结果(仅已发送类型) 成功失败发送中待发送

特殊字段处理

  • 内容和号码:包含逗号、双引号、换行符的字段会用双引号包裹,内部双引号转义为 ""
  • 发送状态:仅对已发送(成功)、发送失败(失败)、发件箱(发送中)、待发送(待发送)类型显示,其他类型为空
  • 时间格式:统一使用 yyyy-MM-dd HH:mm:ss 格式

导出范围

  • 导出已选:仅导出多选模式下用户选中的短信(默认选项,仅在多选模式且有选中项时显示)
  • 导出全部:忽略筛选条件,导出数据库中所有短信
  • 导出筛选结果:仅导出符合当前筛选条件的短信(仅在有筛选条件时显示)

多选模式下点按底部导出按钮时,对话框默认选中"导出已选"。非多选模式下行为与原有逻辑一致。

SAF 集成

  • 使用 Android Storage Access Framework
  • 用户可自定义文件名和保存位置
  • 通过 ActivityResultLauncher 获取用户选择的 URI

进度反馈

  • 分页读取(每页 100 条),逐条写入
  • 实时回调 onProgress(exported, total) 更新进度
  • 导出完成后返回成功导出的条数

导入功能

CSV 解析

  • 使用自定义 CsvParser,遵循 RFC 4180 规范
  • 支持 UTF-8 with BOM 编码,自动检测并跳过 BOM 字符(\uFEFF
  • 支持双引号包裹的字段,包括字段内包含换行符、逗号和转义双引号(""
  • 逐行读取,支持跨行的引号字段

表头验证

导入文件必须包含以下表头列(顺序不限,全部存在即可):

ID, 号码, 内容, 时间, 类型, 已读状态, 锁定状态, SIM卡, 发送状态

缺少任一列将报错"文件格式不正确"。

重复检测

检测规则:号码 + 内容 + 时间三者完全一致即判定为重复。

  • 重复短信不会被导入
  • 跳过数量计入 skipped 计数

字段映射

CSV 列 导入处理
号码 直接作为短信地址
内容 直接作为短信正文
时间 yyyy-MM-dd HH:mm:ss 解析为时间戳
类型 收件箱 → INBOX,已发送 → SENT,草稿 → DRAFT,发件箱 → OUTBOX
已读状态 已读 → true,其他 → false

默认 SIM 卡

导入的短信自动使用第一张活跃 SIM 卡的订阅 ID。若无 SIM 卡信息则默认使用 0。

前置条件

导入操作要求应用为默认短信应用。若不是,会弹出设置引导对话框。

进度反馈

  • 实时回调 onProgress(imported, skipped) 更新进度
  • 导入完成后返回 ImportResult(imported, skipped),包含成功导入数和跳过数

默认短信应用管理

检测机制

通过 PermissionUtils.isDefaultSmsApp() 检测当前应用是否为默认短信应用。

  • Android 10+(API 29+):使用 RoleManager.isRoleHeld(RoleManager.ROLE_SMS)
  • Android 6-9(API 23-28):使用 Telephony.Sms.getDefaultSmsPackage() 与当前包名比较

请求机制

通过 DefaultSmsManager.requestDefaultSmsRole() 请求默认短信应用权限:

  • Android 10+:调用 RoleManager.createRequestRoleIntent(ROLE_SMS) 启动系统角色请求界面
  • Android 6-9:使用 Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT 并传递当前包名

触发场景

以下操作需要默认短信应用权限,若未设置会弹出引导对话框:

  • 删除短信(单条、多选、按条件全删)
  • 导入短信

设置入口

DefaultSmsManager.openDefaultAppsSettings() 可直接打开系统的默认应用设置页面。

筛选历史

存储机制

  • 使用 SharedPreferences 持久化存储
  • 最多保存 5 条历史记录
  • 采用 LRU 排序,最近使用的排在最前面

自动保存

当用户应用筛选且关键词非空时,自动调用 addFilterHistory(keyword) 保存到历史记录。重复关键词会更新其位置到最前面。

操作

  • 查看历史:筛选面板中显示历史关键词列表
  • 复用历史:点击历史记录快速填充关键词
  • 清空历史:调用 clearFilterHistory() 清除所有历史记录

SIM 卡支持

加载逻辑

LoadSimCardsUseCase 负责加载设备中的 SIM 卡信息:

  1. 通过 SmsRepository.getSimCards() 获取所有 SIM 卡列表
  2. 判断短名称是否唯一:提取所有 SIM 卡的短名称,若无重复则使用短名称显示
  3. 若短名称有重复,则使用格式化长名称(含脱敏手机号码)

显示规则

通过 getSimDisplayName(subscriptionId) 获取 SIM 卡的显示名称:

  • 短名称唯一时:显示 getShortName()(如"中国移动")
  • 短名称重复时:显示 getFormattedName()(含运营商和脱敏号码)
  • 未找到匹配 SIM 卡时:回退显示 "SIM {subscriptionId}"

短信列表

分页加载

  • 每页加载 50 条短信
  • 滚动到底部自动触发 loadMore() 加载下一页
  • 首次加载和筛选条件变更时重置到第一页

数据加载策略

  • 使用 async 并行执行:筛选结果数量查询和首页消息加载同时进行
  • 总数量使用 SmsDataSource 内部缓存,命中时即时返回
  • 同时维护 totalCount(全部短信数)和 filteredCount(筛选后短信数)

联系人名称解析

  • 通过 ContactsContract 查询号码对应的联系人名称
  • 短信列表项显示联系人名称而非原始号码

下拉刷新

  • 支持下拉刷新(Pull-to-Refresh)
  • 刷新时重新加载当前筛选条件下的数据
  • 刷新过程中显示加载指示器

关键词高亮

  • 当筛选条件包含关键词时,在短信内容中高亮显示匹配文字
  • 使用黄色背景标记

内容截断与展开

  • 长短信默认截断显示(3 行)
  • 点击展开按钮可查看完整内容
  • 支持折叠回截断状态

类型标签

  • 显示消息类型标签(收件箱、已发送、草稿、发件箱)
  • 不同类型使用不同颜色区分

深色模式

主题支持

  • 基于 Material3 主题系统
  • 跟随系统深色模式设置自动切换
  • 支持 Android 12+ 动态颜色(Material You)

配色方案

浅色模式

用途 颜色值
Primary #2196F3
Surface #FFFFFF
Background #F5F5F5
Error #F44336

深色模式

用途 颜色值
Primary #90CAF9
Surface #1E1E1E
Background #121212
Error #EF9A9A

界面适配

所有界面组件均适配深色模式,包括:

  • 侧边栏筛选面板(DrawerFilterPanel
  • 短信列表项(SmsListItem
  • 删除确认对话框(DeleteConfirmDialog
  • 导出/导入对话框(ExportDialogImportDialog
  • 多选操作栏(MultiSelectBottomBar
  • 顶部应用栏(MainScreenTopBar