Skip to content

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)

淘宝店铺下单后,订单自动发货:

  1. 为你的订单分配 license.dat
  2. 通过淘宝旺旺消息向你发送 SDK zip 和 license.dat
  3. 订单与 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++(推荐):

cpp
#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 错误 — 见下方错误码
}

参数说明:

参数类型说明
licensePathconst char*license.dat 的绝对路径,进程必须有读权限
env (保留)JNIEnv*ABI 保留参数;当前实现不读取。传 nullptr 即可。
context (保留)jobjectABI 保留参数;当前实现不读取。传 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::initacl::version 可安全先行调用。

3. JNI 集成(Android)

典型模式:首次启动时把 license.dat 从 APK assets 复制到内部存储,然后把绝对路径传给 native。

java
// 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::init

native 侧把 jstring 转成 UTF-8 C-string 后调用 acl::init 即可。完整的 JNI wrapper 示例(Java 类 + JNI extern "C" 函数)见集成指南

4. Linux aarch64 集成

Linux aarch64 上,把 license.dat 放在二进制旁边或任何进程可读的位置,直接把绝对路径传进来即可:

cpp
#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 myapp

Linux aarch64 交付 zip 的目录结构是 lib/linux-aarch64/libacl.a + include/acl/*.h + license.dat — 放进你的工程链接即可。

错误码

错误码宏定义含义处理方式
0ACL_OKLicense 有效正常使用
-1001ACL_ERR_LICENSE_INVALIDLicense 文件缺失、损坏、被篡改,或 acl::init() 尚未运行成功检查文件路径和完整性;确认 init() 在任何算子之前被调用并返回 0
-1005ACL_ERR_NOT_LICENSEDTier 不匹配acl::init 检测到 license.tier 与编译的库 tier 不符;或当前算子不在本 tier(调用点检测)使用匹配 tier 的 License 与 .a 配对;或升级 tier;或改用本 tier 内的算子
-1006ACL_ERR_RESOLUTION_LIMIT不符合 Trial 固定尺寸(1920×1280)升级非 Trial 版本(无尺寸限制)

层级(Tier)系统

ACL Pack 分为 4 个标准层级。License 必须与 .a 库的层级完全匹配。库文件名始终是 libacl.a — tier 身份编译进二进制内部、也写入 license.dat,不通过文件名区分。

层级算子族数像素类型说明
Trial1 算子 / 2 固定参数入口uint8_t带水印 + 固定 1920×1280 输入尺寸
Starter57uint8_t基础算子
Pro100uint8_t, uint16_t+ 双边滤波、CLAHE、模板匹配等
Business113uint8_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 或淘宝售后:

  1. 你的淘宝买家 ID
  2. 原始淘宝订单编号
  3. 原有 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
每个算子都返回 -1001init() 尚未成功检查 init() 返回值——必须为 0
返回 -1005Tier 不匹配(init 阶段)或当前 tier 不含该算子(调用点)检查 libacl_{tier}.a 与 License 层级是否一致;或升级 tier
返回 -1006不符合 Trial 固定尺寸升级非 Trial(无尺寸限制;Trial 仅支持 1920×1280)