更新记录

0.2.1(2026-10-17)

  • uni-app x 版本使用独立插件 ID austin-live-x,显示名称改为“灵动岛 X”;演示页、示例代码和接入检测同步使用新路径。
  • 新增 uni-app x Vapor 支持;同一份 .uvue 演示页兼容 Vapor 与 VDOM。
  • 演示页改用组合式 API,保留自定义布局编辑、配置导出与活动管理。
  • 更新滚动容器写法和 uni-app x 页面接入说明。
  • 保留普通 uni-app Vue3 的 .vue 演示页,公开接口不变。

平台兼容性

uni-app(5.26)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ × × √ × × √ ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x(5.26)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × × √ × ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

灵动岛 X · austin-live-x

把订单进度、排队状态、充电进度、预约倒计时显示在 iPhone 灵动岛和锁屏 上。内置可视化编辑页,改好文字、字段、颜色和排列,直接复制接入代码。

你可以做什么 插件提供什么
快速显示业务状态 进度、倒计时、状态三种基础模板
按业务自由搭配 文字、大数字、自定义字段、进度条、倒计时、阶段条六种区块
分别设计不同位置 锁屏、展开灵动岛、紧凑左侧、紧凑右侧、最小状态
让服务器更新内容 APNs 更新、结束;iOS 17.2+ 远程创建,附 Node.js 示例

适用环境: iOS 16.2+ · HBuilderX 5.26+。当前版本 0.2.1。

项目类型 iOS 支持 使用的演示页
uni-app x · Vapor 蒸汽模式 支持 index.uvue
uni-app x · VDOM 模式 支持 同一份 index.uvue
uni-app · Vue3 支持 index.vue

插件跟随宿主项目的编译模式,无需更换接口。Vue2、nvue、Android、鸿蒙、Web 和小程序不在本插件的支持范围内。

从 austin-live 切换: 本版使用独立 ID austin-live-x。同一项目中两个版本二选一;替换时移除旧插件,将导入路径改为 @/uni_modules/austin-live-x,并重新打包自定义基座。

使用苹果系统 SDK,随插件提供 Widget 扩展,通过 DCloud 云打包接入,无需修改 Swift 或安装 Xcode。没有灵动岛的兼容 iPhone 可显示锁屏卡片;Android、H5、小程序不提供此能力。

第一次接入只做下面 6 步,先跑通本地活动。无需 P8,无需部署服务器。

首次接入:在自己的 iPhone 上显示活动

第 1 步:导入完整插件

在插件市场点击“使用 HBuilderX 导入插件”,导入后确认项目中有:

uni_modules/austin-live-x/
├── index.vue       uni-app Vue3 演示页
├── index.uvue      uni-app x 演示页
└── utssdk/         原生接口与 Widget 扩展,完整保留

第 2 步:准备签名材料

已有能正常打包的 P12 和主应用描述文件,通常只需补一份扩展描述文件。

必需材料 对应什么 稍后放在哪里
.p12 + 导出密码 App 签名证书与私钥 HBuilderX 云打包窗口
主应用 .mobileprovision 例如 com.example.app 云打包窗口的 Profile 栏
扩展 .mobileprovision 例如 com.example.app.LiveActivity 项目 nativeResources/ios/

.mobileprovision 就是描述文件,它绑定 App ID、签名证书和适用设备。主应用、扩展必须使用同一团队、匹配用途的证书,各自独立的描述文件;开发测试时,两份文件都要包含这台 iPhone。

下面以开发测试为例。已有哪项就跳过哪项,com.example.app 均替换成自己的苹果 Bundle ID(不是 DCloud 的 __UNI__... AppID)。

缺 P12:在 Mac 生成并导出

  1. 打开“钥匙串访问”→“证书助理”→“从证书颁发机构请求证书”,填写邮箱和名称,CA 邮箱留空,保存到磁盘得到 CSR。
  2. 登录 Apple Developer,进入 Certificates, Identifiers & Profiles → Certificates → + → Apple Development,上传 CSR,下载 .cer。
  3. 在生成 CSR 的同一台 Mac 双击导入 CER;在钥匙串“我的证书”中,确认该证书下能展开看到私钥。
  4. 导出该证书身份为 .p12,设置并保存导出密码。

只有 CER、没有对应私钥时,不能直接得到可签名的 P12;需从持有私钥的电脑导出。已有有效 P12 无需重复申请。苹果 CSR 操作说明

缺扩展 App ID:新增一个标识

  1. 苹果后台 Identifiers → + → App IDs → App。
  2. Description 填便于识别的名称,Bundle ID 选 Explicit,填 com.example.app.LiveActivity。
  3. Continue → Register。本插件无需勾选 App Groups;本地活动无需开启 Push Notifications。

扩展 ID 必须以“主应用 ID + .”开头,两个 ID 属于同一团队。主应用 ID 还没有时,先按同样流程注册 com.example.app;扩展不需要另上架一个 App。

