SMARTWATCH 学习手册有 C 基础 · 嵌入式从零开始
支线三 / Dart 与 Flutter App / 09

Android 拓展:从告警倒计时到原生短信接口

先把取消和失败流程做成可观察的界面,再解释 Dart 如何请求 Android 能力。配套测试使用模拟通道,不向实际号码发送消息。

接续上一篇:接回完整 App:沿一条消息读三个文件

1 · 告警为什么要先给用户取消机会

收到安全事件后,当前 App 显示十五秒倒计时,用户可以点击 I’M OK 取消。倒计时属于页面状态,必须避免重复事件创建多份计时器。取消后应停止计时;页面退出、连接变化时也要根据明确规则清理。

先使用模拟安全事件完成开始、减少、取消、超时四条路径。定时器只推进界面时间,不直接在测试中调用短信接口;当倒计时结束才进入后续检查。

2 · 联系人和权限要在实际提交前核对

首次安装联系人列表为空。添加姓名、关系和号码后保存,倒计时结束时重新读取当前联系人,再判断是否具备 Android SEND_SMS 权限。联系人可能在倒计时期间被修改,不能只使用很早以前缓存的配置。

没有联系人、没有权限、系统不支持、调用失败都要给出可理解结果。告警正文使用手表佩戴者的身份含义,不把收件人姓名误当作遇险人。联系电话属于个人数据,练习使用明确配置的测试号码和模拟发送。

3 · Dart 怎样请求 Android 做一件事

需要 package:flutter/services.dart;与原生端匹配同一通道名称

static const channel = MethodChannel(
  "com.example.smartwatch_app/emergency",
);

final allowed = await channel.invokeMethod<bool>("checkPermission");

MethodChannel 是 Flutter 与平台代码之间传递方法请求和结果的通道。Dart 指定名称、方法和可序列化参数,Android 侧用相同名称登记处理器,再调用平台功能并返回结果。它与主线的无线协议都涉及约定,但传输范围和执行环境不同。

沿 emergency_service.dart 进入 Android MainActivity.kt,看 checkPermission、requestPermission、sendSms 分别映射什么操作。首先把参数和返回路径讲清,再展开系统 SmsManager;不从页面直接插入一大段 Kotlin。

4 · 为什么提交成功还不能说已经送达

当前原生桥接返回的是发送请求被接受的结果,没有完整接入运营商实际送达回执。界面应说明提交状态,测试接收端另行核对实际收到的内容。多个接收人应逐个记录失败,不能因一个请求成功就把全部标成成功。

权限请求也是异步过程。用户拒绝后不能静默当作允许;需要返回页面让用户决定后续操作,避免反复自动弹窗。平台版本、设备短信能力和运行权限都应记录在设备验收结果中。

5 · 从模拟通道验证完整流程

使用 Flutter 的测试消息通道替代原生端,记录请求参数并返回预设结果。测试倒计时取消后没有调用 sendSms,无联系人时没有提交,通道抛错时出现失败提示。仓库现有告警和联系人测试就是这些场景的对照入口。

动手观察

画出“收到事件 → 倒计时 → 取消或检查 → 原生请求 → 提交结果”分支图。先通过模拟测试,再由使用者在 Android 测试设备上验证权限与实际接收;教程不把模拟成功写成真实短信送达。

资料与代码