English | 简体中文
本工具是一个基于 Shell 脚本的自动化解决方案,旨在分析和修复 iOS App 的隐私清单,确保 App 符合 App Store 的要求。它利用 App Store Privacy Manifest Analyzer 对 App 及其依赖项进行 API 使用分析,并生成或修复PrivacyInfo.xcprivacy
文件。
- 非侵入式集成:无需修改源码或调整项目结构。
- 极速安装与卸载:一行命令即可快速完成工具的安装或卸载。
- 自动分析与修复:项目构建时自动分析 API 使用情况并修复隐私清单问题。
- 灵活定制模板:支持自定义 App 和 Framework 的隐私清单模板,满足多种使用场景。
- 隐私访问报告:自动生成报告用于查看 App 和 SDK 的
NSPrivacyAccessedAPITypes
声明情况。 - 版本轻松升级:提供升级脚本快速更新至最新版本。
- 下载最新发布版本。
- 解压下载的文件:
- 解压后的目录通常为
app_privacy_manifest_fixer-xxx
(其中xxx
是版本号)。 - 建议重命名为
app_privacy_manifest_fixer
,或在后续路径中使用完整目录名。 - 建议将该目录移动至 iOS 项目中,以避免因路径问题在不同设备上运行时出现错误,同时便于为每个项目单独自定义隐私清单模板。
- 解压后的目录通常为
-
切换到工具所在目录:
cd /path/to/app_privacy_manifest_fixer
-
运行以下安装脚本:
sh install.sh <project_path>
- 如果是 Flutter 项目,
project_path
应为 Flutter 项目中的ios
目录路径。 - 重复运行安装命令时,工具会先移除现有安装(如果有)。若需修改命令行选项,只需重新运行安装命令,无需先卸载。
- 如果是 Flutter 项目,
如果不使用安装脚本,可以手动添加Fix Privacy Manifest
任务到 Xcode 的 Build Phases 完成安装。安装步骤如下:
-
用 Xcode 打开你的 iOS 项目,进入 TARGETS 选项卡,选择你的 App 目标。
-
进入 Build Phases,点击 + 按钮,选择 New Run Script Phase。
-
将新建的 Run Script 重命名为
Fix Privacy Manifest
。 -
在 Shell 脚本框中添加以下代码:
# 使用相对路径(推荐):如果`app_privacy_manifest_fixer`在项目目录内 "$PROJECT_DIR/path/to/app_privacy_manifest_fixer/fixer.sh" # 使用绝对路径:如果`app_privacy_manifest_fixer`不在项目目录内 # "/absolute/path/to/app_privacy_manifest_fixer/fixer.sh"
请根据实际情况修改
path/to
或absolute/path/to
,并确保路径正确。同时,删除或注释掉不适用的行。
将该脚本移动到所有其他 Build Phases 之后,确保隐私清单在所有资源拷贝和编译任务完成后再进行修复。
下面是自动/手动安装成功后的 Xcode Build Phases 配置截图(未启用任何命令行选项):
安装后,工具将在每次构建项目时自动运行,构建完成后得到的 App 包已经是修复后的结果。
如果启用--install-builds-only
命令行选项安装,工具将仅在安装构建时运行。
下面是项目构建时工具输出的日志截图(默认会存储到app_privacy_manifest_fixer/Build
目录,除非启用-s
命令行选项):
-
强制覆盖现有隐私清单(不推荐):
sh install.sh <project_path> -f
启用
-f
选项后,工具会根据 API 使用分析结果和隐私清单模板生成新的隐私清单,并强制覆盖现有隐私清单。默认情况下(未启用-f
),工具仅修复缺失的隐私清单。 -
静默模式:
sh install.sh <project_path> -s
启用
-s
选项后,工具将禁用修复时的输出,不再复制构建生成的*.app
、自动生成隐私访问报告或输出修复日志。默认情况下(未启用-s
),这些输出存储在app_privacy_manifest_fixer/Build
目录。 -
仅在安装构建时运行(推荐):
sh install.sh <project_path> --install-builds-only
启用
--install-builds-only
选项后,工具仅在执行安装构建(如 Archive 操作)时运行,以优化日常开发时的构建性能。如果你是手动安装的,该命令行选项无效,需要手动勾选 For install builds only 选项。注意:如果 iOS 项目在开发环境构建(生成的 App 包含
*.debug.dylib
文件),工具的 API 使用分析结果可能不准确。
要更新至最新版本,请运行以下命令:
sh upgrade.sh
使用以下命令快速卸载工具:
sh uninstall.sh <project_path>
隐私清单模板存储在Templates
目录,其中根目录已经包含默认模板。
如何为 App 或 SDK 自定义隐私清单?只需使用自定义模板!
模板分为以下几类:
- AppTemplate.xcprivacy:App 的隐私清单模板。
- FrameworkTemplate.xcprivacy:通用的 Framework 隐私清单模板。
- FrameworkName.xcprivacy:特定的 Framework 隐私清单模板,仅在
Templates/UserTemplates
目录有效。
对于 App,隐私清单模板的优先级如下:
Templates/UserTemplates/AppTemplate.xcprivacy
>Templates/AppTemplate.xcprivacy
对于特定的 Framework,隐私清单模板的优先级如下:
Templates/UserTemplates/FrameworkName.xcprivacy
>Templates/UserTemplates/FrameworkTemplate.xcprivacy
>Templates/FrameworkTemplate.xcprivacy
默认模板位于Templates
根目录,目前包括以下模板:
Templates/AppTemplate.xcprivacy
Templates/FrameworkTemplate.xcprivacy
这些模板将根据 API 使用分析结果进行修改,特别是NSPrivacyAccessedAPIType
条目将被调整,以生成新的隐私清单用于修复,确保符合 App Store 要求。
如果需要调整隐私清单模板,例如以下场景,请避免直接修改默认模板,而是使用自定义模板。如果存在相同名称的自定义模板,它将优先于默认模板用于修复。
- 由于 API 使用分析结果不准确,生成了不合规的隐私清单。
- 需要修改模板中声明的理由。
- 需要声明收集的数据。
AppTemplate.xcprivacy
中隐私访问 API 类别及其对应声明的理由如下:
NSPrivacyAccessedAPIType | NSPrivacyAccessedAPITypeReasons |
---|---|
NSPrivacyAccessedAPICategoryFileTimestamp | C617.1: Inside app or group container |
NSPrivacyAccessedAPICategorySystemBootTime | 35F9.1: Measure time on-device |
NSPrivacyAccessedAPICategoryDiskSpace | E174.1: Write or delete file on-device |
NSPrivacyAccessedAPICategoryActiveKeyboards | 54BD.1: Customize UI on-device |
NSPrivacyAccessedAPICategoryUserDefaults | CA92.1: Access info from same app |
FrameworkTemplate.xcprivacy
中隐私访问 API 类别及其对应声明的理由如下:
NSPrivacyAccessedAPIType | NSPrivacyAccessedAPITypeReasons |
---|---|
NSPrivacyAccessedAPICategoryFileTimestamp | 0A2A.1: 3rd-party SDK wrapper on-device |
NSPrivacyAccessedAPICategorySystemBootTime | 35F9.1: Measure time on-device |
NSPrivacyAccessedAPICategoryDiskSpace | E174.1: Write or delete file on-device |
NSPrivacyAccessedAPICategoryActiveKeyboards | 54BD.1: Customize UI on-device |
NSPrivacyAccessedAPICategoryUserDefaults | C56D.1: 3rd-party SDK wrapper on-device |
要创建自定义模板,请将其放在Templates/UserTemplates
目录,结构如下:
Templates/UserTemplates/AppTemplate.xcprivacy
Templates/UserTemplates/FrameworkTemplate.xcprivacy
Templates/UserTemplates/FrameworkName.xcprivacy
在这些模板中,只有FrameworkTemplate.xcprivacy
会根据 API 使用分析结果对NSPrivacyAccessedAPIType
条目进行调整,以生成新的隐私清单用于 Framework 修复。其他模板保持不变,将直接用于修复。
重要说明:
- 特定的 Framework 模板必须遵循命名规范
FrameworkName.xcprivacy
,其中FrameworkName
需与 Framework 的名称匹配。例如Flutter.framework
的模板应命名为Flutter.xcprivacy
。 - SDK 的名称可能与 Framework 的名称不完全一致。要确定正确的 Framework 名称,请在构建项目后检查 App 包中的
Frameworks
目录。
默认情况下,工具会自动在每次构建时为原始 App 和修复后的 App 生成隐私访问报告,并存储到app_privacy_manifest_fixer/Build
目录。
如果需要手动为特定 App 生成隐私访问报告,请运行以下命令:
sh Report/report.sh <app_path> <report_output_path>
# <app_path>: App路径(例如:/path/to/App.app)
# <report_output_path>: 报告文件保存路径(例如:/path/to/report.html)
注意:工具生成的报告目前仅包含隐私访问部分(NSPrivacyAccessedAPITypes
),如果想看数据收集部分(NSPrivacyCollectedDataTypes
)请使用 Xcode 生成PrivacyReport
。
原始 App 报告(report-original.html) | 修复后 App 报告(report.html) |
---|---|
- 如果最新版本的 SDK 支持隐私清单,请尽可能升级,以避免不必要的风险。
- 此工具仅为临时解决方案,不应替代正确的 SDK 管理实践。
- 在提交 App 审核之前,请检查隐私清单修复后是否符合最新的 App Store 要求。
欢迎任何形式的贡献,包括代码优化、Bug 修复、文档改进等。请确保遵循项目规范,并保持代码风格一致。感谢你的支持!