缺描述文件:主应用、扩展各生成一份

  1. Devices → + 注册测试 iPhone 的 UDID。可在 Mac Finder 选中已连接的 iPhone,点击设备名称下方的信息切换查看 UDID;它不是 IMEI。苹果查看 UDID 步骤
  2. Profiles → + → iOS App Development,选择主应用 App ID。
  3. 选择 P12 对应的开发证书,勾选测试 iPhone,填写名称,Generate → Download。
  4. 重复第 2、3 项,改选扩展 App ID,得到扩展描述文件。已有有效主应用文件时只做这一份。

新增测试设备后,要重新生成包含该设备的两份文件。苹果开发描述文件步骤

后台没有证书权限? 个人开发者账号邀请的 App Store Connect“管理员”没有该账号的证书资源权限,请账户持有人完成本步并提供文件。组织账号由有权限的管理员处理。苹果账号角色说明

第 3 步:把扩展配置放进项目

在包含 manifest.json 的项目根目录创建以下两个文件:

你的项目/
├── manifest.json
├── pages.json
├── uni_modules/austin-live-x/
└── nativeResources/
    └── ios/
        ├── ios-extension.json
        └── LiveActivity.mobileprovision   ← 第 2 步的扩展描述文件

将扩展描述文件复制并命名为 LiveActivity.mobileprovision。新建 ios-extension.json,复制以下内容,只把 identifier 改成自己的扩展 Bundle ID:

{
  "AustinLiveActivityExtension.appex": {
    "identifier": "com.example.app.LiveActivity",
    "profile": "LiveActivity.mobileprovision"
  }
}
这里填什么 注意
AustinLiveActivityExtension.appex 固定名称,与插件自带的扩展文件夹一致
identifier 扩展 Bundle ID,不能填主应用 ID
profile 相对 nativeResources/ios/ 的路径;保持上面文件名即可

已有其他扩展时合并配置,保留原节点。插件自带的 utssdk/app-ios/Plugins/AustinLiveActivityExtension.appex 留在原处。

权限还要配什么? 本地活动需要的 NSSupportsLiveActivities 已由插件提供;无需 uni.authorize、普通通知授权或额外后台模式。系统“实时活动”开关由用户控制。P8 和推送权限在后面的可选推送步骤中配置。

这一步不能省略: 没有 ios-extension.json,云打包不会包含该扩展,即使 UTS 编译成功也无法显示活动。DCloud 扩展配置说明

第 4 步:复制演示页并添加入口

按项目类型只复制一份,目标目录不存在就新建:

项目 复制来源 复制到
uni-app Vue3 uni_modules/austin-live-x/index.vue pages/live-activity/index.vue
uni-app x(Vapor / VDOM) uni_modules/austin-live-x/index.uvue pages/live-activity/index.uvue

完整复制文件,保留原来的 lang="ts" / lang="uts";不要直接改后缀。无需额外复制组件或图片,@/uni_modules/austin-live-x 导入路径保持原样。

在 pages.json 已有的 pages 数组内追加这一项,不要覆盖整份文件:

{
  "path": "pages/live-activity/index",
  "style": { "navigationBarTitleText": "灵动岛与实时活动" }
}

uni-app x 项目: 在上面路由的 style 中再加 "disableScroll": true,由演示页内部的 scroll-view 负责滚动。.uvue 使用组合式 API,同一份页面可用于 Vapor 和 VDOM;无需改插件 ID 或接口。

在自己首页的按钮事件中调用,即可打开:

uni.navigateTo({ url: '/pages/live-activity/index' })

第 5 步:云打包并安装自定义基座

HBuilderX 选中项目,打开 发行 → App-Android/iOS-云打包(部分版本显示“原生 App-云打包”),按表填写:

打包项 填写内容
平台 iOS
Bundle ID 主应用 ID,例如 com.example.app
私钥证书 第 2 步的 .p12
证书密码 导出 P12 时设置的密码
证书 Profile 主应用 .mobileprovision
包类型 勾选“自定义调试基座 / 自定义运行基座”

扩展描述文件通过第 3 步的 JSON 引用,不填到主应用 Profile 栏。

打包完成后,按 HBuilderX 提示取得新基座,连接并解锁 iPhone,信任电脑。在 运行 → 运行到 iOS App 基座中选择使用自定义基座运行,安装并运行刚生成的基座。设备要求开发者模式时,按 iPhone“设置 → 隐私与安全性 → 开发者模式”提示启用。

下载 IPA 之后还要实际安装新基座。标准基座、旧基座和仅同步页面代码都不能补上原生扩展。

第 6 步:创建、查看、更新、结束

打开第 4 步的页面,按以下顺序操作:

操作 应看到什么
点击页面顶部“检查” 状态为设备已就绪
关闭“允许服务端更新”,点击“创建新活动” “当前活动”出现刚创建的记录
返回桌面,长按灵动岛 支持灵动岛的 iPhone 显示紧凑 / 展开内容
锁屏 显示实时活动卡片
回到页面改文字或进度,点“更新所选活动” 系统卡片更新内容
点“结束所选活动” 请求结束并移除活动

