# 插件元信息
插件元信息包括名称、描述、作者、版本、图标等。这些信息决定了插件在宿主应用中的展示方式——插件列表、设置页、插件商店都会用到。
# 元信息来源
插件的元信息来自两个地方:
| 来源 | 用途 |
|---|---|
package.json | 基础元数据:id、版本号、作者、仓库地址、许可证 |
resources/lang/*.json | 可翻译的展示文本:名称、描述、作者名(覆盖 package.json 中的值) |
名称和描述支持国际化。插件列表会根据用户当前语言自动切换。
# package.json 字段
package.json 是插件的唯一配置文件。以下是插件系统识别的字段:
{
"name": "@myplugins/my-toolkit",
"version": "1.2.0",
"description": "A powerful toolkit for Android devices",
"author": "Your Name",
"license": "MIT",
"repository": "https://github.com/you/my-toolkit"
}
| 字段 | 必须 | 说明 |
|---|---|---|
name | 是 | 插件唯一标识(pluginPackageName)。推荐使用 npm 包名格式,如 @myplugins/toolkit 或 autumnbox.my-toolkit |
version | 是 | 语义化版本号,用于版本管理和更新检查 |
description | 否 | 插件描述。未在语言文件中覆盖时作为显示文本 |
author | 否 | 作者名。未在语言文件中覆盖时作为显示文本 |
license | 否 | 开源许可证标识(如 MIT、Apache-2.0) |
repository | 否 | 源码仓库地址。支持字符串或 { type, url } 格式 |
name 字段一旦发布就不应更改。它是插件的唯一标识,更改后会被视为一个全新的插件。
# 可翻译的元信息
插件的展示名称和描述可以在语言文件中覆盖,实现多语言支持。在 resources/lang/*.json 中使用特殊前缀键:
实际开发中推荐使用 <name> / <description> / <author> 语法糖。构建工具 autumnbox-sdk package 会自动把它们替换为带 namespace 的 key,避免多插件冲突:
// resources/lang/zh-CN.json(开发者编写)
{
"<name>": "我的工具箱",
"<description>": "一个强大的 Android 设备工具集",
"<author>": "张三",
"app.name.my-tool": "工具",
"card.name.status": "状态卡片"
}
// resources/lang/en-US.json
{
"<name>": "My Toolkit",
"<description>": "A powerful toolkit for Android devices",
"<author>": "Zhang San"
}
打包后,.atmb 内的实际 JSON 会变为:
| 开发者写的 | 打包后变成 | 用途 |
|---|---|---|
"<name>" | "plugin.name.{pluginPackageName}" | 插件显示名称 |
"<description>" | "plugin.description.{pluginPackageName}" | 插件描述 |
"<author>" | "plugin.author.{pluginPackageName}" | 作者名 |
其他自定义 key(如 app.name.*、card.name.*)原样保留,不会被转换。
解析规则: 宿主首先查找语言文件中对应 key 的翻译。如果找不到(即翻译值与 key 相同),则回退到 package.json 中的字段值。
为什么需要 namespace?
多个插件的翻译内容共享同一个 LanguageService。如果所有插件都用 "name" 作 key 会互相覆盖。<name> 糖在编译时自动加前缀,开发者写起来简洁,运行时又不冲突。
即使不在语言文件中覆盖,也建议在 package.json 中填写 description 和 author。这样在未提供翻译的语言环境下仍有展示内容。
# 插件图标(resources/icon.png)
插件可以定义一个专属图标,用于插件列表、设置页等位置的展示。
# 约定
将 PNG 格式的图标文件放在 resources/icon.png:
my-plugin/
├── resources/
│ ├── icon.png ← 插件图标(建议 128×128 或 256×256)
│ └── lang/
│ └── ...
├── src/
└── package.json
构建时 autumnbox-sdk package 会将 resources/ 目录整体打包进 .atmb 文件。运行时可通过 PluginService 访问:
const iconBlob = pluginService.getPluginResource(pluginPackageName, 'icon.png');
# 图标规范
| 属性 | 建议 |
|---|---|
| 格式 | PNG(透明背景) |
| 尺寸 | 128×128 或 256×256 像素 |
| 文件大小 | 建议不超过 100KB |
| 风格 | 圆角矩形(rx 约 22-28),与秋之盒桌面图标风格统一 |
# 与 App 图标的区别
插件有两个层级的图标,不要混淆:
| 图标类型 | 定义位置 | 用途 | 格式 |
|---|---|---|---|
| 插件图标 | resources/icon.png | 插件列表、设置页、插件商店 | PNG 文件 |
| App 图标 | AutumnApp.icon 字段 | 桌面图标、Tab 图标、应用列表 | SVG data URI 或 PNG data URI |
插件图标代表整个插件包,App 图标代表单个功能页面。一个插件可以有多个 App,每个 App 有自己的图标,但插件只有一个图标。
# App 图标
App 图标通过 AutumnApp 定义的 icon 字段指定,在桌面和应用列表中展示。
# 方式一:内联 SVG data URI(推荐)
最常用、最灵活的方式。直接在 TypeScript 中定义 SVG:
const myIcon = `data:image/svg+xml,${encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#6366f1"/>
<stop offset="100%" stop-color="#8b5cf6"/>
</linearGradient>
</defs>
<rect width="128" height="128" rx="28" fill="url(#bg)"/>
<text x="64" y="80" text-anchor="middle" font-size="48" fill="white"
font-family="system-ui" font-weight="bold">TK</text>
</svg>
`)}`;
export const MyApp: AutumnApp = {
id: 'my-toolkit',
name: 'app.name.my-toolkit',
icon: myIcon,
component: MyComponent,
};
优势:
- 矢量图,任何尺寸都清晰
- 文件体积小
- 支持渐变、滤镜等高级效果
- 不需要额外文件
# 方式二:导入 PNG 文件
将 PNG 放在 src/assets/ 目录,通过 import 导入。Vite 构建时会将其转为 data URI:
import myIcon from '~/assets/my-icon.png';
export const MyApp: AutumnApp = {
id: 'my-app',
name: 'app.name.my-app',
icon: myIcon, // Vite 自动转为 data:image/png;base64,...
component: MyComponent,
};
注意:小于 100KB 的 PNG 会被内联为 data URI,超过的会作为外部文件引用。
# 方式三:运行时从 resources/ 加载
从 .atmb 包内懒加载图标资源:
import { usePluginResource } from '@autumnbox/sdk/hooks';
const MyAppView: React.FC = () => {
const { data: iconBlob, loading } = usePluginResource('icons/my-icon.png');
if (loading) return <Spin />;
const iconUrl = iconBlob ? URL.createObjectURL(iconBlob) : '';
return <img src={iconUrl} alt="My Icon" />;
};
适用于大尺寸图标或不需要立即展示的场景。
# iconFit 模式
默认情况下,App 图标在桌面图标中会保持原始比例。设置 iconFit: true 可以让图标填满整个圆角矩形区域(类似 CSS object-fit: cover):
export const MyApp: AutumnApp = {
id: 'photo-viewer',
name: 'app.name.photo-viewer',
icon: myPhotoIcon,
iconFit: true, // 图标填满整个圆角矩形,不保留边距
component: PhotoViewer,
};
适合照片、截图等需要铺满展示的图标。对于文字+背景色的图标,通常不需要开启。
# 完整示例
一个完整的插件元信息配置:
my-toolkit/
├── src/
│ ├── apps/
│ │ └── ToolkitApp.tsx ← 定义 icon 字段(App 图标)
│ └── main.ts
├── resources/
│ ├── icon.png ← 插件图标(128×128 PNG)
│ └── lang/
│ ├── zh-CN.json
│ └── en-US.json
└── package.json
// package.json
{
"name": "@myplugins/toolkit",
"version": "1.0.0",
"description": "A toolkit for Android",
"author": "Developer",
"license": "MIT",
"repository": "https://github.com/dev/toolkit"
}
// resources/lang/zh-CN.json
{
"<name>": "工具箱",
"<description>": "Android 设备工具集",
"app.name.toolkit": "工具箱"
}
// resources/lang/en-US.json
{
"<name>": "Toolkit",
"<description>": "Android device toolkit",
"app.name.toolkit": "Toolkit"
}
// src/apps/ToolkitApp.tsx
import { defineApp } from '@autumnbox/sdk';
const toolkitIcon = `data:image/svg+xml,${encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
<rect width="128" height="128" rx="28" fill="#4f46e5"/>
<text x="64" y="80" text-anchor="middle" font-size="48" fill="white"
font-family="system-ui" font-weight="bold">TK</text>
</svg>
`)}`;
export const ToolkitApp = defineApp({
id: 'toolkit',
name: 'app.name.toolkit',
icon: toolkitIcon,
tags: ['tools'],
component: ToolkitView,
});