图表规则贡献指南

July 20, 2026 · View on GitHub

English | 简体中文

本目录存放 LibChecker 图表页面使用的声明式统计规则。规则负责描述需要检查的数据、判定匹配的条件,以及向用户显示的标题、说明和图标。

规则不能执行脚本或任意代码。APK、DEX、Manifest 和原生文件的遍历都由 LibChecker 实现。规则只能组合当前客户端已经支持的证据类型和操作符。

开始之前

编写 JSON 前,请先确认以下问题:

  1. 这个图表统计什么,它对 LibChecker 用户有什么作用?
  2. 已安装应用中的哪类证据能够证明匹配?
  3. 每个应用只会得到“匹配或不匹配”的结果,还是可能同时匹配多项能力?
  4. 是否有介绍该技术或能力的 HTTPS 一手资料?
  5. 是否有已知匹配和不匹配的 APK 可用于验证?

Schema v1 只能使用证据类型参考中列出的证据。如果规则需要 DEX 字段、资源表条目、原生符号、证书属性或任意文件内容等新数据,请先在 LibChecker 客户端中设计并实现通用的证据提供器,不要在规则中绕过这一限制。

新规则通常应先设置 "releaseChannel": "preview-only"。使用兼容的 LibChecker 版本完成预览验证后,再将规则发布到稳定渠道。

提交流程

  1. Fork 本仓库并创建独立分支。
  2. rules/ 中选择最接近的示例:
  3. rules/ 下新增一个 UTF-8 JSON 文件。使用四个空格缩进,文件名与规则 ID 的最后一段保持一致。
  4. icons/ 下添加规则引用的 SVG。
  5. 更新测试中的规则 ID、图标、Catalog 数量和稳定渠道内容,并为新规则的关键判定数据添加专门断言。
  6. 运行单元测试,并将预览 Bundle 生成到临时目录。
  7. 使用已知匹配和不匹配的应用验证预览规则。
  8. 按照目标分支确定的 Bundle 版本和最低应用版本,重新生成 cloud/v1/chart.bundlecloud/v1/manifest.json
  9. 在同一个 Pull Request 中提交源规则、图标、测试、生成的 Bundle 和 Manifest。PR 描述中应写明证据来源与人工测试结果。

从仓库根目录运行:

python3 -m unittest chart.tools.test_build_bundle
python3 chart/tools/build_bundle.py \
  --bundle-version 12 \
  --channel preview \
  --minimum-app-version-code 2731 \
  --output-dir /tmp/libchecker-chart-preview

上面的数字只是示例。选择 Bundle 版本或最低应用版本前,请先检查 chart/cloud/v1/manifest.json 和目标分支的发布状态。

目录结构

路径用途
rules/经过审核的源规则,每个统计项对应一个 JSON 文件。
icons/源规则引用的 SVG 图标。
schema/v1/chart-rule.schema.json源规则的机器可读 Schema。
schema/v1/manifest.schema.json生成后 Manifest 的机器可读 Schema。
tools/build_bundle.py校验器和确定性 Bundle 生成器。
tools/test_build_bundle.py源规则校验与 Bundle 回归测试。
cloud/v1/chart.bundleLibChecker 使用的已生成 Catalog 与图标。
cloud/v1/manifest.json已生成的版本、兼容性、大小和校验和信息。

最小完整规则

以下示例包含一个完整的单条件规则:

{
    "id": "official.example-sdk",
    "revision": 1,
    "source": "official",
    "releaseChannel": "preview-only",
    "title": {
        "translations": {
            "en": "Example SDK",
            "zh-Hans": "示例 SDK"
        }
    },
    "details": {
        "description": {
            "translations": {
                "en": "Example SDK provides a documented capability for Android apps.",
                "zh-Hans": "示例 SDK 为 Android 应用提供一项有公开文档的能力。"
            }
        },
        "referenceUrl": "https://example.com/android-sdk"
    },
    "icon": {
        "asset": "icons/example-sdk.svg",
        "renderMode": "monochrome",
        "tintRole": "on_surface"
    },
    "calculation": {
        "kind": "predicate",
        "predicate": {
            "evidence": "native_library",
            "operator": "contains",
            "value": {
                "string": "libexample.so"
            },
            "matchedTitle": {
                "translations": {
                    "en": "Example SDK apps",
                    "zh-Hans": "示例 SDK 应用"
                }
            },
            "unmatchedTitle": {
                "translations": {
                    "en": "Other apps",
                    "zh-Hans": "其他应用"
                }
            }
        }
    },
    "fingerprint": "artifact"
}