页面预览用于编辑,实际灵动岛/锁屏由 iOS 展示。创建时 App 应在前台;系统决定最终展示时机和位置。

未就绪时先按页面提示处理:activitiesEnabled=false 到系统设置开启实时活动;extensionEmbedded=false 检查第 3 步并重新打包安装;undefined class 检查第 5 步是否运行了新基座。


接到自己的业务页面

最省事的方式:在演示页改好内容 →“带走你的配置”→“复制完整接入代码”。

将代码放入业务页面的脚本和对应方法,替换业务编号、文字、时间及跳转地址;无需把整个编辑器留在正式页面中。复制的倒计时是绝对时间,新建活动时要重新计算,更新已有活动时保留原时间。

“复制布局 JSON”只复制布局。使用时还需传 businessId、template: 'custom'、title,并把布局放入 layoutJson 字符串。

最小调用示例

下面代码放入现有页面脚本,按按钮依次调用三个函数;每次等上次回调完成再操作:

import {
  startLiveActivity, updateLiveActivity, endLiveActivity
} from '@/uni_modules/austin-live-x'

let activityId = ''

function createActivity() {
  if (activityId.length > 0) return
  startLiveActivity({
    businessId: 'task-' + Date.now(),
    template: 'progress',
    pushEnabled: false,
    title: '任务处理中',
    status: '已完成 30%',
    progress: 0.3,
    success: result => { activityId = result.activityId },
    fail: error => { console.error(error.errCode, error.errMsg) }
  })
}

function updateActivity() {
  if (activityId.length === 0) return
  updateLiveActivity({
    activityId: activityId,
    title: '任务处理中',
    status: '已完成 80%',
    progress: 0.8,
    fail: error => { console.error(error.errCode, error.errMsg) }
  })
}

function finishActivity() {
  if (activityId.length === 0) return
  endLiveActivity({
    activityId: activityId,
    dismissImmediately: true,
    success: () => { activityId = '' },
    fail: error => { console.error(error.errCode, error.errMsg) }
  })
}

两个接口规则: 创建、更新、结束使用回调,不能用 await 等待成功;更新是完整替换,需重传要保留的文字、颜色、原起止时间和完整布局。App 重启后,通过 getLiveActivities().activities 按 businessId 找回活动。

点击卡片打开业务页面(可选)

传入 deepLink: 'yourapp://activity/detail?id=123'。宿主先注册自己的 URL Scheme,并处理打开链接时的业务路由;使用 HTTPS Universal Link 时,还需 Associated Domains 和网站的 apple-app-site-association 文件。不需要跳转就省略该字段。DCloud URL Scheme 与关联域配置


可选:接入服务器推送

需要 App 退到后台后由服务器更新状态,再做这一部分。本插件直接使用 ActivityKit,不依赖 UniPush 或第三方推送 SDK。

A. 给主应用开启推送能力

  1. 苹果后台 Identifiers → 主应用 App ID → Capabilities,开启 Push Notifications 并保存。
  2. 重新生成并下载带该能力的主应用描述文件;已有文件已包含正确权限时可沿用。
  3. 在项目 nativeResources/ios/UniApp.entitlements 合并以下内容。已有文件要保留其他权限键;宿主已正确配置时不重复添加。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>aps-environment</key>
    <string>development</string>
  </dict>
</plist>
签名用途 aps-environment 服务端 APNS_ENVIRONMENT
iOS App Development development sandbox
Ad Hoc / TestFlight / App Store production production
  1. 用匹配的主应用与扩展描述文件重新打包安装。只改 XML 不会获得苹果后台尚未授权的能力。

B. 申请或确认 APNs P8

  1. 登录 Apple Developer,进入 Certificates, Identifiers & Profiles → Keys → +。
  2. 填写名称,勾选 Apple Push Notifications service (APNs);如有 Configure,选择匹配的环境和应用范围,继续并注册。
  3. 下载 .p8,记录这把 Key 的 Key ID。私钥只提供一次下载,妥善保存。
  4. 到账号 Membership details 记录 Team ID。三项必须属于同一团队。

已有 P8 可以复用,先在 Keys 详情核对: APNs 已启用、未撤销、允许当前应用和推送环境。不能只凭 .p8 后缀判断;App Store Connect API Key 不能用作 APNs Key。新密钥按所选环境/范围使用,旧版同时支持开发与生产的密钥按原授权使用。

P8 只放服务器,不放进 App、插件或 DCloud 打包资料。 云打包仍用 P12 和描述文件。

C. 配好服务端示例

需要 Node.js 20.6+,无 npm 运行时依赖。把插件 server/ 中以下公开文件复制到自己的后端目录:

live-activity/
├── apns.mjs
├── layout.mjs
├── cli.mjs
├── package.json
├── config.example.env
└── examples/

打开终端,路径替换为自己的后端目录:

cd "/absolute/path/to/你的后端/live-activity"
cp config.example.env .env.local
chmod 600 .env.local

