notify
The NotifyReadiness type and the deliveryBlocker function, for screens that check whether reminders and scheduled checks can arrive on time.
For reminders and scheduled checks to arrive on time, the user has to allow a few things in the
system settings. This module helps a plugin screen find out which one is missing and guide the
user to turn it on. Use it with services.notify.readiness(), which reads the current state, and
services.notify.fix(kind), which shows the system prompt or opens the matching system screen.
Source: packages/sdk/src/notify.ts.
What on-time delivery needs
Android is supported first. On Android, on-time delivery needs the following:
- The notification permission.
- The "Alarms & reminders" special access, which allows exact alarms. Android 14 and later deny it by default.
- No battery optimisation for the app. This one is only recommended. Reminders still fire on time without it.
Types and functions
type NotifyPermission = 'granted' | 'undetermined' | 'denied';
interface NotifyReadiness {
/** 'denied' = the system won't ask again; only system settings can turn it on. */
notifications: NotifyPermission;
/** Exact alarms allowed (always true where the OS has no such permission). */
exactAlarms: boolean;
/** The OS may defer the app's background work (battery optimisation on). */
batteryOptimized: boolean;
}
/** Something the user can fix: shows the system prompt or opens the matching system screen. */
type NotifyFixKind = 'notifications' | 'exactAlarms' | 'battery';
/**
* The first thing that stops reminders from arriving on the minute, or null when nothing does.
* Battery optimisation is advisory (exact alarms still fire), so it never blocks.
*/
function deliveryBlocker(r: NotifyReadiness): 'notifications' | 'exactAlarms' | null;Example: showing a fix button
A screen only needs to show a fix button when something actually blocks delivery. Call fix only
when the user taps:
import { deliveryBlocker, type NotifyReadiness, type PluginScreenProps } from '@pku-harness/sdk';
import { useEffect, useState } from 'react';
export function ReminderBanner({ host, services }: PluginScreenProps) {
const { Button } = host.components;
const [r, setR] = useState<NotifyReadiness | null>(null);
useEffect(() => void services.notify.readiness().then(setR), [services]);
const blocker = r && deliveryBlocker(r);
if (!blocker) return null;
return (
<Button
title={blocker === 'notifications' ? '允许通知' : '允许准时提醒'}
variant="secondary"
onPress={() => void services.notify.fix(blocker).then(setR)}
/>
);
}The user may come back from a system screen without changing anything. Read the readiness again when the app returns to the foreground.
scheduler
Types and helpers for the scheduler. Trigger, Action, Condition and Job with their zod schemas, the pure recurrence engine, the model-friendly ScheduleInput format, condition evaluation and the limits for unattended runs.
campus
Types for signed-in campus requests through the host (CampusService, CampusRequest, CampusResponse, multipart uploads, picked files), the sign-in status and the 手机令牌 (IAAA authenticator) code.