顶层参数

源规则 Schema 不允许出现未定义的字段。官方在线规则可以使用以下顶层参数。

参数是否必填类型或全部可选值默认值含义
id符合 official.<name> 格式的字符串统计规则的永久标识。
revision不小于 1 的整数当前规则定义的修订号。
sourceofficial本仓库在线规则的来源类型。
title多语言文本对象LibChecker 显示的图表标题。
details对象应用内说明与一手资料链接。
icon对象Bundle 内的 SVG 及其渲染方式。
calculationpredicatefacets应用的分类方式。
releaseChannelstablepreview-onlystable决定规则进入哪些渠道的 Bundle。
availabilityalwaysalways可用性限制。Schema v1 在线规则只支持始终可用。
requiresFeatureInitializationtruefalsefalse是否在特征初始化完成前隐藏图表。
controls只能是空数组 [][]Schema v1 不支持在线图表控件。
dashboardnonenoneSchema v1 不支持在线 Dashboard 集成。
fingerprintstandardfeaturesartifactstandard用于判断图表缓存是否失效的应用数据指纹。

JSON Schema 中的 default 用于说明客户端默认行为。Bundle 生成器不会把缺少的可选字段自动写入 Catalog。

id

ID 必须符合:

^official\.[a-z0-9]+(?:[.-][a-z0-9]+)*$
示例是否有效原因
official.flutter使用 official. 前缀和小写名称。
official.android-api-level可以使用小写字母、数字、连字符和分段点号。
official.vendor.capability可以包含多个点号分段。
flutter缺少 official. 前缀。
official.Flutter包含大写字母。
official_target_sdk格式不符合要求。

ID 应具体且不依赖容易变化的展示文案。规则发布后,不得将原 ID 用于另一项统计。源文件名应与 ID 最后一段一致,例如 official.flutter 使用 flutter.json

revision

场景修订号处理
新规则1 开始。
修改已发布规则的判定逻辑1
修改标题、说明、图标、计算类型或其他展示元数据1
只修改仓库文档,不改变规则不需要修改。

revision 属于单条规则,与生成 Bundle 的 bundleVersion 相互独立。

source

本仓库中的每条规则都必须使用:

"source": "official"

其他值会被生成器拒绝。

多语言文本

titledetails.description、Predicate 分组标题和 Facet 标题使用同一种结构。可选的 Facet 短标题也使用这一结构:

{
    "translations": {
        "en": "English text",
        "zh-Hans": "简体中文文本"
    }
}

多语言文本参数

参数类型是否必填全部可选值与限制含义
translations对象2 至 16 个语言项,必须包含 enzh-Hans语言标签到显示文本的映射。
translations.<locale>字符串每个已声明语言都必填不能为空;图表和分组标题最多 80 个字符,Facet 标题和短标题最多 40 个字符,说明最多 1,500 个字符指定语言的本地化文本。
语言标签是否允许含义
en必填英文,也是运行时回退语言。
zh-Hans必填简体中文。
zhzh-CN禁止必须改用 zh-Hans
其他符合 Schema 的标签可选可以添加 pt-BRes-419 等翻译,总数不能超过 16。

不同语言应表达相同含义,不能只在某一种语言中增加事实或宣传性断言。图表标题和分组标题应尽量简短。matchedTitleunmatchedTitle 分别命名匹配和不匹配的两组结果,例如“Flutter 应用”和“其他应用”。

详情与参考链接

details 为必填对象:

"details": {
    "description": {
        "translations": {
            "en": "A neutral introduction to the technology.",
            "zh-Hans": "对该技术的中性介绍。"
        }
    },
    "referenceUrl": "https://project.example/documentation"
}