编辑 .env.local:

APNS_BUNDLE_ID=com.example.app
APNS_ENVIRONMENT=sandbox
APNS_KEY_ID=ABC123DEFG
APNS_TEAM_ID=DEF123GHIJ
APNS_P8_PATH="/absolute/path/to/AuthKey_ABC123DEFG.p8"

分别填主应用 Bundle ID、推送环境、Key ID、Team ID、服务器上 P8 的绝对路径。.env.local、P8 和 Token 文件不要提交到代码仓库。

D. 取得活动 Token,发送一次更新

  1. 演示页先选择进度模板,打开“允许服务端更新”,创建一个新活动,与本节 update.json 示例对应。已有未启用推送的活动需要重建。
  2. 在“跳转与推送”点击“复制当前活动 Token”。首次为空时稍后再试,Token 由系统异步生成。
  3. 在后端目录新建 activity.token,仅粘贴该 Token。编辑 examples/update.json 中的文字、进度;暂不使用跳转时把 deepLink 改为 ""。
  4. 执行以下命令,先检查,再发送:
chmod 600 activity.token
node --env-file=.env.local cli.mjs --check-key
node --env-file=.env.local cli.mjs update --payload examples/update.json
node --env-file=.env.local cli.mjs update --payload examples/update.json --token-file activity.token --send

--check-key 只在本地验证密钥可签名;不加 --send 只检查参数。最后一条才发送推送。发送后到 iPhone 锁屏/灵动岛查看更新;APNs 返回成功表示已接收,最终展示仍由设备和系统决定。

更新自定义活动时,在 contentState 中额外填写完整 layout 对象,可使用演示页复制的布局 JSON;更新倒计时活动时保留原起止时间,不能直接套用本节无布局、时间为 0 的基础示例。

结束活动:

node --env-file=.env.local cli.mjs end --payload examples/end.json --token-file activity.token --send

先把 examples/end.json 的 contentState 改为本活动的完整最终内容;自定义活动同时携带完整 layout。示例 dismissalDate: 0 请求立即移除,删除该字段则由系统决定移除时间。

E. 远程创建活动(iOS 17.2+,按需使用)

演示页“复制远程启动 Token”取得的是 pushToStartToken,另存为 push-to-start.token。修改 examples/start.json 的业务编号、内容和提醒文字后执行:

node --env-file=.env.local cli.mjs start --payload examples/start.json --token-file push-to-start.token --priority 10 --send
操作 使用哪个 Token
远程创建 pushToStartToken
更新 / 结束已有活动 该活动自己的 pushToken
普通消息通知 device token,不能用于上述两种操作

远程创建后,后续更新改用新活动的 pushToken。示例不自动重试 start,超时先确认是否已创建,防止重复;业务后端按订单/事件处理去重。本版不包含广播 channel。

正式业务如何对接

App 用 getLiveActivityPushInfo() 查询最新 Token,与用户、设备、业务 ID 一起上传自己的服务器。首次为空可稍后重查;创建后和 App 回到前台时刷新,Token 轮换后同步新值。插件不会自动上传。

后端可直接复用 apns.mjs;长驻服务只初始化一次 Token provider:

import {
  readConfiguration, loadPrivateKey, createTokenProvider,
  buildPayload, sendNotification
} from './apns.mjs';

const config = readConfiguration(process.env, true);
const tokenProvider = createTokenProvider({
  keyId: config.keyId,
  teamId: config.teamId,
  privateKey: await loadPrivateKey(config)
});

export async function updateOrder(activityToken, fullContentState) {
  return sendNotification({
    config,
    notification: buildPayload('update', { contentState: fullContentState }),
    token: activityToken,
    tokenProvider
  });
}

APNS_BUNDLE_ID 始终填主应用 ID;示例发送 apns-push-type: liveactivity,topic 为 <主应用 Bundle ID>.push-type.liveactivity。收到 410 Unregistered 后停用旧 Token。


接口速查

首次显示活动只需完成前面的步骤;以下用于把演示参数替换为自己的业务数据。

接口与返回值

全部从 @/uni_modules/austin-live-x 导入。

接口 返回方式 / 用途
getLiveActivityCapabilities() 同步返回设备与配置状态
startLiveActivity(options) 回调返回创建结果,函数返回 void
updateLiveActivity(options) 回调返回完整内容更新结果,函数返回 void
endLiveActivity(options) 回调返回结束结果,函数返回 void
getLiveActivities() 同步返回 { activities: [...] },不是数组
getLiveActivityPushInfo() 同步返回推送 Token 缓存

创建与更新参数

