PKU harness
SDK reference

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.

On this page