详情参数

参数类型是否必填全部可选值与限制含义
details.description多语言文本必须包含 enzh-Hans,每种语言 1 至 1,500 个字符对技术或能力的中性介绍。
details.referenceUrl字符串HTTPS URL,必须有有效 Host,不得包含账号、密码或空白,最多 512 个字符详情对话框中打开的一手资料。

说明只介绍技术或能力本身,不要声称当前选中的应用已经匹配。LibChecker 会在运行时追加实际分析结果。Facet 规则还会列出匹配到的 Facet 标题。

参考链接应指向项目官网、标准组织、供应商或平台的一手文档。不要使用追踪链接、短链接、推广链接、搜索结果或未经审核的第三方摘要。

图标

每条在线规则都要引用仓库中的一个 SVG:

"icon": {
    "asset": "icons/example-sdk.svg",
    "renderMode": "monochrome",
    "tintRole": "on_surface"
}

图标参数

参数类型是否必填全部可选值默认值含义
icon.asset字符串icons/<safe-name>.svg会被打包进 Bundle 的仓库相对路径。
icon.renderMode字符串monochromeoriginalmonochrome决定 LibChecker 是否应用主题着色。
icon.tintRole字符串on_surfaceon_surface_variantprimarysecondarytertiaryon_surface单色图标使用的主题颜色。
renderMode渲染行为tintRole 是否生效适用场景
monochromeLibChecker 使用主题颜色统一着色。应随浅色或深色主题变化的单色轮廓。
original保留 SVG 自带颜色。品牌颜色具有识别意义的图标。

SVG 要求

项目限制
viewBox必须是 0 0 1024 1024
视觉边界图形应大致位于居中的 800 x 800 区域,保持不同图标的视觉尺寸一致。
文件大小小于 64 KiB。
编码有效 UTF-8。
外部内容禁止脚本、样式、文本节点、链接图片、实体、外部引用和 url(...)

