跳转到内容

快速开始 ​

集成 ANIP SDK 到你的项目中。

部署依赖 ​

Maven CentralMaven metadata URLAndroid Min SDK

ANIP SDK 的依赖发布在 Maven Central 和我们的公共存储库中,你可以使用如下方式配置存储库。

我们推荐使用 Kotlin DSL 作为 Gradle 构建脚本语言。

在你的项目 build.gradle.kts 中配置存储库。

kotlin
repositories {
    google()
    mavenCentral()
    // (可选) 你可以添加此 URL 以使用我们的公共存储库
    // 当 Sonatype-OSS 发生故障无法发布依赖时,此存储库作为备选进行添加
    // 详情请前往:https://github.com/HighCapable/maven-repository
    // 中国大陆用户请将下方的 "raw.githubusercontent.com" 修改为 "raw.gitmirror.com"
    maven("https://raw.githubusercontent.com/HighCapable/maven-repository/main/repository/releases")
}

你可以使用如下方式将此模块添加到你的项目中。

在你的项目 gradle/libs.versions.toml 中添加依赖。

toml
[versions]
anip-sdk = "<version>"

[libraries]
anip-sdk = { module = "com.highcapable.anip:anip-sdk", version.ref = "anip-sdk" }

在你的项目 build.gradle.kts 中配置依赖。

kotlin
dependencies {
    implementation(libs.anip.sdk)
}

请将 <version> 修改为此小节顶部显示的版本。

传统方式 ​

在你的项目 build.gradle.kts 中配置依赖。

kotlin
dependencies {
    implementation("com.highcapable.anip:anip-sdk:<version>")
}

请将 <version> 修改为此文档顶部显示的版本。

功能介绍 ​

你可以 点击这里 查看 KDoc,或 点击这里 查看对应的演示项目来更好地了解 SDK 的使用方式。

创建实例 ​

Anip 是 SDK 的统一创建入口,一份实例对应维护一份缓存目录和内存状态。你可以选择在应用启动时仅创建一个实例并在整个应用中复用。

示例如下

kotlin
val anip = Anip(context)

如果你需要指定系统类型、缓存目录或远程来源,可以传入 AnipConfig。

示例如下

kotlin
val config = AnipConfig(
    // 指定系统类型,用于合并厂商系统图标
    systemVariant = SystemVariant.MIOS,
    // 显式指定缓存目录
    cacheDirectory = context.cacheDir.resolve("your-anip-resources"),
    // 指定远程资源来源
    source = RemoteSource.GitHub(
        repository = RemoteSource.GITHUB_OFFICIAL_REPO_SLUG
    )
)
val anip = Anip(context, config)

systemVariant 默认为 null,此时不会加载任何系统图标。配置为 COMMON 时只加载 common 系统图标,配置为 MIOS (HyperOS/MIUI) 或 COLOROS 时,会加载 common 与对应厂商的系统图标。

配置对象会由当前 Anip 实例持续引用。修改其中的属性后,下一次更新时会直接读取最新配置,已装载到内存中的图标不会在配置变化时自动替换。

装载与更新资源 ​

以下是 SDK 提供的装载与更新资源 API。

API行为
reload仅从缓存目录装载最新的有效资源,不请求网络,成功返回 true
fetch读取远程发布清单,资源有变化时下载并替换缓存,随后更新内存中的图标规则
getIcon / getIcons仅查询当前实例的内存状态,返回 null 或空列表

我们推荐在启动时先读取已有缓存,再检查是否有更新。

示例如下

kotlin
anip.reload()

val cachedIcons = anip.getIcons()
val result = anip.fetch()
val latestIcons = anip.getIcons()

这些装载 API 均标记为 suspend,文件与网络操作由 SDK 调度到 IO 线程。

timestamp 表示最近一次成功同步的资源提交时间,默认值为 0L,并以文本形式持久化在缓存目录的 timestamp 文件中。

更新结果 ​

fetch 返回 Anip.FetchResult,其中 status 有以下三种状态。

状态含义
SUCCESS已下载并装载新的资源
UP_TO_DATE本地资源已经是最新版本
FAILED查询、下载、校验或装载失败

Anip.FetchResult 同时提供了 isOk 和 message,isOk 在状态不为 FAILED 时返回 true,message 会描述本次更新结果或失败原因。

示例如下

kotlin
when (result.status) {
    Anip.FetchResult.Status.SUCCESS -> {
        // Do something.
    }
    Anip.FetchResult.Status.UP_TO_DATE -> {
        // Do something.
    }
    Anip.FetchResult.Status.FAILED -> showError(result.message)
}

