License 接入指南
版本: 1.0.3 平台: Android arm64-v8a · Linux aarch64
概述
ACL Pack 使用基于文件的 License 系统,通过加密签名验证防篡改。每个 License 绑定:
- licenseId — 唯一标识,在我方交付台账中可回溯
- Tier(层级) — 必须与编译的库层级匹配(Trial / Starter / Pro / Business)
- 签发日期 — License 的签发时间
- 登记有效期 — 订阅服务窗口,记录你享受更新与技术支持的资格期。在购买约定范围内,你收到的版本在窗口结束后可继续使用;续费即可继续获得后续版本。
有效期内的订阅服务
登记有效期为 1 年(可续费延长)。我们会根据你的 licenseId 主动推送:
- 新算子 — 版本迭代新增的 NEON/CPP 实现
- 性能优化 — 相同算子的更快版本
- Bug 修复 — 兼容性、边界条件、稳定性改进
- 平台扩展 — 如新增 Android ABI(armeabi-v7a / x86_64)、新增 Linux 发行版、iOS 移植(按 tier 可用性;Linux aarch64 已在 v1.0.3 实装)
- 技术支持 — Pro / Business / Enterprise 享优先邮件或专属工程师响应
有效期结束后,你收到的版本可在购买约定的范围内继续使用;要获取之后新版本 / 性能改进,续费即可。定价参见套餐定价。
License 不绑定 Android 包名或 APK 签名证书。只要在购买约定的范围内使用,你可以在自有 app 中部署,调试 / 发布构建签名变化、重新打包都不需要重新申请 License。
转分发、OEM 转售、向其他公司分享本库均不在购买范围内。一经发现,我方将依法追究法律责任 — 完整条款见随 SDK 交付的 README.md / README_CN.md。
License 如何送达
淘宝购买(标准 tier)
淘宝店铺下单后,订单自动发货:
- 为你的订单分配
license.dat - 通过淘宝旺旺消息向你发送 SDK zip 和
license.dat - 订单与 license 绑定,便于售后(续费、补发)
无需注册、邮件往返或提交技术信息。打开 zip,把 .a 和头文件放进工程,license.dat 一并放入即可构建。
企业 OEM / 源码
每家 OEM 独立构建(见定价页)请联系 zangotech@163.com — 我方将提供 OEM 合同模板与商务对接。
关于 License 文件
license.dat 是签名的文本文件。请勿修改 — 任何编辑都会让签名失效,acl::init() 将返回 -1001。请原样使用交付的文件。
授权权益
在购买约定的范围内,你可以继续使用所收到的版本。续费的意义在于继续获得 后续更新(新算子、性能优化)。超出购买范围的使用,适用上方的转分发条款。
接入步骤
1. 放置 License 文件
将 license.dat 复制到应用的 assets 目录:
app/src/main/assets/license.dat或运行时可访问的任何路径(如首次启动后复制到内部存储)。
2. 应用启动时初始化
在使用任何 ACL Pack 算子之前,调用 acl::init() 一次。
原生 C++(推荐):
#include <acl/acl.h>
// 设备上 license.dat 的路径 — 从应用可写存储里解析,例如:
// Android: 通过 JNI 把 Context.getFilesDir() + "/license.dat" 传进来;
// Linux: 任何进程可读的路径。
const char* licensePath = /* 绝对路径,Android 模式见 §3 */;
int ret = acl::init(licensePath);
if (ret != 0) {
// 处理 License 错误 — 见下方错误码
}参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
licensePath | const char* | license.dat 的绝对路径,进程必须有读权限 |
env (保留) | JNIEnv* | ABI 保留参数;当前实现不读取。传 nullptr 即可。 |
context (保留) | jobject | ABI 保留参数;当前实现不读取。传 nullptr 即可。 |
完整签名 int acl::init(const char* licensePath, JNIEnv* env = nullptr, jobject context = nullptr);。只传 licensePath 即可 — 后两个参数为 ABI 稳定性而保留,v1.0.3 实现不读取。
acl::init() 在进程内只执行一次完整流程。首次调用后,后续调用直接返回相同的状态码、不会重新读文件。必须在调用任何算子前返回 0,否则算子调用将返回 -1001(ACL_ERR_LICENSE_INVALID)。acl::init 与 acl::version 可安全先行调用。
3. JNI 集成(Android)
典型模式:首次启动时把 license.dat 从 APK assets 复制到内部存储,然后把绝对路径传给 native。
// Activity/Application 启动时一次性做
File licenseFile = new File(context.getFilesDir(), "license.dat");
if (!licenseFile.exists()) {
try (InputStream is = context.getAssets().open("license.dat");
OutputStream os = new FileOutputStream(licenseFile)) {
byte[] buf = new byte[4096];
int n;
while ((n = is.read(buf)) > 0) os.write(buf, 0, n);
}
}
int rc = nativeInitAcl(licenseFile.getAbsolutePath()); // JNI 内部调 acl::initnative 侧把 jstring 转成 UTF-8 C-string 后调用 acl::init 即可。完整的 JNI wrapper 示例(Java 类 + JNI extern "C" 函数)见集成指南。
4. Linux aarch64 集成
Linux aarch64 上,把 license.dat 放在二进制旁边或任何进程可读的位置,直接把绝对路径传进来即可:
#include <acl/acl.h>
#include <cstdio>
int main() {
int ret = acl::init("/opt/myapp/license.dat");
if (ret != 0) {
fprintf(stderr, "acl::init 失败: %d\n", ret);
return 1;
}
// 继续调用 ACL Pack 算子...
return 0;
}链接命令示例:
g++ -std=c++17 main.cpp \
-I/path/to/sdk/include \
/path/to/sdk/lib/linux-aarch64/libacl.a \
-lpthread -o myappLinux aarch64 交付 zip 的目录结构是 lib/linux-aarch64/libacl.a + include/acl/*.h + license.dat — 放进你的工程链接即可。
错误码
| 错误码 | 宏定义 | 含义 | 处理方式 |
|---|---|---|---|
| 0 | ACL_OK | License 有效 | 正常使用 |
| -1001 | ACL_ERR_LICENSE_INVALID | License 文件缺失、损坏、被篡改,或 acl::init() 尚未运行成功 | 检查文件路径和完整性;确认 init() 在任何算子之前被调用并返回 0 |
| -1005 | ACL_ERR_NOT_LICENSED | Tier 不匹配:acl::init 检测到 license.tier 与编译的库 tier 不符;或当前算子不在本 tier(调用点检测) | 使用匹配 tier 的 License 与 .a 配对;或升级 tier;或改用本 tier 内的算子 |
| -1006 | ACL_ERR_RESOLUTION_LIMIT | 不符合 Trial 固定尺寸(1920×1280) | 升级非 Trial 版本(无尺寸限制) |
层级(Tier)系统
ACL Pack 分为 4 个标准层级。License 必须与 .a 库的层级完全匹配。库文件名始终是 libacl.a — tier 身份编译进二进制内部、也写入 license.dat,不通过文件名区分。
| 层级 | 算子族数 | 像素类型 | 说明 |
|---|---|---|---|
| Trial | 1 算子 / 2 固定参数入口 | uint8_t | 带水印 + 固定 1920×1280 输入尺寸 |
| Starter | 57 | uint8_t | 基础算子 |
| Pro | 100 | uint8_t, uint16_t | + 双边滤波、CLAHE、模板匹配等 |
| Business | 113 | uint8_t, uint16_t, float | 所有标准算子;标准像素类型按算子支持 |
表中的算子数按文档算子族计数(同一算子的 CPP 与 NEON 实现合并为 1 行)。企业定制融合管线不计入标准层级数量。若按客户面可调用入口口径(含多图输入变体、核大小分派、独立交付的 CPP/NEON 对),Business 层共 163 个入口。
详见算子分层详情。
层级不匹配示例: 如果你持有 Starter License 但链接的是 Business tier 的 libacl.a,acl::init() 将返回 -1005(ACL_ERR_NOT_LICENSED,tier 不匹配)。请始终把交付 zip 里的 license.dat 与同一个 zip 里的 libacl.a 配对使用。
License 续费 & 补发
"续费"与"补发"是两件事。要交的材料一样,差别在我方处理方式。
两种情况都发到 zangotech@163.com 或淘宝售后:
- 你的淘宝买家 ID
- 原始淘宝订单编号
- 原有
license.dat— 以附件方式上传(优先;直接复制粘贴文本可能截断末尾的签名块)
续费(延长订阅窗口)
1 年订阅窗口快到期、希望继续获得新算子 / 性能优化 / Bug 修复时,申请续费。定价见套餐定价。
licenseId不变- 我方在台账里延长
expireDate,重新签发一份新的license.dat - 你现有的
libacl.a继续可用,只换license.dat - 1 个工作日内完成
补发(原 License 文件丢失或损坏)
license.dat 丢失、误编辑、或因任何原因需要重新拿一份 — 且仍在原购买范围内(同 tier、同 slot)。
- 分配一个新的
licenseId追加到台账,原licenseId标记为已被替代 libacl.a不变 — 同一 slot、同一份库,只换license.dat- 补发不限次,但每次留痕便于追溯
- 1 个工作日内完成
换设备、换 app、换签名证书
在购买约定的范围内,License 不绑定包名、签名证书、设备序列号。切换 debug/release 构建、重新打包、部署到同一 app 的另一台设备 — 都不需要重新申请 License。
如果需要换 tier、换平台(Android ↔ Linux)、或为不同产品线申请独立 slot,那是新订单,不是补发。不确定走哪条路时,先联系我方。
续费或补发后,把新的 license.dat 替换掉旧的即可,无需改代码。
安全说明
- License 文件只读 — ACL Pack 不会写入磁盘
- 加密签名防篡改 — 任何对
license.dat的编辑都会让签名失效 - 算子调用需要 License 已初始化成功,否则返回
-1001 - 库内字符串加密与符号混淆,抵抗逆向分析
- 可追溯性:每个签发的
licenseId与淘宝订单绑定。任何泄露或转分发都可追溯到来源。
常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 每次启动返回 -1001 | 文件路径错误,或 init() 未调用 | 打印 licensePath、验证文件存在、确认 acl::init() 在任何算子之前调用 |
| 编辑 license 文件后返回 -1001 | 任何修改都会让签名失效 | 使用交付原始的 license.dat |
| 每个算子都返回 -1001 | init() 尚未成功 | 检查 init() 返回值——必须为 0 |
| 返回 -1005 | Tier 不匹配(init 阶段)或当前 tier 不含该算子(调用点) | 检查 libacl_{tier}.a 与 License 层级是否一致;或升级 tier |
| 返回 -1006 | 不符合 Trial 固定尺寸 | 升级非 Trial(无尺寸限制;Trial 仅支持 1920×1280) |