校验器会拒绝 <!doctype<!entity<?xml-stylesheet<script<foreignObject<image<style<texthref=xlink:url(。请将文字转换为路径,并直接写入需要保留的填充颜色。

选择计算类型

应用只能落入匹配或不匹配两组时使用 predicate。一个应用可能同时匹配多项能力,并且界面需要显示每项能力的 Chip 时使用 facets

统计问题应使用的类型
应用是否以 SDK 35 或更高版本为目标?predicate
应用是否包含 libflutter.sopredicate
应用实现了哪些金标联盟开放能力?facets

calculation 参数

参数类型是否必填全部可选值含义
calculation.kind字符串predicatefacets决定必须同时提供哪一种计算对象。
calculation.predicate对象kindpredicate 时必填Predicate 计算根据一个条件生成匹配组和不匹配组。
calculation.facets对象kindfacets 时必填Facet 计算除了匹配和不匹配分组,还会生成每个应用的能力 Chip。

只能提供 kind 选中的对象。在线规则不能使用客户端内置规则所使用的 native 计算类型。

Facet 用于可以重叠的能力,不适用于互斥分桶或数值分布。Schema v1 暂时没有支持这些场景的在线计算类型。

Predicate 计算

Predicate 必须包含 matchedTitleunmatchedTitle 和一个完整条件。

predicate 参数

参数类型是否必填全部可选值与限制含义
predicate.matchedTitle多语言文本每种语言 1 至 80 个字符条件结果为真的应用分组名称。
predicate.unmatchedTitle多语言文本每种语言 1 至 80 个字符条件结果为假的应用分组名称。
predicate.evidence字符串直接叶子写法必填target_sdknative_libraryarchive_entrydex_classmanifest_receiver_actionmanifest_attribute叶子条件使用的证据。
predicate.operator字符串直接叶子写法必填取决于 evidence应用于证据的比较操作。
predicate.value对象直接叶子写法必填只能包含一种与 evidence 兼容的值比较所需的目标值。
predicate.conditionCondition 对象递归写法必填一个证据叶子、allanynot代替三个直接叶子字段的递归条件。

单个证据叶子可以直接放在 predicate 中:

"calculation": {
    "kind": "predicate",
    "predicate": {
        "evidence": "target_sdk",
        "operator": "greater_than_or_equal",
        "value": {
            "integer": 35
        },
        "matchedTitle": {
            "translations": {
                "en": "Target SDK 35 or newer",
                "zh-Hans": "Target SDK 35 及以上"
            }
        },
        "unmatchedTitle": {
            "translations": {
                "en": "Target SDK 34 or older",
                "zh-Hans": "Target SDK 34 及以下"
            }
        }
    }
}

需要组合逻辑时,用一个 condition 取代直接叶子的三个字段:

"predicate": {
    "condition": {
        "any": [
            {
                "evidence": "native_library",
                "operator": "contains",
                "value": {
                    "string": "libexample.so"
                }
            },
            {
                "evidence": "manifest_receiver_action",
                "operator": "contains_any",
                "value": {
                    "strings": [
                        "com.example.ACTION_READY"
                    ]
                }
            }
        ]
    },
    "matchedTitle": {
        "translations": {
            "en": "Example apps",
            "zh-Hans": "示例应用"
        }
    },
    "unmatchedTitle": {
        "translations": {
            "en": "Other apps",
            "zh-Hans": "其他应用"
        }
    }
}

直接叶子字段与 condition 不能同时出现,三个直接叶子字段也不能只提供一部分。

Facet 计算

Facet 计算包含 1 至 8 个有顺序的条目。

facets 参数

参数类型是否必填全部可选值与限制含义
facets.matchedTitle多语言文本每种语言 1 至 80 个字符至少匹配一个 Facet 的应用分组名称。
facets.unmatchedTitle多语言文本每种语言 1 至 80 个字符没有匹配任何 Facet 的应用分组名称。
facets.items数组1 至 8 个 Facet 对象按界面展示顺序排列的能力定义。
items[].id字符串符合规定格式的小写局部 ID,在规则内唯一Facet 的稳定内部标识。
items[].title多语言文本每种语言 1 至 40 个字符在详细结果和图表 Chip 中使用的完整 Facet 名称。
items[].shortTitle多语言文本每种语言 1 至 40 个字符匹配项摘要使用的紧凑名称;省略时回退到 title
items[].conditionCondition 对象一个证据叶子、allanynot判断当前 Facet 是否匹配。
"calculation": {
    "kind": "facets",
    "facets": {
        "matchedTitle": {
            "translations": {
                "en": "Example capability apps",
                "zh-Hans": "示例能力应用"
            }
        },
        "unmatchedTitle": {
            "translations": {
                "en": "Other apps",
                "zh-Hans": "其他应用"
            }
        },
        "items": [
            {
                "id": "service-kit",
                "title": {
                    "translations": {
                        "en": "Service Kit",
                        "zh-Hans": "服务套件"
                    }
                },
                "shortTitle": {
                    "translations": {
                        "en": "Kit",
                        "zh-Hans": "套件"
                    }
                },
                "condition": {
                    "evidence": "native_library",
                    "operator": "contains",
                    "value": {
                        "string": "libexample_service.so"
                    }
                }
            }
        ]
    }
}

Facet ID 必须符合 ^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$。ID 在当前规则中必须唯一,发布后应保持稳定。title 必填;shortTitle 可选,两者每种语言都不能超过 40 个字符。

应用至少匹配一个 Facet 时会进入图表的匹配组。所有命中的 Facet 标题都会按照 items 中的声明顺序显示为 Chip;匹配项摘要优先使用 shortTitle,省略时回退到 title。不要再用一个根 any 重复 Facet 条件,否则会产生两份判定来源。

Condition 条件

Condition 对象只能是一个带类型的证据叶子,或者一个逻辑操作。未定义字段会被拒绝。

Condition 对象参数

参数类型是否必填全部可选值与限制含义
evidence字符串叶子条件必填target_sdknative_libraryarchive_entrydex_classmanifest_receiver_actionmanifest_attribute选择要检查的应用数据。
operator字符串叶子条件必填equalgreater_than_or_equalless_than_or_equalcontainscontains_any,具体兼容性取决于 evidence选择比较方式。
value对象叶子条件必填只能包含 integerstringstringsdexClassesmanifestAttribute 中的一个提供比较目标。
allCondition 数组all 节点必填1 至 16 个子条件所有子条件都为真时匹配。
anyCondition 数组any 节点必填1 至 16 个子条件至少一个子条件为真时匹配。
notCondition 对象not 节点必填一个子条件对子条件结果取反。

一个对象只能定义一种操作。证据叶子必须同时包含 evidenceoperatorvalue。逻辑节点只能包含 allanynot 中的一个。

value 对象参数

参数类型对应证据全部可选值与限制含义
integer整数target_sdk任意 JSON 整数数值比较目标。
string字符串native_library1 至 160 个安全文件名字符精确的原生库文件名。
strings字符串数组archive_entrymanifest_receiver_action1 至 16 项,每项 1 至 160 个符合对应证据限制的安全字符精确 APK 条目或 Receiver Action 列表,任意一项可以匹配。
dexClassesDEX Class Query 数组dex_class1 至 16 个查询类查询列表,任意一个查询可以匹配。
manifestAttributeManifest 属性查询manifest_attribute一个 application 元素、一个安全的 android: 属性名和一个布尔值精确的 Application Manifest 布尔属性及期望值。

一个 value 对象只能包含上述参数中的一个。

逻辑操作符

操作符匹配语义
all1 至 16 个 Condition所有子条件匹配时为真。
any1 至 16 个 Condition至少一个子条件匹配时为真。
not一个 Condition将子条件结果取反。
{
    "all": [
        {
            "evidence": "target_sdk",
            "operator": "greater_than_or_equal",
            "value": {
                "integer": 35
            }
        },
        {
            "not": {
                "evidence": "native_library",
                "operator": "contains",
                "value": {
                    "string": "liblegacy.so"
                }
            }
        }
    ]
}

条件复杂度限制

限制项最大值计算方式
嵌套深度8根 Condition 的深度为 1。
Condition 节点总数64Predicate 单独计算;Facet 规则的所有 Facet 共用 64 个节点。
单个 allany 的子条件数16每个数组至少包含 1 项。

应使用有可靠依据的最窄条件。条件更长不等于误报率更低。

证据类型参考

evidence唯一兼容的 operatorvalue 结构匹配语义
target_sdkequalgreater_than_or_equalless_than_or_equal{ "integer": <整数> }比较应用的 Target SDK。
native_librarycontains{ "string": "<库文件名>" }精确匹配原生库文件名。
archive_entrycontains_any{ "strings": ["<条目名称>", ...] }Base APK 或 Split APK 中存在任意一个精确条目时为真。
dex_classcontains_any{ "dexClasses": [<查询>, ...] }任意查询匹配任意一个 DEX 类时为真。
manifest_receiver_actioncontains_any{ "strings": ["<action>", ...] }Manifest Receiver 声明任意一个 Action 时为真。
manifest_attributeequal{ "manifestAttribute": { "element": "application", "name": "android:<属性名>", "boolean": <布尔值> } }匹配显式声明的 Application Manifest 布尔属性。

target_sdk

参数
evidencetarget_sdk
operatorequalgreater_than_or_equalless_than_or_equal
value只包含一个 integer
推荐 fingerprintstandard,也可以省略并使用默认值

整数会与已安装应用记录的 Target API 比较。Schema 没有限制 API Level 的范围,但提交的值应当对应真实的 Android API Level。

{
    "evidence": "target_sdk",
    "operator": "less_than_or_equal",
    "value": {
        "integer": 34
    }
}

native_library

参数
evidencenative_library
operator只能是 contains
value.string1 至 160 个字符,只允许 ASCII 字母、数字、._+-
推荐 fingerprintartifact

值是精确的 .so 文件名,不是路径、正则表达式或子串。LibChecker 会检查已解压的原生库和 APK 内打包的原生库。

{
    "evidence": "native_library",
    "operator": "contains",
    "value": {
        "string": "libflutter.so"
    }
}

archive_entry

参数
evidencearchive_entry
operator只能是 contains_any
value.strings1 至 16 个精确 ZIP 条目名称,每项 1 至 160 个字符
推荐 fingerprintartifact

该证据检查 Base APK 和 Split APK 中的精确 ZIP 条目名称,不读取文件内容,也不支持前缀、Glob 或正则表达式。

{
    "evidence": "archive_entry",
    "operator": "contains_any",
    "value": {
        "strings": [
            "META-INF/example.properties"
        ]
    }
}

条目名称只允许 ASCII 字母、数字、._+-/,不能以 / 结尾,也不能包含 ... 路径段。

manifest_receiver_action

参数
evidencemanifest_receiver_action
operator只能是 contains_any
value.strings1 至 16 项,每项 1 至 160 个字符,只允许 ASCII 字母、数字、_.-
推荐 fingerprintartifact

该证据读取 Base APK 和 Split APK 中由 Manifest 声明的 Broadcast Receiver Action。列表中至少一个 Action 存在时即为匹配。

{
    "evidence": "manifest_receiver_action",
    "operator": "contains_any",
    "value": {
        "strings": [
            "com.example.ACTION_TRIM",
            "com.example.ACTION_KILL"
        ]
    }
}

manifest_attribute

该证据读取 APK 的 application Manifest 元素中显式声明的布尔属性。属性不存在时不会匹配,即使 Android 平台在运行时提供了相同的默认值。

{
    "evidence": "manifest_attribute",
    "operator": "equal",
    "value": {
        "manifestAttribute": {
            "element": "application",
            "name": "android:enableOnBackInvokedCallback",
            "boolean": true
        }
    }
}

属性名必须使用 android: 命名空间,后接一个 ASCII 字母以及最多 79 个 ASCII 字母、数字或下划线。Schema v1 只支持 application 元素和布尔值;引用资源的布尔属性会在资源解析后参与比较。推荐使用 fingerprint: artifact

dex_class

参数
evidencedex_class
operator只能是 contains_any
value.dexClasses1 至 16 个 DEX Class Query
推荐 fingerprintartifact

dexClasses 数组使用 OR 语义。Base APK 或 Split APK 中的任意类满足任意一个 Query 时,整个证据即为匹配。

{
    "evidence": "dex_class",
    "operator": "contains_any",
    "value": {
        "dexClasses": [
            {
                "name": {
                    "operator": "starts_with",
                    "value": "Lcom/example/sdk/"
                },
                "stringConstants": [
                    "com.example.ACTION_READY"
                ],
                "methodReferences": [
                    {
                        "definingClass": "Landroid/content/IntentFilter;",
                        "name": "addAction",
                        "parameterTypes": [
                            "Ljava/lang/String;"
                        ]
                    }
                ]
            }
        ]
    }
}

DEX Class Query 参数

参数类型是否必填全部可选值与限制匹配语义
name对象包含 operatorvalue限制类描述符。
stringConstants字符串数组1 至 16 项,每项 1 至 160 个无控制字符的字符串当前类引用任意一个字符串时满足该项。
methodReferencesMethod Reference 数组1 至 16 项当前类引用任意一个方法时满足该项。

每个 Query 至少要有一个参数。一个 Query 同时出现多个参数时,所有参数类别必须由同一个 DEX 类满足:

  • name 时,类名必须匹配。
  • stringConstants 时,该类至少引用列表中的一个字符串。
  • methodReferences 时,该类至少引用列表中的一个方法。

例如,同时包含 stringConstantsmethodReferences 的 Query,要求同一个类至少引用一个目标字符串和一个目标方法,但两条引用指令不要求位于同一个方法体中。证据可能出现在不同类时,应拆成多个 dexClasses 数组项。

类名参数

DEX 类名使用描述符,不使用 Java 或 Kotlin 的点分名称。

name 参数类型是否必填全部可选值与限制含义
name.operator字符串equalstarts_with精确匹配类描述符,或匹配描述符前缀。
name.value字符串L 开头的 DEX 类描述符模式;equal 必须以 ; 结尾需要匹配的完整描述符或前缀。
目标operator示例
匹配一个类equalLcom/example/sdk/EntryPoint;
匹配一个包或嵌套前缀starts_withLcom/example/sdk/

类名可以使用字母、数字、下划线、美元符号、斜杠和连字符。starts_with 可以省略分号,匹配包前缀时通常以斜杠结尾。

字符串常量参数

参数类型数量单项长度其他限制
stringConstants字符串数组1 至 161 至 160 个字符禁止控制字符;按 DEX 中的完整字符串引用匹配,不支持正则或子串。

方法引用参数

{
    "definingClass": "Landroid/content/IntentFilter;",
    "name": "<init>",
    "parameterTypes": [
        "Ljava/lang/String;"
    ]
}
参数类型是否必填全部可选值与限制含义
definingClass字符串L 开头、以 ; 结尾的完整 DEX 类描述符定义目标方法的类。
name字符串1 至 80 个允许字符,支持 <init><clinit>方法名。
parameterTypes字符串数组最多 16 项,每项为合法参数类型描述符要求精确匹配的参数列表。

省略 parameterTypes 会匹配同一类中同名方法的任意重载。提供该字段后,参数列表必须完全相同。空数组只匹配无参数方法。

类型DEX 描述符
booleanZ
byteB
shortS
charC
intI
longJ
floatF
doubleD
对象Ljava/lang/String; 形式的完整描述符
数组每一维在元素描述符前增加一个 [,例如 [I[[Ljava/lang/String;

可选元数据

releaseChannel

是否进入 Preview Bundle是否进入 Stable Bundle含义
stable已完成兼容性和检测结果验证的规则,也是默认值。
preview-only仍在试验或等待稳定验证的规则。

生成器会从 Catalog 中删除 releaseChannel。它只控制仓库发布渠道,不是运行时图表元数据。

availability

含义
always图表始终可用,也是唯一允许值和默认值。

未来 Schema 增加在线可用性限制前,应省略该字段。

requiresFeatureInitialization

含义
false不等待特征初始化,默认值。
true特征初始化完成前隐藏图表。

当前在线证据不依赖特征数据,新规则通常应省略该字段或使用 false

controls

含义
省略推荐写法,Schema v1 没有在线图表控件。
[]合法,但不会增加任何行为。
非空数组非法,校验器会拒绝。

dashboard

含义
none不提供 Dashboard 集成,也是唯一允许值和默认值。

fingerprint

Fingerprint 决定已安装应用数据变化后,LibChecker 何时丢弃图表缓存。它不会开放新的证据读取能力。

默认值适用规则含义
standard只依赖 target_sdk 等标准元数据使用不包含特征数据的完整应用信息指纹。
artifact检查原生库、APK 条目、DEX 或 Manifest 内容使用包含应用版本和更新时间等制品变化信息的指纹。
features依赖 LibChecker 已初始化特征数据的规则将特征数据纳入缓存指纹,Schema v1 当前在线证据不需要此值。

应选择能够覆盖规则中所有证据叶子的值。Target SDK 与 DEX 组合的规则应使用 artifact

校验与测试

运行:

python3 -m unittest chart.tools.test_build_bundle

JSON Schema 定义完整的对象结构与字段限制。Python 生成器还会进行语义校验,包括证据、操作符和值的兼容性,URL 安全性,图标路径和 SVG 安全性,重复规则 ID,重复 Facet ID,以及复杂度限制。

新增规则时,请更新 chart/tools/test_build_bundle.py 中的现有断言:

测试位置需要修改的内容
test_source_rules_are_valid按排序后的顺序添加新规则 ID。
test_bundle_is_deterministic_and_contains_only_expected_files按 ZIP 中的排序添加图标路径,并修改 Catalog 数量。
test_stable_bundle_excludes_preview_only_rules根据规则渠道修改稳定 Bundle 的规则 ID 列表。
新的专门测试固定关键判定值、条件顺序、图标渲染模式、详情 URL 或其他不能被误改的属性。
新 Schema 能力或校验分支添加对应的非法输入测试。

不要为了让新规则通过测试而降低限制或删除回归断言。

生成 Bundle

本地预览时,先输出到临时目录,避免修改 Git 已跟踪的生成文件:

python3 chart/tools/build_bundle.py \
  --bundle-version 12 \
  --channel preview \
  --minimum-app-version-code 2731 \
  --output-dir /tmp/libchecker-chart-preview

生成目标分支最终制品时,省略 --output-dir,文件会写入 chart/cloud/v1/

python3 chart/tools/build_bundle.py \
  --bundle-version 12 \
  --channel preview \
  --minimum-app-version-code 2731

命令行参数

参数是否必填类型与全部可选值默认值含义
--bundle-version大于 0 的整数目标分支单调递增的发布版本。
--channelpreviewstablepreviewPreview 包含全部规则;Stable 排除 preview-only
--minimum-app-version-code不小于 0 的整数0能安全加载 Bundle 中所有规则的首个 LibChecker Version Code。
--output-dir文件系统路径chart/cloud/v1/Bundle 与 Manifest 的输出目录。

如果规则只使用已发布客户端支持的证据和计算能力,可以沿用目标分支当前兼容的最低应用版本。规则依赖新的客户端能力时,应先协调客户端修改,并填写首个兼容版本的准确 Version Code。不要猜测该值。只有所有仍受支持的客户端都兼容时,才可以发布 0

生成结果

字段或限制含义
规则排序id 排序保证 Catalog 稳定。
图标排序按路径排序保证 ZIP 条目稳定。
最大规则数64超出后生成失败。
单个 SVG 最大大小64 KiB超出后校验失败。
Bundle 最大大小2 MiB超出后生成失败。

manifest.json 包含以下参数:

参数类型与限制含义
schemaVersion固定为 1Catalog 与 Manifest 使用的 Schema 版本。
bundleVersion不小于 1 的整数当前发布版本。
bundleSha25664 位小写十六进制字符串chart.bundle 的 SHA-256。
bundleSize1 至 2,097,152 字节chart.bundle 的实际字节数。
minimumAppVersionCode不小于 0 的整数最低兼容 LibChecker Version Code。

chart.bundlemanifest.json 必须一起提交。一次生成得到的校验和与大小不能搭配另一次生成得到的 Bundle。

人工验证

自动校验只能证明规则格式正确,不能证明规则能够准确识别目标应用。

请求稳定发布前,请完成以下检查:

  1. 安装能够读取预览分支的兼容 LibChecker 版本。
  2. 至少检查一个已知匹配应用和一个已知不匹配应用。
  3. 对于 Facet 规则,分别验证每个 Facet,并确认同时匹配多项能力的应用会按照规则顺序显示全部 Chip。
  4. 检查图表标题、分组标题、说明、参考链接、图标大小、图标颜色、浅色主题和深色主题。
  5. 在 PR 描述中记录用于测试的应用版本或样本 APK。
  6. 使用 --channel stable 重新生成并检查 Catalog,确保所有 preview-only 规则都不在其中。

Pull Request 检查表

  • 规则只解决一项定义清楚的统计需求。
  • ID 和文件名稳定并符合命名规范。
  • 新规则从 Revision 1 开始,修改已发布规则时已增加 Revision。
  • 所有文本都有含义一致的 enzh-Hans 翻译。
  • 说明保持中性,HTTPS 链接指向一手资料。
  • 计算只使用受支持的证据和兼容操作符。
  • DEX Query 使用描述符,并保持同类匹配语义。
  • SVG 满足安全限制与 viewBox 要求。
  • 发布渠道和 Fingerprint 与规则成熟度、证据类型一致。
  • 专门测试覆盖关键判定数据和渠道行为。
  • 单元测试通过。
  • 已使用兼容的 LibChecker 检查匹配和不匹配应用。
  • 生成的 Bundle 和 Manifest 已重新生成并一起提交。

错误发布后的恢复

不要重新使用旧的 Bundle Version。恢复上一个已知正常的源规则和生成内容,然后用更高的 bundleVersion 重新发布。下载、校验和、Schema 或最低版本检查失败时,兼容的 LibChecker 客户端会保留已缓存的 Bundle。