报告口径本页直接渲染本地报告真源;静态能力、动态观察、推断和线上未验证项不得互相替代。
All Document Reader v1.5.6-Doc-Solara 保活、拉活与通知逆向报告#
竞品包名:
com.solara.alldocumentreader.officepdfwordexcel
APK versionName / versionCode:1.5.6-Doc-Solara/56
静态样本、真机观察日期:2026-08-20
结论口径:静态代码和本次测试机快照;不代表线上 Remote Config 当前值,也不代表所有用户或机型行为。
1. 结论先行#
- 这款的核心不是常驻进程保活,而是一条本地定时召回通知:
Remote Config 默认值 → AlarmManager → ReminderReceiver → 本地 Notification → SplashActivity。静态代码和测试机中已登记的ReminderReceiver闹钟共同闭环了这条链路。 - 默认召回策略为:首延迟 2 天、20:30 投递、间隔 3 天、7 天最多 2 条;另有最近 48 小时活跃抑制、点击后 72 小时冷却、连续忽略退避/停发等参数。它们来自 APK 内置的 Firebase Remote Config 默认值,线上可覆盖,不能当作当前线上固定策略。
- 通知不是远端下发正文:通知标题和正文内置在 APK。默认策略当前只会从 11 组“工具能力”文案中随机选取,并避开上次场景;另外还内置 9 组带“文件会损坏/将过期/有风险”意味的候选文案,但默认配置没有选择这些风险场景。
- 通知点击不是直接进某个 PDF 或工具页:
PendingIntent以ACTION_VIEW显式启动SplashActivity,只携带实验、场景、忽略次数等埋点参数;静态无法证实 Splash 之后最终展示的具体页面。 - 真机上已实际登记 2026-08-22 20:30 的
RTC_WAKEUP闹钟和RecyclerBinWorker;但该机POST_NOTIFICATIONS未授权,因此未观察到真实弹出的通知。强停后进程、活动服务、活跃闹钟和活跃 Job 均消失,stopped=true,不存在绕过 Force Stop 的证据。 RecyclerBinWorker与通知/拉活无关:它会筛选回收站已满 30 天的文件,删除存储中对应文件并同步数据仓库,是普通延迟清理任务。
2. 样本与证据边界#
| 项目 | 值 |
|---|---|
| 基础 APK | all-document-reader-v1.5.6-doc-solara/apk/base.apk(85,164,426 bytes) |
| ABI / density split | split_config.arm64_v8a.apk(87,729,830 bytes)/ split_config.xxhdpi.apk(4,651,474 bytes) |
| base SHA-256 | a76622f423bfc38e8d11e4065c4aab54f747ba57984e0d7baba3ff5f7d2ec180 |
| arm64 split SHA-256 | 0a7a9b0f583154c719950cae0e2d1756a855a254ffcd146d1ac121741e16bbe5 |
| xxhdpi split SHA-256 | a88573dabb01b89f56bc2461ffb56fbf74fbb9c78d9a4d9fa1f316b576b8d813 |
| 运行时 minSdk / targetSdk | 32 / 36 |
| 静态工具 | apkanalyzer、JADX 1.5.5 |
| 动态工具 | 已授权测试机的 adb dumpsys、任务划除、Force Stop;未清数据、未授予通知权限、未发送远端消息 |
报告不写入账号、用户文件、Token、设备标识或服务端请求数据。下文的“默认值”均指 res/xml/remote_config_defaults.xml,不是线上 Remote Config 的当前值。
3. 通知召回完整链路(静态事实)#
SplashActivity 的 Remote Config 完成协程
└─ 写入 experiment / variant / 排程与频控参数
└─ as8.g(...) 计算下一次时间并登记 AlarmManager
└─ setAndAllowWhileIdle(RTC_WAKEUP, triggerAt, ReminderReceiver)
└─ ReminderReceiver 选场景、建通知、重新安排下一次
└─ notify(33333, Notification)
└─ 点击:SplashActivity(携带实验/场景参数)
| 环节 | 已核验证据 | 正确解读 |
|---|---|---|
| 配置入口 | SplashActivity 的配置完成协程(混淆类 Luc.invokeSuspend)读取 config_schedule_daily,写入实验、变体和排程字段;配置变更时会取消旧闹钟再重排 |
Firebase Remote Config 用于策略配置,不是 FCM 推送消息本体 |
| 定时触发 | as8.g(...) 创建显式广播 ReminderReceiver,请求码 1111222,调用 AlarmManager.setAndAllowWhileIdle(RTC_WAKEUP, ...) |
允许在 idle 期间获得短暂投递机会;这不是常驻服务,也不保证在 Doze/系统配额下准点到达 |
| 实际发通知 | ReminderReceiver 选择场景后,协程 zz6 创建 NotificationCompat.Builder,调用 NotificationManager.notify(33333, ...) |
使用固定 ID 33333;按 Android 通知 ID 语义,后一次会替换同一 ID 的已有通知,而不是无限堆叠(此处为平台语义推断) |
| 点击 | Content PendingIntent 显式启动 com.roosterx.featurefirst.splash.SplashActivity,携带 EXTRA_SCHEDULE_DAILY_NOTIFICATION、实验 ID、变体 ID、场景 ID、忽略次数 |
可确认“点击会启动应用”,不能从本段代码确认最终一定落到某个功能页或某份文件 |
| 划除 | NotificationDismissedReceiver(exported=false)读取同一组参数,并记录 dismiss_daily_notification |
已有划除埋点;不能由此推断服务端一定会立即改变策略 |
| 计量 | 展示、点击分别记录 show_daily_notification、click_daily_notification,带 experiment / variant / scenario / ignored_count |
说明此机制有实验和效果衡量设计,不等于本次真机已上报成功 |
3.1 默认节奏与频控(APK 内置默认值)#
| 配置项 | 默认值 | 含义与边界 |
|---|---|---|
is_enable |
true |
默认开启;线上 Remote Config 可关闭或替换 |
experiment_id / variant_id |
retention_frequency_v1 / twice_weekly |
留存频次实验标识,不是用户 ID |
first_delay_days |
2 天 |
首次计划的默认延迟 |
delivery_hour / delivery_minute |
20:30 |
默认目标时刻;系统调度仍可延迟 |
interval_days |
3 天 |
默认重排间隔 |
max_notifications / window_days |
2 / 7 天 |
7 天最多 2 条的频控参数 |
suppress_if_active_within_hours |
48 小时 |
近 48 小时活跃时的抑制参数 |
cooldown_after_click_hours |
72 小时 |
点击后的冷却参数 |
backoff_after_ignored_count / backoff_interval_days |
3 次 / 7 天 |
连续忽略后的退避参数 |
stop_after_ignored_count |
6 次 |
连续忽略后的停发阈值参数 |
ReminderReceiver 的代码会读取已发次数、最后打开/点击等持久化状态后再决定是否展示,并在发出后调用重排逻辑;故这不是无条件的“每 3 天必发”。
3.2 通知渠道(静态 + 真机)#
| 字段 | 值 |
|---|---|
| Channel ID | feature_tips_channel_id_v1 |
| 名称 | Notifications(通知) |
| 描述 | PDF Reader & PDF Viewer(PDF 阅读器与查看器) |
| importance | 3,即默认重要级别 |
| 灯光 / 振动 | 开灯 / 关闭振动 |
| category | recommendation(推荐) |
| 图标 | ic_notification_small |
测试机已能看到该渠道,渠道 importance 仍为 3;但 App 级通知权限是 POST_NOTIFICATIONS: granted=false,系统 App 通知重要级为 NONE。因此本次没有可见通知并非没有通知代码,而是授权条件不满足;本轮按测试边界未修改该权限。
4. 通知文案#
4.1 当前默认会选中的 11 组本地文案#
默认 scenario_ids 为 27–37。ReminderReceiver 从该集合随机选取,并排除上一次的场景;下表是每个 ID 的实际 APK 字符串,英文后紧跟中文释义。
| 场景 | 标题(原文 / 中文) | 正文(原文 / 中文) |
|---|---|---|
| 27 | 📎 Merge PDFs in Seconds / 几秒合并 PDF |
Combine multiple documents into one organized PDF that’s easy to share. / 把多份文档合成一份易于整理和分享的 PDF。 |
| 28 | ✂️ Keep Only the Pages You Need / 只保留需要的页面 |
Split a large PDF into smaller, more manageable files in seconds. / 几秒把大 PDF 拆成更易管理的小文件。 |
| 29 | 🖼️ Turn Images into a PDF / 把图片转成 PDF |
Combine photos, receipts, or notes into one convenient PDF file. / 把照片、收据或笔记合并成一份便于使用的 PDF。 |
| 30 | 📸 Convert PDFs to Images / 将 PDF 转为图片 |
Export PDF pages as high-quality images for easy saving and sharing. / 将 PDF 页面导出为高清图片,便于保存和分享。 |
| 31 | 📄 Convert Word to PDF / Word 转 PDF |
Turn Word documents into polished, shareable PDFs in just a few taps. / 轻点几下将 Word 文档转为适合分享的 PDF。 |
| 32 | 🔐 Protect Important Documents / 保护重要文档 |
Add a password to your PDF and keep sensitive information secure. / 给 PDF 加密码,保护敏感信息。 |
| 33 | 🔓 Unlock Your PDF / 解锁 PDF |
Remove a password from your PDF for easier viewing and editing. / 移除 PDF 密码,以便查看和编辑。 |
| 34 | 📷 A Scanner in Your Pocket / 口袋里的扫描仪 |
Scan paper documents with your camera and save them as clear PDFs. / 用相机扫描纸质文档并存成清晰 PDF。 |
| 35 | ✏️ Need to Update a PDF? / 要更新 PDF 吗? |
Add content, notes, and changes to your documents directly on your phone. / 可直接在手机上为文档添加内容、批注和修改。 |
| 36 | 🔍 Extract Text Instantly / 即刻提取文字 |
Recognize and copy text from images or scanned documents in seconds. / 几秒识别并复制图片或扫描件中的文字。 |
| 37 | 🔄 Organize Your PDF Pages / 整理 PDF 页面 |
Drag and drop pages into the perfect order for your document. / 拖放页面,为文档排出合适顺序。 |
4.2 APK 中额外存在、但不在默认场景列表的风险型候选#
场景 1–9 映射到 s_d_t_* / s_d_d_* 字符串。它们是可被远端配置选入的候选,并不等于默认策略正在使用。例子如下:
| 原文标题 | 原文正文 | 中文释义 |
|---|---|---|
🔥 Important Files May be Corrupted! |
Unopened PDFs can get corrupted. View and back them up today! |
“重要文件可能损坏”;用未打开的 PDF 可能损坏来催促查看和备份。 |
🔔 PDF File Expiring Soon! |
Time-sensitive PDFs will disappear soon. Act now before it's gone! |
“PDF 文件即将过期”;用文件将消失来催促操作。 |
🚨 Your Important PDFs Are At Risk! |
Ignored files can lead to data loss. Secure and view them now! |
“重要 PDF 有风险”;用可能数据丢失来催促查看。 |
⚠️ Crucial Files Are Being Ignored! |
Vital documents need your attention. Tap to organize and review! |
“关键文件被忽略”;引导点击整理和复核。 |
📄 Unread PDFs Are Hurting Your Work! |
Unchecked documents slow you down. Read and act immediately! |
“未读 PDF 正拖累工作”;引导立即阅读处理。 |
这些风险文案没有基于某份真实文件状态的静态取证;不要把它们解读为“应用检测到文件过期、损坏或丢失”。
5. 保活、拉活与后台任务拆分#
| 机制 | 静态 / 真机证据 | 能确认什么 | 不能确认什么 |
|---|---|---|---|
| 本地闹钟召回 | 静态 setAndAllowWhileIdle(RTC_WAKEUP, ReminderReceiver);真机存在待执行 ReminderReceiver 闹钟 |
可在系统允许的时机拉起接收器,构建本地通知 | 不等于常驻、不保证准点、不证明可直接拉起可见 Activity |
| 点击通知启动 | 显式 PendingIntent → SplashActivity |
用户点击后有启动应用入口 | 不代表后台静默拉起,也不证明最终业务落点 |
| BootReceiver | Manifest 声明 BOOT_COMPLETED 的 BootReceiver;代码会重排或取消闹钟 |
APK 有开机重排意图 | Manifest 权限列表没有 RECEIVE_BOOT_COMPLETED;未做真实重启,不能写成已验证开机可触发 |
| RecyclerBinWorker | 真机 WorkManager Job;反编译后筛选进入回收站满 30 天的 PdfFile,删除存储中的实际文件,再更新数据仓库 |
存在独立的回收站过期清理 | 不参与通知创建、不是保活;本次未让其真正执行,未验证失败/权限不足分支 |
| FGS | APK 有 FOREGROUND_SERVICE 权限与 WorkManager 框架组件;启动后只见 WebView Chromium 沙箱服务,startForegroundCount=0 |
无动态 FGS 运行证据 | 不能由权限或框架类推“存在 FGS 保活” |
| DataTransport Job | 真机有 Google DataTransport 网络 Job | 存在 SDK 数据传输调度 | 不能写成业务保活或通知任务 |
5.1 真机状态对照#
| 场景 | 观察结果 | 结论 |
|---|---|---|
| 正常启动并退后台 | stopped=false;存在 ReminderReceiver 的 RTC_WAKEUP 闹钟,目标为 2026-08-22 20:30:00,系统窗口 +1h,带 10 秒临时 allowlist;存在 RecyclerBinWorker,当时最早执行约 3 小时 26 分后 |
设备上实际已安排本地通知和回收站清理。20:30 与内置默认值吻合,但不能据此确认线上配置未被覆盖。 |
| 通知授权 | 渠道存在,但 POST_NOTIFICATIONS: granted=false |
未观察到通知落地;原因是测试机授权关闭,而非否定静态链路。 |
| 从最近任务划掉 | 最近任务中不再有该包;约 40 秒后仍可见 App 进程;未见产品自定义 FGS | 单一时点显示划卡不必然即时杀进程;没有足够证据把残留进程归因于保活机制。 |
| Force Stop 后 30 秒 | stopped=true;pidof 为空;Activity services 为 (nothing);活跃 ReminderReceiver 闹钟与 RecyclerBinWorker Job 均不再列出(仅留下系统历史取消记录) |
Force Stop 是明确边界:没有绕过强停的保活、闹钟或 Worker 证据。 |
6. 产品侧可借鉴与避坑#
- 可以借鉴的是可配置的节奏和频控,不是风险恐吓。 首延迟、活跃抑制、点击冷却、忽略退避和 7 天上限,都是比“固定周期群发”更可控的召回变量;但任何“文件损坏/过期/丢失”的文案必须有真实文件状态支撑,否则是误导。
- 通知点击应直接指向可完成的任务。 该样本点击只进入 Splash 并做归因;若我方要使用同类提醒,最好携带经验证的内部路由,落到对应文件、扫描结果或具体工具页,而非泛化首页。
- 定时提醒与保活必须分开验收。
AlarmManager、WorkManager、点击启动、FGS、开机重排和 Force Stop 是不同能力;本样本的证据支持“本地通知召回 + 清理任务”,不支持“稳定多路保活”。 - 强停必须写成终止边界。 Android Force Stop 后等待系统/闹钟/Worker 自行恢复不可作为产品承诺;需要用户再次启动应用才可能恢复调度。
7. 未验证项与风险#
- 未授予通知权限、未等到 2026-08-22 的实际投递时刻;因此未真机看到标题、正文、点击落点或划除埋点。
- 未发送或抓取 Firebase Remote Config / FCM 网络请求;当前线上实验分组、文案和频控仍未知。
- 未进行真实重启、Doze 长时等待或省电限制测试;
BootReceiver由于缺少RECEIVE_BOOT_COMPLETED声明,尤其不能视为已验证可用。 - 未让回收站 Worker 实际删除文件;只确认代码路径和已登记 Job,未验证文件权限、失败重试与数据一致性。
- 未评估广告、订阅、阅读/编辑功能体验;首启广告只是本次测试窗口观察,不是本报告对广告频控的结论。