字段 类型 使用时机 / 默认值 / 限制
businessId string 创建必填,非空 ≤128 字符;不能与尚在 active/stale 的活动重复
template string 仅创建;默认 progress,可选 timer、status、custom
pushEnabled boolean 仅创建;默认 false,true 为该活动申请推送 Token
activityId string 更新、结束必填;系统活动 ID,非空 ≤256 字符
title string 创建、更新必填,非空 ≤80 字符;custom 同样必填
subtitle string 默认 '',≤160 字符
status string 默认 '',≤40 字符
progress number 默认 0,范围 0–1;0.65 表示 65%
startTime / endTime number 默认 0,Unix 毫秒,范围 0–4102444800000
symbol string 默认 shippingbox.fill;SF Symbols 名称,≤80 字符,仅字母、数字、.
accentColor string 默认 #176BFF,格式 #RRGGBB
deepLink string 默认 '',≤1024 字符;带 scheme、无空白,拒绝 javascript/data/file/about
layoutJson string custom 必填的布局 JSON 字符串;其他模板省略或传 ''
staleAfterSeconds number 默认 3600,范围 60–28800 秒;内容过期标记,不会自动结束活动

参数放在 options 第一层;App 接口不使用服务端的 contentState 包装。businessId、template、pushEnabled 创建后不可修改,要变更需结束后重建。

倒计时: template: 'timer' 要求 startTime > 0 且 endTime > startTime。例如创建时保存 Date.now() 和它加 10 * 60 * 1000 的值,每次更新沿用这两个值。custom 顶层时间可都为 0;任一非零时须同时提供有效起止时间,继承计时的区块/槽位也需要有效顶层时间。系统自行刷新倒计时,无需每秒调用更新。

结束参数与操作回调

endLiveActivity 接收 activityId、可选 dismissImmediately(默认 true)及回调。设为 false 时,结束后由系统决定保留多久。需要完成状态时,先更新成功再结束;结束接口不接收新的内容字段。

回调 调用时机
success(result) 操作成功,一次
fail(result) 操作失败,一次
complete(result) success 或 fail 之后一次,不代表一定成功

三个回调均可选,建议至少处理 fail。同一活动的操作按回调串行执行,避免重复点击或并发更新。

result 字段 类型 成功 / 失败
ok boolean true / false
activityId / businessId string 对应 ID / 空字符串
errCode number 0 / 错误码
errMsg string 空字符串 / 错误说明

设备状态 getLiveActivityCapabilities()

字段 类型 含义
supported boolean 当前平台与系统是否支持,单独为 true 不代表配置完成
activitiesEnabled boolean 系统是否允许本 App 使用实时活动
extensionEmbedded boolean 安装包是否包含本插件 Widget 扩展
liveActivitiesConfigured boolean 主应用是否包含 NSSupportsLiveActivities=true
platform string ios / android / other
minimumSystemVersion / systemVersion string 最低版本 16.2 / 当前系统版本
pushToStartSupported boolean 是否达到 iOS 17.2 远程创建版本要求
pushEnvironment string 当前固定为 unknown;按实际签名确定推送环境
templates string[] progress、timer、status、custom;仍须判断 supported

本地创建前检查前四项均为 true,并在 App 前台调用;操作失败继续处理 fail 回调。

活动查询 getLiveActivities()

从 .activities 按 businessId 找回业务活动,保存 activityId 用于更新/结束:

import { getLiveActivities } from '@/uni_modules/austin-live-x'

const item = getLiveActivities().activities.find(activity =>
  activity.businessId === 'your-order-id')
if (item != null && (item.state === 'active' || item.state === 'stale')) {
  // 使用 item.activityId;计时活动同时恢复 item.startTime / item.endTime。
}
每项字段 类型 / 内容
activityId、businessId、template string,系统 ID、业务 ID、模板
state string:active / stale / ended / dismissed / unknown
title、subtitle、status string,当前文字
progress、startTime、endTime number,进度与毫秒时间
symbol、accentColor、deepLink string,图标、颜色、跳转
layoutJson string,完整布局;未使用时为 ''

在页面 onShow 和操作完成后刷新;插件没有 JS 常驻监听接口。系统刷新可能稍有延迟。布局经过原生重新编码,比较时解析 JSON 后比较字段,不比较字符串顺序。

推送查询 getLiveActivityPushInfo()

字段 类型 / 内容
supported boolean,是否支持查询,不代表 APNs 接入成功
pushToStartSupported boolean,是否支持 iOS 17.2+ 远程创建
pushToStartToken string,远程创建令牌;未取得时为 ''
activityTokens 数组,每项为 { activityId, businessId, pushToken },三个字段均为 string
updatedAt number,令牌缓存发生变化的 Unix 毫秒时间;初始为 0,不是本次查询时间

activityTokens 对应 active/stale 活动;未启用推送或尚未取得令牌时 pushToken 可为空。活动结束后停止保留其令牌。查询不会发送推送、验证 P8 或上传服务器。


自定义布局字段

可先在演示页配置并复制 JSON;手写时遵循下面的结构。只填写当前类型支持的字段,可选字段不用就省略,不填 null。

最小布局

{
  "version": 1,
  "lockScreen": [
    { "id": "title", "type": "text", "text": "任务处理中" },
    { "id": "progress", "type": "progress" }
  ],
  "expanded": [
    { "id": "title", "type": "text", "text": "任务处理中" },
    { "id": "progress", "type": "progress" }
  ],
  "compactTrailing": { "type": "progress" }
}