查询图标 ​

你可以直接按包名查询单个图标,也可以按类别获取列表。

示例如下

kotlin
val icon = anip.getIcon("com.example.app")
val apps = anip.getIcons(IconCategory.APP)
val games = anip.getIcons(IconCategory.GAME)
val systemIcons = anip.getIcons(IconCategory.SYSTEM)
val allIcons = anip.getIcons()

每个 NotificationIcon 提供以下数据。

  • packageName:应用包名
  • label:按照当前系统语言解析后的应用名称
  • availableLabels:规则包含的全部本地化名称,类型为 Map<Locale, String>
  • color:图标使用的颜色,未设置时为 null
  • overlay:是否强制覆盖应用推送的所有通知图标,无论其是否为原生单色
  • contributors:贡献者的名称列表

图标位图不会随实体列表一次性解码,单独使用时,请通过 loadBitmap 显式装载,解码失败会返回 null,成功结果会进入当前 Anip 实例持有的 LRU 内存缓存。

示例如下

kotlin
val bitmap = anip.getIcon("com.example.app")?.loadBitmap()

创建内存快照 ​

如果你需要长期、集中使用整套图标时,可以创建不可变的 NotificationIconSnapshot。

示例如下

kotlin
val snapshot = anip.createSnapshot(IconCategory.ALL)
val icon = snapshot.getIcon("com.example.app")
val bitmap = snapshot.getBitmap("com.example.app")

快照会顺序装载所选类别中的图标,只保留成功解码的条目,并缓存全部位图实例,memorySizeBytes 会按实际 Bitmap 对象去重后统计占用,继承规则或多个包名使用同一资源时不会重复计算。

快照构建完成后将保持不变,后续调用 fetch 或 reload 不会修改已有快照。你可以先完整创建新快照,再替换旧引用。

释放快照引用后由 GC 回收,无需手动调用 recycle 或 close。

注意

createSnapshot 会显式承担整套图标的装载内存成本,如果你只需要偶尔获取少量图标,请直接使用 NotificationIcon.loadBitmap。

配置远程来源 ​

RemoteSource 提供以下远程来源模板。

模板行为
GitHub从 GitHub 存储库最新 Release 读取资源清单,默认使用官方仓库
GitLab从 GitLab 项目最新 Release 读取资源清单,支持自定义地址
Static在基础地址后追加 anip-release.json
Custom直接使用完整的资源清单地址

示例如下

kotlin
val github = RemoteSource.GitHub("owner/repository")
val gitLab = RemoteSource.GitLab("group/project")
val static = RemoteSource.Static("https://cdn.example.com/anip")
val custom = RemoteSource.Custom("https://resources.example.com/anip-release.json")

config.source = custom

在自定义来源时,其需要提供符合 ANIP 规范的 anip-release.json 与对应的资源 Bundle。

自定义请求地址 ​

每个模板都可以传入 RemoteSource.UrlResolver,它会在请求资源清单和 Bundle 前接收原始 URL,并返回最终请求地址。

示例如下

kotlin
val source = RemoteSource.GitHub(
    urlResolver = RemoteSource.UrlResolver { sourceUrl, _, _ ->
        "https://some.domain/$sourceUrl"
    }
)

如果清单请求的 tag 为 null,Bundle 请求则会同时提供 TAG 与附件名称,因此也可以分别映射到自建 CDN。

示例如下

kotlin
val source = RemoteSource.Custom(
    manifestUrl = "https://origin.example.com/anip-release.json",
    urlResolver = RemoteSource.UrlResolver { _, tag, assetName ->
        if (tag == null)
            "https://cdn.example.com/anip-release.json"
        else "https://cdn.example.com/releases/$tag/$assetName"
    }
)

注意

回调中应进行静态地址拼接,你不能在回调中执行网络或耗时请求。

返回空白或非法 URL 时将直接导致失败。

缓存与多进程 ​

未指定 cacheDirectory 时,SDK 使用应用缓存目录下的 anip-icon-resources。

如果你正在 Xposed 模块中使用,如需让模块进程与宿主进程共享资源,可以由调用方设置双方均可访问的同一目录,负责联网的进程执行 fetch,其他进程在收到刷新通知后执行 reload,或者在两个进程都能获得联网权限时,每个进程都持有自己的缓存目录并通知对方更新即可。

SDK 不包含任何目录权限处理功能,它只会使用标准的文件 API,你需要自行处理目录的授权与跨进程同步功能。

基于 Apache-2.0 许可发布