跨端: feat(推送客户端): PushService.ets(取 token → 上报 → 点击跳转)+ 接进 EntryAbility ⇒ **文件真的被编译了**

pi 三件里的前两件 + 第三件的"目标解析"这半。

- `pushService.getToken()` → `POST /me/devices/push-token`(`provider/token/device_name/session_id`,省略空项);
- 上报标记按 **`accountKey|token`**(服务端同一 token 换账号是**转移**不是并存 ⇒ 标记必须按账号维度,否则新账号永远不报、旧账号的登记已被转走);
- 注销:`DELETE` **带 body**(服务端就是这么定的),`deleted:false` 不当错误;
- 点击跳转:`onNewWant` → `routeFromWant`(`parseNotificationData` + 有界去重 ledger)→ `PushService.pendingRoute` 等页面来取;
- **所有失败静默**(没 token / 401 / 400 / 500 / 权限拒绝 ⇒ 只写 hilog,不提示、不重试、不阻塞启动);
- 通知权限**只在拿到 token 后**才申请(没 token 就弹窗是打扰)。

★ 一条我差点当成"验过了"的证据:`assembleHap` 在**没接入**时也报 `BUILD SUCCESSFUL` ——
因为 ArkTS 只编译**可达**模块,没人 import 的文件根本不参与编译。我植入类型错误后仍是 SUCCESSFUL,
才确认"编译通过"当时**什么都没证明**。接入 EntryAbility 后再植入同样的错误 ⇒ `Failed :entry:default@CompileArkTS` 且指名 `PushService.ets:102` ✓
—— 现在这句"编译通过"是有内容的。

**未完成(不掩盖)**:① 登录成功后主动补报一次(现在只在冷启 `onCreate` 报,冷启时未登录 ⇒ 401 静默,等下次冷启才补上);
② `pendingRoute` 的**消费端**(页面读它并跳转)—— 这两处都要动 `LoginPage/MainPage`,而那两个文件正被别人在飞编辑,我没抢着改。
This commit is contained in:
2026-09-15 14:20:00 +08:00
parent 3c8f18d4de
commit 1e3aac2f7d
2 changed files with 269 additions and 0 deletions

View File

@ -16,10 +16,16 @@
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { ApiClient } from '../api/ApiClient';
import { PushService } from '../api/PushService';
import { NotificationLedger } from '../model/PushContract';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
/** 通知点击去重(有界) */
private ledger: NotificationLedger = new NotificationLedger(50);
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
@ -27,6 +33,36 @@ export default class EntryAbility extends UIAbility {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
/*
* 推送上报:**不 await、失败全静默** —— 启动不能被网络/权限阻塞,也不能因为推送不可用而报错。
* 冷启时还没登录 ⇒ POST 会 401,静默忽略;标记没写成功 ⇒ 下次启动会再试一次。
*/
try {
const push: PushService = PushService.getInstance(this.context);
push.reportToken(ApiClient.getInstance(this.context)).catch((err: Object) => {
hilog.info(DOMAIN, 'testTag', 'push 上报异常(静默):%{public}s', JSON.stringify(err));
});
} catch (err) {
hilog.info(DOMAIN, 'testTag', 'push 初始化跳过(静默):%{public}s', JSON.stringify(err));
}
}
/**
* 点通知拉起应用时走这里(应用已在运行时)。
* 解析不出来就**什么都不做** —— 一条格式不认识的通知,最坏结果应当是"没反应",不是"跳到空页面"。
*/
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
const params: Record<string, Object> = want.parameters === undefined
? {} as Record<string, Object>
: want.parameters as Record<string, Object>;
const route = PushService.routeFromWant(params, this.ledger);
if (route !== undefined) {
PushService.pendingRoute = route; // 页面起来后读它
}
} catch (err) {
hilog.info(DOMAIN, 'testTag', '通知跳转解析失败(静默):%{public}s', JSON.stringify(err));
}
}
onDestroy(): void {