创建时传 template: 'custom'、必填 businessId 和 title,把上述布局序列化到 layoutJson。示例进度条跟随顶层 progress;更新时继续传完整布局和内容。

根对象与五个区域

字段 类型 规则
version number 必填,固定为数字 1
appearance object 可选,配色与密度
lockScreen Block[] 必填,锁屏 1–4 个区块
expanded Block[] 必填,展开灵动岛 1–3 个区块
compactLeading Slot 可选,紧凑左侧
compactTrailing Slot 可选,紧凑右侧
minimal Slot 可选,最小状态

区块按数组顺序显示,同一区域 id 不能重复。三个槽位省略时均显示顶层 symbol;要显示百分比需明确设为 progress。

样式 appearance 与区块公共字段

appearance 字段 类型 / 默认值
accentColor string,继承活动顶层主题色
textColor string,默认白色
secondaryTextColor string,默认 72% 不透明度白色
backgroundColor string,默认深灰蓝;只影响锁屏卡片
density string,comfortable(默认)或 compact

所有自定义颜色采用 #RRGGBB,不接受 #FFF、透明度、颜色名称或空值。

Block 公共字段 类型 / 规则
id 必填 string,1–32 位字母、数字、_、-
type 必填 string,下面六种类型之一
title 可选 string,小标题 ≤24
color 可选 string,局部颜色;text 覆盖主文字,fields 覆盖值,其余类型覆盖主题色
size 可选 string,small / medium / large,默认 medium;影响 text、metric 字号
align 可选 string,leading / center / trailing,默认 leading;控制容器与文字/字段对齐

标题、字段标签和 detail 使用辅助文字色。align 不改变进度条、计时行、阶段条内部结构。

六种区块:各自可以填写什么

下表专用字段之外,只能使用上表的公共字段。例如 text 不能携带 currentStep,即使值为 null 也不行。

type 展示内容 专用字段
text 单行文字 必填 text: string,非空 ≤80
metric 大数字 / 短信息 必填 text: string,非空 ≤24;可选 detail: string ≤48
fields 两列字段 必填 items: Field[],1–4 项,按顺序排列
progress 进度条 可选 value: number,0–1;省略时跟随顶层 progress
timer 系统倒计时 可选 startTime、endTime,Unix 毫秒;分别省略时继承顶层对应时间
steps 阶段条 必填 labels: string[],2–4 项、每项非空 ≤8;必填 currentStep: number,整数,从 0 开始,小于阶段数

fields.items 每项仅包含:必填 label: string(非空 ≤16)、value: string(非空 ≤24),可选 color: string。值的颜色按“字段项 → 区块 → 主文字色”继承。

{
  "id": "details",
  "type": "fields",
  "items": [
    { "label": "取餐号", "value": "A016" },
    { "label": "取餐位置", "value": "一楼服务台", "color": "#FBBF24" }
  ]
}
{ "id": "stages", "type": "steps", "labels": ["准备", "处理", "完成"], "currentStep": 1 }

进度区块写了独立 value,就不再跟随顶层进度;计时区块写了独立时间,也不会随顶层时间改变。计时的最终开始值须大于 0、结束值须晚于开始;显式填 0 不等于省略继承。独立时间均有效且其他区域无需顶层计时时,顶层时间可为 0 / 0。

灵动岛槽位 Slot

共有字段为必填 type 和可选 color(主题色)。只可再添加对应类型的专用字段:

type 专用字段 紧凑状态 / 最小状态
symbol 可选 symbol: string,≤80,仅字母、数字、.;默认顶层图标 系统图标 / 系统图标
text 必填非空 text: string,≤6 单行文字 / 前 2 个字符,建议直接填 1–2 字符
progress 无,跟随顶层 progress 百分比 / 圆形进度环
timer 无,使用有效顶层起止时间 倒计时数字 / 计时图标

槽位不接受 value、独立起止时间、size 或 align。minimal 的 timer 同样需要有效顶层时间。图标使用目标 iOS 已有的 SF Symbol,自定义槽位遇到缺失图标会使用后备图标。

uni-app x 动态生成布局

使用动态 UTSJSONObject,只输出适用字段;不要先转成包含大量可选字段的 DTO 再序列化。下面函数返回值可直接作为 layoutJson:

function makeLayoutJson(): string {
  const heading: UTSJSONObject = { id: 'title', type: 'text', text: '任务处理中' }
  const progress: UTSJSONObject = { id: 'progress', type: 'progress' }
  const expandedHeading: UTSJSONObject = { id: 'title', type: 'text', text: '任务处理中' }
  const expandedProgress: UTSJSONObject = { id: 'progress', type: 'progress' }
  const trailing: UTSJSONObject = { type: 'progress' }
  const layout: UTSJSONObject = {
    version: 1,
    lockScreen: [heading, progress],
    expanded: [expandedHeading, expandedProgress],
    compactTrailing: trailing
  }
  return JSON.stringify(layout)
}

