更新记录
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 生成并导出
- 打开“钥匙串访问”→“证书助理”→“从证书颁发机构请求证书”,填写邮箱和名称,CA 邮箱留空,保存到磁盘得到 CSR。
- 登录 Apple Developer,进入 Certificates, Identifiers & Profiles → Certificates → + → Apple Development,上传 CSR,下载
.cer。 - 在生成 CSR 的同一台 Mac 双击导入 CER;在钥匙串“我的证书”中,确认该证书下能展开看到私钥。
- 导出该证书身份为
.p12,设置并保存导出密码。
只有 CER、没有对应私钥时,不能直接得到可签名的 P12;需从持有私钥的电脑导出。已有有效 P12 无需重复申请。苹果 CSR 操作说明
缺扩展 App ID:新增一个标识
- 苹果后台 Identifiers → + → App IDs → App。
- Description 填便于识别的名称,Bundle ID 选 Explicit,填
com.example.app.LiveActivity。 - Continue → Register。本插件无需勾选 App Groups;本地活动无需开启 Push Notifications。
扩展 ID 必须以“主应用 ID + .”开头,两个 ID 属于同一团队。主应用 ID 还没有时,先按同样流程注册 com.example.app;扩展不需要另上架一个 App。
缺描述文件:主应用、扩展各生成一份
- Devices → + 注册测试 iPhone 的 UDID。可在 Mac Finder 选中已连接的 iPhone,点击设备名称下方的信息切换查看 UDID;它不是 IMEI。苹果查看 UDID 步骤
- Profiles → + → iOS App Development,选择主应用 App ID。
- 选择 P12 对应的开发证书,勾选测试 iPhone,填写名称,Generate → Download。
- 重复第 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. 给主应用开启推送能力
- 苹果后台 Identifiers → 主应用 App ID → Capabilities,开启 Push Notifications 并保存。
- 重新生成并下载带该能力的主应用描述文件;已有文件已包含正确权限时可沿用。
- 在项目
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 |
- 用匹配的主应用与扩展描述文件重新打包安装。只改 XML 不会获得苹果后台尚未授权的能力。
B. 申请或确认 APNs P8
- 登录 Apple Developer,进入 Certificates, Identifiers & Profiles → Keys → +。
- 填写名称,勾选 Apple Push Notifications service (APNs);如有 Configure,选择匹配的环境和应用范围,继续并注册。
- 下载
.p8,记录这把 Key 的 Key ID。私钥只提供一次下载,妥善保存。 - 到账号 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,发送一次更新
- 演示页先选择进度模板,打开“允许服务端更新”,创建一个新活动,与本节 update.json 示例对应。已有未启用推送的活动需要重建。
- 在“跳转与推送”点击“复制当前活动 Token”。首次为空时稍后再试,Token 由系统异步生成。
- 在后端目录新建
activity.token,仅粘贴该 Token。编辑examples/update.json中的文字、进度;暂不使用跳转时把deepLink改为""。 - 执行以下命令,先检查,再发送:
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。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 642
赞赏 4
下载 12688623
赞赏 1956
赞赏
京公网安备:11010802035340号