背景
#344 引入的「响铃时用系统 TTS 播报日程」在真机后台场景不可靠,三个根因:
- 绑定时机:
AlarmSoundService 第一次启动往往发生在 App 已在后台、被系统认为受限时,此时 new TextToSpeech() 内部要跨进程绑定 TTS 引擎所在的另一个 App,MIUI 类 ROM 会拦后台进程新发起的这类绑定 → status=-1 稳定失败——即使设备装了引擎、前台手动试听正常。
- 包可见性:targetSdk 30+ 不声明
<queries> 的 TTS_SERVICE intent,new TextToSpeech() 查到空引擎列表,初始化稳定失败(真机 adb logcat 实测确认,官方文档明确要求声明)。
- 文案生成横跨两端:原生
ReminderSpeechFormatter.java + JS reminderSpeech.ts 两条路径分开维护,且文案不区分提醒强度。
方案
- 新增全局单例
AlarmTtsEngine.kt:TextToSpeech 改为全模块共用单例,在 AlarmModule 构造时(React Native 加载原生模块,几乎总是应用正常启动的前台时机)抢先绑定一次;响铃时 AlarmSoundService 直接复用这条已建立的连接,绕开「后台新绑定被拦」。
AndroidManifest.xml 声明 <queries><intent action="android.intent.action.TTS_SERVICE"/></queries>,解决包可见性。
AlarmSoundService 全文案朗读:high 档位且有非空文案时设备 TTS 循环播报(onDone 后延迟重播);引擎未就绪先响打包铃保底、notifyWhenReady() 就绪那一刻无缝切到 TTS;onError/不可用一律回退打包铃。best-effort,绝不因 TTS 崩溃。
- 文案生成统一收敛到 JS 侧
strengthDelivery.ts::composeReminderSpeech()(删除 reminderSpeech.ts 及其测试):仅 high 强度返回非空;「标题,时间到了。现在已经X点Y分了。」/ 全天「X月X日,今天任务是标题。」/ 读不出时间「标题,时间到了,请及时处理。」;原生只念 JS 传进来的文案。
speech_text 全链路打通:AlarmSchedulerPort/NativeAlarmScheduler/TimeflowAlarmBridge → EXTRA_SPEECH_TEXT → presentNow/schedule;删除原生 ReminderSpeechFormatter.java 及其测试。
- 删除
withTimeflowAlarm.js 配置插件(权限改由 Android library manifest 合并);ExpoLocationMonitor 监听回调 async 化。
验收标准
不做
规格:MiniSpec
背景
#344 引入的「响铃时用系统 TTS 播报日程」在真机后台场景不可靠,三个根因:
AlarmSoundService第一次启动往往发生在 App 已在后台、被系统认为受限时,此时new TextToSpeech()内部要跨进程绑定 TTS 引擎所在的另一个 App,MIUI 类 ROM 会拦后台进程新发起的这类绑定 →status=-1稳定失败——即使设备装了引擎、前台手动试听正常。<queries>的 TTS_SERVICE intent,new TextToSpeech()查到空引擎列表,初始化稳定失败(真机 adb logcat 实测确认,官方文档明确要求声明)。ReminderSpeechFormatter.java+ JSreminderSpeech.ts两条路径分开维护,且文案不区分提醒强度。方案
AlarmTtsEngine.kt:TextToSpeech 改为全模块共用单例,在AlarmModule构造时(React Native 加载原生模块,几乎总是应用正常启动的前台时机)抢先绑定一次;响铃时AlarmSoundService直接复用这条已建立的连接,绕开「后台新绑定被拦」。AndroidManifest.xml声明<queries><intent action="android.intent.action.TTS_SERVICE"/></queries>,解决包可见性。AlarmSoundService全文案朗读:high 档位且有非空文案时设备 TTS 循环播报(onDone 后延迟重播);引擎未就绪先响打包铃保底、notifyWhenReady()就绪那一刻无缝切到 TTS;onError/不可用一律回退打包铃。best-effort,绝不因 TTS 崩溃。strengthDelivery.ts::composeReminderSpeech()(删除reminderSpeech.ts及其测试):仅 high 强度返回非空;「标题,时间到了。现在已经X点Y分了。」/ 全天「X月X日,今天任务是标题。」/ 读不出时间「标题,时间到了,请及时处理。」;原生只念 JS 传进来的文案。speech_text全链路打通:AlarmSchedulerPort/NativeAlarmScheduler/TimeflowAlarmBridge→EXTRA_SPEECH_TEXT→presentNow/schedule;删除原生ReminderSpeechFormatter.java及其测试。withTimeflowAlarm.js配置插件(权限改由 Android library manifest 合并);ExpoLocationMonitor监听回调 async 化。验收标准
不做
规格:MiniSpec