不同区域使用独立对象,避免重复引用导致序列化异常。uni-app 的纯 JS 脚本使用同样结构,去掉类型标注即可。按条件增加可选字段时用 field['color'] = '#FBBF24';value: 0、currentStep: 0 是合法数值,不要用真值判断漏掉它们。

内容与空间上限

布局文字长度按 JavaScript string.length(UTF-16)计算,表情可能占多个单位。顶层文字原生按 Swift 字符计数,服务端按 JS 长度检查;建议业务先 trim() 并按 JS 长度控制。输入上限不等于屏幕可完整显示的长度,卡片请使用短文字。数字均须为有限数值,可选字段直接省略,禁止 null。

内容限制 上限
完整原生调用参数 JSON 16,384 UTF-8 字节
layoutJson 输入 12,000 UTF-8 字节,仍受下一项约束
原生编码后的状态 + 属性 3,500 UTF-8 字节,包含业务 ID、模板和完整布局
完整 APNs payload 4,096 UTF-8 字节

每个区域还有高度预算:锁屏 128,展开 112。按下面占用相加,再加相邻间距(compact 为 4,comfortable 为 6):

区块 基础占用 额外占用
text small / medium / large:20 / 24 / 32 非空 title +16
metric small / medium / large:44 / 50 / 58,已含标题位 非空 detail +14
fields 每两项 36,不足两项算一行 非空 title +16
progress 26 非空 title +16
timer 30 非空 title +16
steps 42 非空 title +16

超限时减少区块、字段、标题或补充说明,缩小 text/metric 字号,或使用 compact。不要添加未定义的 height/fontSize/padding。

灵动岛背景、尺寸和展示状态由系统决定。本版不支持任意 Vue/CSS、远程图片、自定义字体或交互按钮;实时活动也不会让后台 JS 保活。


服务端 JSON 速查

CLI 的 --payload 读取业务 JSON,自动包装为 APNs aps。所有事件都提交完整 contentState,不支持局部补丁。 从附带的 server/examples/ 选择最接近的示例修改即可。

示例文件 用途
update.json 更新已有活动
end.json 结束活动,包含最终内容
start.json 远程创建基础模板
custom-start.json 远程创建自定义布局

contentState 必填内容

基础内容的九个字段均需提供;title 始终非空,subtitle / status / deepLink 不使用时传 "",不使用的时间传 0,图标和颜色填合法值:

{
  "contentState": {
    "title": "订单配送中",
    "subtitle": "骑手正在前往目的地",
    "status": "预计 8 分钟送达",
    "progress": 0.65,
    "startTime": 0,
    "endTime": 0,
    "symbol": "bicycle",
    "accentColor": "#2563EB",
    "deepLink": ""
  }
}

字段类型及长度同 App 内容参数。时间使用毫秒整数,均有值时结束不能早于开始;远程创建 timer 时开始须大于 0、结束须晚于开始。custom 额外传 contentState.layout 对象,不能传 layoutJson 或再次序列化成字符串;结构与前面的布局完全一致。

其他字段 规则
attributes 仅 start 必填:businessId 非空 ≤128,template 为四种模板之一;custom 必须有 layout,其他模板不能有
alert start 必填,update/end 可选;非空 title ≤100、body ≤200,可选非空 sound ≤100
timestamp 可选 Unix 秒,默认当前时间,不要重放过期时间戳
staleDate 可选 Unix 秒,仅 start/update,映射到 stale-date
dismissalDate 可选 Unix 秒,仅 end,映射到 dismissal-date
relevanceScore 可选非负数字,映射到 relevance-score

CLI 固定使用 attributes-type: AustinLiveActivityAttributes。App 的起止时间用毫秒,APNs 的 timestamp/staleDate/dismissalDate 用秒;这是两组不同字段。

常用调试参数

参数 / 行为 说明
不带 --send 离线校验,不读取 P8、不联网;只需设置 APNS_BUNDLE_ID
--check-key 本地读取 P8 并验证签名,不验证其苹果后台授权
--priority 5 / 10 默认 5;10 请求及时投递,仍受系统预算限制
--expiration <Unix 秒> 默认 0,离线不保存;可设置未来过期时间
--write-payload <新文件路径> 导出实际 APNs JSON;目标文件必须不存在

可把导出的 JSON 放到苹果 Push Notifications Console 调试:选主应用和匹配环境,使用 liveactivity 类型、活动 Token 与该 payload。通过控制台测试无需向控制台提供 P8。

正式服务复用 Token provider(JWT 默认缓存 45 分钟);每次请求默认 15 秒超时。示例仅对 update/end 明确返回的 500/503 重试一次;start、429、超时及连接中断不自动重试。失败按状态码、reason 和 apnsId 排查,不能用 apnsId 代替业务去重。

官方格式:ActivityKit 推送、APNs Token 鉴权。


常见问题与错误码

问题 怎么处理
undefined class / 设备状态读取失败 按第 5 步安装并运行包含当前插件的新自定义基座;仅下载 IPA 或同步页面无效
extensionEmbedded=false 按第 3 步检查 JSON、扩展 ID 和扩展描述文件,确认插件 .appex 保留,再重新打包安装
liveActivitiesConfigured=false 检查主应用是否覆盖了插件的 NSSupportsLiveActivities 声明,改正后重打包
activitiesEnabled=false iPhone“设置 → App → 你的 App”开启实时活动;不同系统入口略有区别
layout.lockScreen[0] 不支持字段 currentStep currentStep 只属于 steps;移除其他区块的该键,包括自动生成的 null
更新后文字/颜色消失,倒计时重置 更新会完整替换;重传全部保留字段与原起止时间,custom 同时传完整 layoutJson
更新 progress 后进度条不变 区块有独立 value,移除它以继承或一并更新布局
复制页面后找不到模块 保留整个插件,使用对应 vue/uvue,导入路径为 @/uni_modules/austin-live-x
活动 Token 一直为空 检查 pushEnabled:true、主应用推送签名和网络;Token 异步生成,稍后查询,P8 不是客户端取 Token 的条件
InvalidProviderToken / 403 核对 P8、Key ID、Team ID、APNs 权限、环境/Topic 范围、撤销状态及服务器时钟
BadDeviceToken / DeviceTokenNotForTopic 核对 Token 类型、安装包环境、主应用 topic;不要填扩展 ID
410 Unregistered 停用旧 Token,获取新活动/令牌后再发
推送成功但未显示 确认活动未结束、实时活动已允许、payload 和时间有效;APNs 接收不等于设备展示
无法导出 P12 / IPA 无法安装 前者检查对应私钥;后者检查两份 profile 的证书、有效期、设备和分发类型
errCode 含义 / 处理
9010201 参数、布局或长度不合法,按 errMsg 定位字段
9010202 系统版本或平台不支持
9010203 系统未允许实时活动
9010204 缺少 Widget 扩展
9010205 businessId 已有活动,查出后更新或先结束
9010206 活动不存在或已结束,刷新列表
9010207 原生错误、数量限制或操作尚未完成,按 errMsg 处理
9010208 本地创建不满足前台要求,回到 App 前台
9010209 实时活动声明或签名权限缺失,检查配置并重打包

Android/H5 等未适配平台的创建、更新、结束返回 9010202;查询 supported 为 false、活动为空。应据此隐藏不可用入口。

哪些改动需要重新打包

改动 处理
文字、字段、颜色、区块顺序、进度 调用创建/更新,无需重打基座
复制到自己项目的演示页逻辑 重新运行同步页面
首次导入、修改插件 ID、升级原生代码或 .appex 重打并安装新自定义基座 / App
Bundle ID、描述文件、推送权限 重打并安装新包

发布正式 App 时换什么

用途 证书与描述文件类型 设备要求
开发测试 Apple Development + iOS App Development 主/扩展均包含测试设备
指定设备分发 Apple Distribution + Ad Hoc 主/扩展均包含指定设备
TestFlight / App Store Apple Distribution + App Store Connect 通过 TestFlight / App Store 分发,不直接安装此类 IPA

主应用与扩展一起换成同团队、同用途、匹配证书的文件。正式云打包时不勾选自定义基座。推送环境按签名确定: Development 仍用 sandbox;Ad Hoc / TestFlight / App Store 用 production,并使用匹配的 Token 和密钥授权。

可选:macOS 打包前检查

在项目根目录执行,替换主应用 ID 和主描述文件路径:

node uni_modules/austin-live-x/scripts/check-ios-setup.mjs \
  --project "$PWD" \
  --bundle-id com.example.app \
  --main-profile "/absolute/path/to/MyAppDev.mobileprovision"

需要核对推送时加 --environment development 或 production。脚本使用 macOS 的 security/plutil 检查路径、标识、团队、有效期与配置,不修改项目、不上传证书。

插件文件保留哪些

路径 用途
utssdk/、package.json 运行必需,完整保留;utssdk 包含真机 Widget 扩展
index.vue / index.uvue 两类项目的演示编辑页;正式业务可只用 API,不注册演示页
README.md 本使用文档
scripts/check-ios-setup.mjs 可选打包配置检查
server/ 可选后端示例,复制到服务器使用

签名文件放在宿主项目对应配置位置,服务器私钥和环境配置保存在服务器。插件无需额外下载第三方运行时 SDK。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

iOS 需启用实时活动并嵌入 Widget Extension。远程更新需主应用推送能力及匹配签名;APNs 私钥仅配置于服务端。首版不依赖 App Groups、定位或相册权限。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

本地实时活动由 iOS 系统展示。启用远程更新时会取得 ActivityKit 推送令牌,宿主负责向自己的业务服务器提交并管理令牌,服务器通过苹果 APNs 发送更新。插件不内置服务器地址,不收集数据,不包含推送私钥。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。