@leonxin/meetgames 0.1.8 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/meet-sdk-regression/SKILL.md +93 -0
- package/.cursor/mcp.example.json +16 -0
- package/.cursor/mcp.json +11 -0
- package/.cursor/skills/meetgames-mcp/SKILL.md +48 -0
- package/.vite/vitest/results.json +1 -0
- package/README.md +31 -8
- package/dist/aab-converter/aab-entry.d.ts +3 -0
- package/dist/aab-converter/aab-entry.d.ts.map +1 -0
- package/dist/aab-converter/aab-entry.js +49 -0
- package/dist/aab-converter/aab-entry.js.map +1 -0
- package/dist/aab-converter/apksExtractor.d.ts +2 -0
- package/dist/aab-converter/apksExtractor.d.ts.map +1 -0
- package/dist/aab-converter/apksExtractor.js +108 -0
- package/dist/aab-converter/apksExtractor.js.map +1 -0
- package/dist/aab-converter/bundletoolRunner.d.ts +15 -0
- package/dist/aab-converter/bundletoolRunner.d.ts.map +1 -0
- package/dist/aab-converter/bundletoolRunner.js +46 -0
- package/dist/aab-converter/bundletoolRunner.js.map +1 -0
- package/dist/aab-converter/cliArgs.d.ts +27 -0
- package/dist/aab-converter/cliArgs.d.ts.map +1 -0
- package/dist/aab-converter/cliArgs.js +170 -0
- package/dist/aab-converter/cliArgs.js.map +1 -0
- package/dist/aab-converter/convertAabToApk.d.ts +7 -0
- package/dist/aab-converter/convertAabToApk.d.ts.map +1 -0
- package/dist/aab-converter/convertAabToApk.js +69 -0
- package/dist/aab-converter/convertAabToApk.js.map +1 -0
- package/dist/aab-converter/resourcePaths.d.ts +4 -0
- package/dist/aab-converter/resourcePaths.d.ts.map +1 -0
- package/dist/aab-converter/resourcePaths.js +42 -0
- package/dist/aab-converter/resourcePaths.js.map +1 -0
- package/dist/aab-converter/signingOptions.d.ts +9 -0
- package/dist/aab-converter/signingOptions.d.ts.map +1 -0
- package/dist/aab-converter/signingOptions.js +21 -0
- package/dist/aab-converter/signingOptions.js.map +1 -0
- package/dist/aab-converter/types.d.ts +24 -0
- package/dist/aab-converter/types.d.ts.map +1 -0
- package/dist/aab-converter/types.js +2 -0
- package/dist/aab-converter/types.js.map +1 -0
- package/dist/android/adapter.d.ts.map +1 -1
- package/dist/android/adapter.js +2 -2
- package/dist/android/adapter.js.map +1 -1
- package/dist/android/detect.d.ts +2 -2
- package/dist/android/detect.d.ts.map +1 -1
- package/dist/android/detect.js +36 -8
- package/dist/android/detect.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +157 -31
- package/dist/cli.js.map +1 -1
- package/dist/config/meetSdkDefaultConfig.d.ts +19 -2
- package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
- package/dist/config/meetSdkDefaultConfig.js +67 -5
- package/dist/config/meetSdkDefaultConfig.js.map +1 -1
- package/dist/config/meetSdkIosConfig.d.ts +21 -0
- package/dist/config/meetSdkIosConfig.d.ts.map +1 -0
- package/dist/config/meetSdkIosConfig.js +66 -0
- package/dist/config/meetSdkIosConfig.js.map +1 -0
- package/dist/config/meetSdkRemoteConfig.d.ts +18 -1
- package/dist/config/meetSdkRemoteConfig.d.ts.map +1 -1
- package/dist/config/meetSdkRemoteConfig.js +61 -25
- package/dist/config/meetSdkRemoteConfig.js.map +1 -1
- package/dist/contracts/types.d.ts +19 -6
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/core/doctor.d.ts +17 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +444 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +0 -15
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/platform.d.ts +12 -0
- package/dist/core/platform.d.ts.map +1 -0
- package/dist/core/platform.js +40 -0
- package/dist/core/platform.js.map +1 -0
- package/dist/core/reporter.js +1 -1
- package/dist/core/reporter.js.map +1 -1
- package/dist/core/workspace.d.ts +2 -2
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +4 -5
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ios/channelConfig.d.ts +1 -0
- package/dist/ios/channelConfig.d.ts.map +1 -1
- package/dist/ios/channelConfig.js +82 -0
- package/dist/ios/channelConfig.js.map +1 -1
- package/dist/ios/codeUtils.d.ts +1 -0
- package/dist/ios/codeUtils.d.ts.map +1 -1
- package/dist/ios/codeUtils.js +11 -2
- package/dist/ios/codeUtils.js.map +1 -1
- package/dist/ios/detect.d.ts +2 -2
- package/dist/ios/detect.d.ts.map +1 -1
- package/dist/ios/detect.js +49 -10
- package/dist/ios/detect.js.map +1 -1
- package/dist/ios/entitlements.d.ts +4 -0
- package/dist/ios/entitlements.d.ts.map +1 -0
- package/dist/ios/entitlements.js +53 -0
- package/dist/ios/entitlements.js.map +1 -0
- package/dist/ios/fileManager.d.ts.map +1 -1
- package/dist/ios/fileManager.js +3 -2
- package/dist/ios/fileManager.js.map +1 -1
- package/dist/ios/infoPlist.d.ts +1 -1
- package/dist/ios/infoPlist.d.ts.map +1 -1
- package/dist/ios/infoPlist.js.map +1 -1
- package/dist/ios/integrate.d.ts.map +1 -1
- package/dist/ios/integrate.js +211 -36
- package/dist/ios/integrate.js.map +1 -1
- package/dist/ios/pbxprojEditor.d.ts +2 -0
- package/dist/ios/pbxprojEditor.d.ts.map +1 -1
- package/dist/ios/pbxprojEditor.js +179 -1
- package/dist/ios/pbxprojEditor.js.map +1 -1
- package/dist/ios/pluginConfig.d.ts +1 -0
- package/dist/ios/pluginConfig.d.ts.map +1 -1
- package/dist/ios/pluginConfig.js +36 -4
- package/dist/ios/pluginConfig.js.map +1 -1
- package/dist/ios/sdkBundle.d.ts +1 -1
- package/dist/ios/sdkBundle.d.ts.map +1 -1
- package/dist/ios/sdkBundle.js +7 -5
- package/dist/ios/sdkBundle.js.map +1 -1
- package/dist/ios/template.d.ts +1 -0
- package/dist/ios/template.d.ts.map +1 -1
- package/dist/ios/template.js +14 -1
- package/dist/ios/template.js.map +1 -1
- package/dist/ios/types.d.ts +2 -2
- package/dist/ios/types.d.ts.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +14 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service.d.ts +8 -6
- package/dist/mcp/service.d.ts.map +1 -1
- package/dist/mcp/service.js +34 -14
- package/dist/mcp/service.js.map +1 -1
- package/dist/ops/handlers.d.ts.map +1 -1
- package/dist/ops/handlers.js +10 -4
- package/dist/ops/handlers.js.map +1 -1
- package/dist/remote/sdkHomeDownload.d.ts +65 -0
- package/dist/remote/sdkHomeDownload.d.ts.map +1 -0
- package/dist/remote/sdkHomeDownload.js +208 -0
- package/dist/remote/sdkHomeDownload.js.map +1 -0
- package/dist/remote/topsdkDownloadSdkConfig.d.ts.map +1 -1
- package/dist/remote/topsdkDownloadSdkConfig.js +11 -1
- package/dist/remote/topsdkDownloadSdkConfig.js.map +1 -1
- package/dist/shared/errors.d.ts +7 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +16 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/fileUtils.d.ts +5 -0
- package/dist/shared/fileUtils.d.ts.map +1 -0
- package/dist/shared/fileUtils.js +35 -0
- package/dist/shared/fileUtils.js.map +1 -0
- package/dist/shared/logger.d.ts +10 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +37 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/pathUtils.d.ts +4 -0
- package/dist/shared/pathUtils.d.ts.map +1 -0
- package/dist/shared/pathUtils.js +22 -0
- package/dist/shared/pathUtils.js.map +1 -0
- package/dist/shared/processRunner.d.ts +12 -0
- package/dist/shared/processRunner.d.ts.map +1 -0
- package/dist/shared/processRunner.js +31 -0
- package/dist/shared/processRunner.js.map +1 -0
- package/docs/AAB_CONVERTER_CLI_PLAN.md +392 -0
- package/docs/API.md +246 -32
- package/docs/CLI.md +292 -0
- package/docs/INTEGRATION.md +116 -0
- package/docs/MCP.md +86 -0
- package/docs/README.md +19 -10
- package/docs/{api → archive/api}/downloadSDKConfig.md +8 -6
- package/docs/{api → archive/api}/getChannelConfig-meetgames.md +1 -1
- package/docs/archive/ios-migration.md +2139 -0
- package/docs/{ → archive/product/}/346/212/200/346/234/257/346/226/271/346/241/210/350/260/203/347/240/224.md +7 -7
- package/docs/{ → archive/product/}/351/234/200/346/261/202/346/226/207/346/241/243.md +15 -14
- package/logs/convert-20260622-155037.log +5 -0
- package/logs/convert-20260622-155226.log +6 -0
- package/meetsdk-android.json +2 -1
- package/meetsdk-ios.json +15 -0
- package/package.json +10 -36
- package/scripts/package-aab-cli-win.mjs +193 -0
- package/src/aab-converter/aab-entry.ts +48 -0
- package/src/aab-converter/apksExtractor.ts +119 -0
- package/src/aab-converter/bundletoolRunner.ts +63 -0
- package/src/aab-converter/cliArgs.ts +194 -0
- package/src/aab-converter/convertAabToApk.ts +81 -0
- package/src/aab-converter/resourcePaths.ts +43 -0
- package/src/aab-converter/signingOptions.ts +29 -0
- package/src/aab-converter/types.ts +26 -0
- package/src/android/adapter.ts +9 -0
- package/src/android/assembleIntegrationJson.ts +33 -0
- package/src/android/detect.ts +132 -0
- package/src/android/downloadGoogleServicesJson.ts +56 -0
- package/src/android/gradle.ts +116 -0
- package/src/android/manifest.ts +50 -0
- package/src/android/meetSdkRemoteGradle.ts +837 -0
- package/src/cli.ts +488 -0
- package/src/config/fetchConfigWrite.ts +30 -0
- package/src/config/loadAndroidIntegration.ts +41 -0
- package/src/config/loadManifest.ts +40 -0
- package/src/config/meetSdkDefaultConfig.ts +99 -0
- package/src/config/meetSdkIosConfig.ts +87 -0
- package/src/config/meetSdkRemoteConfig.ts +1211 -0
- package/src/config/topsdkFeatureModules.ts +92 -0
- package/src/contracts/types.ts +121 -0
- package/src/core/doctor.ts +485 -0
- package/src/core/patch.ts +64 -0
- package/src/core/pipeline.ts +107 -0
- package/src/core/platform.ts +47 -0
- package/src/core/previewPatches.ts +23 -0
- package/src/core/reporter.ts +24 -0
- package/src/core/workspace.ts +29 -0
- package/src/entry.ts +7 -0
- package/src/index.ts +133 -0
- package/src/ios/channelConfig.ts +128 -0
- package/src/ios/codeUtils.ts +160 -0
- package/src/ios/detect.ts +105 -0
- package/src/ios/entitlements.ts +61 -0
- package/src/ios/fileManager.ts +48 -0
- package/src/ios/infoPlist.ts +55 -0
- package/src/ios/integrate.ts +516 -0
- package/src/ios/pbxprojEditor.ts +383 -0
- package/src/ios/pluginConfig.ts +97 -0
- package/src/ios/reserved.ts +8 -0
- package/src/ios/sdkBundle.ts +36 -0
- package/src/ios/template.ts +36 -0
- package/src/ios/types.ts +65 -0
- package/src/mcp/server.ts +170 -0
- package/src/mcp/service.ts +222 -0
- package/src/mcp-entry.ts +7 -0
- package/src/ops/fileStore.ts +56 -0
- package/src/ops/handlers.ts +304 -0
- package/src/remote/fetchJson.ts +22 -0
- package/src/remote/sdkHomeDownload.ts +274 -0
- package/src/remote/topsdkDownloadSdkConfig.ts +93 -0
- package/src/remote/topsdkGetSdkConfig.ts +122 -0
- package/src/remote/topsdkSign.ts +10 -0
- package/src/shared/errors.ts +16 -0
- package/src/shared/fileUtils.ts +41 -0
- package/src/shared/logger.ts +49 -0
- package/src/shared/pathUtils.ts +24 -0
- package/src/shared/processRunner.ts +43 -0
- package/test-projects/README.md +51 -0
- package/test-projects/_preview/pipeline.patch +281 -0
- package/tests/aab-converter.test.ts +213 -0
- package/tests/assemble.test.ts +12 -0
- package/tests/doctor.test.ts +89 -0
- package/tests/downloadGoogleServicesJson.test.ts +47 -0
- package/tests/fetch-remote.test.ts +23 -0
- package/tests/fetchConfigOverrides.test.ts +28 -0
- package/tests/fetchConfigWrite.test.ts +54 -0
- package/tests/gradle.test.ts +33 -0
- package/tests/integration-json.test.ts +29 -0
- package/tests/ios.codeUtils.test.ts +23 -0
- package/tests/ios.sdkBundle.test.ts +16 -0
- package/tests/loadManifest.test.ts +15 -0
- package/tests/manifest-xml.test.ts +30 -0
- package/tests/mcp.e2e.ts +217 -0
- package/tests/mcp.service.test.ts +53 -0
- package/tests/meetSdkRemoteConfig.test.ts +456 -0
- package/tests/meetSdkRemoteGradle.test.ts +414 -0
- package/tests/pipeline.android.test.ts +96 -0
- package/tests/pipeline.integration-json.test.ts +58 -0
- package/tests/pipeline.ios.test.ts +385 -0
- package/tests/pipeline.preview.patch.test.ts +85 -0
- package/tests/platformSelection.test.ts +77 -0
- package/tests/sdkHomeDownload.test.ts +124 -0
- package/tests/sdkVersionConfig.test.ts +130 -0
- package/tests/test-projects-hosts.test.ts +78 -0
- package/tests/topsdk.test.ts +53 -0
- package/tests/topsdkDownloadSdkConfig.test.ts +81 -0
- package/tests/topsdkFeatureModules.test.ts +116 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +9 -0
- package/vitest.mcp.config.ts +11 -0
- package/bundled/android/sample.txt +0 -1
- package/docs/ANDROID.md +0 -133
- package/docs/CURSOR-MCP-SETUP.md +0 -72
- package/docs/MCP-SKILL.md +0 -63
- package/fixtures/api-samples/getChannelConfig-meetgames.sample.json +0 -123
- package/fixtures/meetsdk-remote-config.download-shape.json +0 -20
- package/fixtures/meetsdk-remote-config.mock.json +0 -69
- package/fixtures/recipes/android-default.fixture.yaml +0 -15
- package/fixtures/recipes/android-integration.fixture.json +0 -29
- package/fixtures/topsdk-config-reference.json +0 -39
- /package/docs/{api → archive/api}/getSDKConfig.md +0 -0
|
@@ -0,0 +1,2139 @@
|
|
|
1
|
+
# iOS 迁移归档
|
|
2
|
+
|
|
3
|
+
本文由原 iOS 迁移相关文档合并而来,用于保留 `topsdk-tool-ios` Python 工具迁移到 `meet-sdk-tool` 的历史过程、功能对照、测试方法和差异记录。日常接入请查看 `docs/INTEGRATION.md`。
|
|
4
|
+
|
|
5
|
+
## 合并来源
|
|
6
|
+
|
|
7
|
+
- 旧 Python 工具完整流程: `docs/ios-topsdk-tool-python-flow.md`
|
|
8
|
+
- 功能点与测试方法: `docs/ios-topsdk-tool-feature-test-plan.md`
|
|
9
|
+
- Python 到 TypeScript 对照: `docs/ios-migration-parity.md`
|
|
10
|
+
- 差异与缺失备忘: `docs/ios-migration-gap-memo.md`
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 旧 Python 工具完整流程
|
|
16
|
+
|
|
17
|
+
本文档基于 `topsdk-tool-ios` 工程源码整理,目标是把旧 Python 工具中会被打包为 `TopSDKTool` 的 iOS 原生工程自动接入流程完整记录下来,方便后续在 `meet-sdk-tool` 中用 TypeScript 实现等价能力。
|
|
18
|
+
|
|
19
|
+
范围只覆盖旧工具对 iOS SDK 接入的核心行为:
|
|
20
|
+
|
|
21
|
+
- `TopSDKTool` 打包和运行时资源布局。
|
|
22
|
+
- 读取 SDK / 插件配置。
|
|
23
|
+
- 获取并校验远端渠道参数。
|
|
24
|
+
- 自动修改 `.xcodeproj`、`Info.plist`、entitlements。
|
|
25
|
+
- 复制 framework、bundle、lib、源码等资源到游戏工程。
|
|
26
|
+
- 自动注入 `UIApplicationDelegate` / `UIWindowSceneDelegate` 相关代码。
|
|
27
|
+
|
|
28
|
+
不覆盖上传、更新、Unity、Cocos、LayaNative 等非原生 iOS 工程接入逻辑;这些逻辑在旧工具中存在,但本次迁移目标不需要实现。
|
|
29
|
+
|
|
30
|
+
## 1. 关键源码位置
|
|
31
|
+
|
|
32
|
+
旧工程:`/Users/work/Workspace/Projects/topsdk-tool-ios`
|
|
33
|
+
|
|
34
|
+
| 文件 | 作用 |
|
|
35
|
+
|------|------|
|
|
36
|
+
| `TopSDKTool.py` | 主入口,串联资源读取、在线参数获取、目标 target 选择、SDK / 插件接入、Delegate 注入 |
|
|
37
|
+
| `autoBuild.sh` | 使用 PyInstaller 打包 `TopSDKTool.py` 为单文件可执行程序 |
|
|
38
|
+
| `TopSDKTool.spec` | PyInstaller 打包配置 |
|
|
39
|
+
| `TOPSDKUtils/PluginConfig.py` | 解析 `sdk/*.json` 和 `plugins/*/config.json` |
|
|
40
|
+
| `TOPSDKUtils/ChannelConfigManager.py` | 请求服务端 SDK 渠道配置 |
|
|
41
|
+
| `TOPSDKUtils/XcodeManager.py` | 修改 Xcode 工程、Info.plist、entitlements、查找 Delegate 文件 |
|
|
42
|
+
| `TOPSDKUtils/FileManager.py` | 把 SDK 资源复制到游戏工程 `topSDK/` 目录 |
|
|
43
|
+
| `TOPSDKUtils/InfoPlistManager.py` | 写入 `Info.plist` 字段、URL Scheme、Queries Schemes |
|
|
44
|
+
| `TOPSDKUtils/CodeUtils.py` | 给 Objective-C / Objective-C++ 文件插入 import 和方法代码 |
|
|
45
|
+
| `TOPSDKUtils/commonUtils.py` | 命令行交互选择和路径输入 |
|
|
46
|
+
| `TOPSDKUtils/ToolConfig.py` | 工具版本、环境、wiki 地址、服务端 base url |
|
|
47
|
+
|
|
48
|
+
## 2. 打包形态
|
|
49
|
+
|
|
50
|
+
### 2.1 打包命令
|
|
51
|
+
|
|
52
|
+
`autoBuild.sh` 的实际动作:
|
|
53
|
+
|
|
54
|
+
1. 删除本地 `build/` 和 `dist/`。
|
|
55
|
+
2. 执行:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pyinstaller -F TopSDKTool.py
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
3. 删除 `TopSDK/TopSDKTool`。
|
|
62
|
+
4. 将 `dist/TopSDKTool` 复制到 `TopSDK/TopSDKTool`。
|
|
63
|
+
5. 再次删除 `build/` 和 `dist/`。
|
|
64
|
+
|
|
65
|
+
### 2.2 PyInstaller 配置
|
|
66
|
+
|
|
67
|
+
`TopSDKTool.spec` 中 `datas=[]`、`binaries=[]`,说明 SDK 资源并不会被打进可执行文件。可执行文件只包含 Python 代码和依赖。
|
|
68
|
+
|
|
69
|
+
因此发布包必须把 `TopSDKTool` 和资源目录放在同一个根目录下:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
TopSDK/
|
|
73
|
+
TopSDKTool
|
|
74
|
+
sdk/
|
|
75
|
+
*.json
|
|
76
|
+
source/
|
|
77
|
+
...
|
|
78
|
+
plugins/
|
|
79
|
+
AppleSignin/
|
|
80
|
+
config.json
|
|
81
|
+
source/
|
|
82
|
+
...
|
|
83
|
+
GoogleSignin/
|
|
84
|
+
config.json
|
|
85
|
+
source/
|
|
86
|
+
...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2.3 运行时根目录
|
|
90
|
+
|
|
91
|
+
`TopSDKTool.py` 中:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
rootPath = os.path.dirname(os.path.realpath(sys.argv[0]))
|
|
95
|
+
sdkPath = os.path.join(rootPath, "sdk")
|
|
96
|
+
pluginsPath = os.path.join(rootPath, "plugins")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
生产环境下,`rootPath` 是 `TopSDKTool` 可执行文件所在目录。也就是说,工具依赖“可执行文件旁边的 `sdk/` 和 `plugins/`”。
|
|
100
|
+
|
|
101
|
+
注意:当 `currentEnv != ENV.prod` 时,代码会把 `rootPath` 写死成开发者本机路径:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
rootPath = "/Users/lvyunjie/Downloads/topSDK-ios--V1.6.0.2"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
这个行为只用于旧工具本地调试,TS 迁移时不应该保留。
|
|
108
|
+
|
|
109
|
+
## 3. 运行输入
|
|
110
|
+
|
|
111
|
+
旧工具通过命令行交互获取输入:
|
|
112
|
+
|
|
113
|
+
1. `appId`
|
|
114
|
+
2. `appSecret`
|
|
115
|
+
3. 游戏引擎类型
|
|
116
|
+
4. Unity / Cocos 版本,原生 iOS 不需要
|
|
117
|
+
5. `.xcodeproj` 路径
|
|
118
|
+
6. 当工程中有多个 target 时,选择目标 target
|
|
119
|
+
7. 当检测到多个 AppDelegate / SceneDelegate 文件时,选择需要注入的文件
|
|
120
|
+
|
|
121
|
+
原生 iOS 迁移到 `meet-sdk-tool` 后,建议改为非交互式参数:
|
|
122
|
+
|
|
123
|
+
| 旧工具交互输入 | TS 工具建议 |
|
|
124
|
+
|----------------|------------|
|
|
125
|
+
| `appId` | 沿用现有 `--app-id` |
|
|
126
|
+
| `appSecret` | 沿用现有 `--app-secret` |
|
|
127
|
+
| `.xcodeproj` 路径 | 使用 `--project-root` 自动查找或由命令参数指定 |
|
|
128
|
+
| 游戏引擎 | 不再识别 engine,只处理 Xcode 工程 |
|
|
129
|
+
| target 选择 | 可默认选择唯一 App target;多 target 时通过参数或明确报错 |
|
|
130
|
+
| Delegate 文件选择 | 唯一时自动注入;多个时通过参数或明确报错 |
|
|
131
|
+
|
|
132
|
+
## 4. 配置文件模型
|
|
133
|
+
|
|
134
|
+
旧工具将 SDK 核心和插件都抽象为 `PluginConfig`。
|
|
135
|
+
|
|
136
|
+
### 4.1 SDK 核心配置
|
|
137
|
+
|
|
138
|
+
启动时读取:
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
sdk/*.json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
过滤规则:
|
|
145
|
+
|
|
146
|
+
- 文件名必须以 `.json` 结尾。
|
|
147
|
+
- 文件名不能以 `.` 开头。
|
|
148
|
+
|
|
149
|
+
读取后放入 `sdkConfigs`。
|
|
150
|
+
|
|
151
|
+
### 4.2 插件配置
|
|
152
|
+
|
|
153
|
+
启动时读取:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
plugins/<PluginName>/config.json
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
只要 `config.json` 存在,就构造 `PluginConfig` 并放入 `pluginConfigs`。
|
|
160
|
+
|
|
161
|
+
### 4.3 PluginConfig 字段
|
|
162
|
+
|
|
163
|
+
`PluginConfig.py` 强依赖这些字段存在:
|
|
164
|
+
|
|
165
|
+
| 字段 | 用途 |
|
|
166
|
+
|------|------|
|
|
167
|
+
| `name` | 插件名,同时用于匹配插件目录名 |
|
|
168
|
+
| `key` | 服务端渠道配置 key,如 `GOOGLE`、`FACEBOOK` |
|
|
169
|
+
| `type` | 插件类型,`0` SDK 核心、`1` 登录、`2` 支付、`3` UI、`4` 数据 |
|
|
170
|
+
| `pluginVersion` | 插件版本,仅用于日志 |
|
|
171
|
+
| `sources` | 需要复制和加入 Xcode 工程的源码 / 资源 |
|
|
172
|
+
| `frameworks` | framework / bundle 依赖列表 |
|
|
173
|
+
| `libs` | 静态库或系统 lib 依赖列表 |
|
|
174
|
+
| `buildSettings` | 需要写入 target build settings 的配置 |
|
|
175
|
+
| `OtherLinkerFlags` | 需要追加到 `OTHER_LDFLAGS` 的 flag |
|
|
176
|
+
| `queriesSchemes` | 需要追加到 `LSApplicationQueriesSchemes` 的 scheme |
|
|
177
|
+
| `urlScheme` | 需要追加到 `CFBundleURLTypes` 的 URL Scheme |
|
|
178
|
+
| `infoParams` | 需要写入 `Info.plist` 的字段 |
|
|
179
|
+
| `requireConfigs` | 必须从服务端返回的渠道参数 |
|
|
180
|
+
| `pluginParams` | 写入 `TOPSDK.Plugins[].params` 的参数模板 |
|
|
181
|
+
| `appDelegateCodes` | 需要注入到 AppDelegate 的代码片段 |
|
|
182
|
+
| `sceneDelegateCodes` | 需要注入到 SceneDelegate 的代码片段 |
|
|
183
|
+
|
|
184
|
+
### 4.4 framework 配置
|
|
185
|
+
|
|
186
|
+
每个 framework 项解析为:
|
|
187
|
+
|
|
188
|
+
| 字段 | 用途 |
|
|
189
|
+
|------|------|
|
|
190
|
+
| `name` | framework / bundle 文件名 |
|
|
191
|
+
| `system` | 是否系统 framework |
|
|
192
|
+
| `embed` | 是否加入 Embed Frameworks |
|
|
193
|
+
| `copyFile` | 是否额外加入 CopyFiles phase,默认 `false` |
|
|
194
|
+
|
|
195
|
+
### 4.5 lib 配置
|
|
196
|
+
|
|
197
|
+
每个 lib 项解析为:
|
|
198
|
+
|
|
199
|
+
| 字段 | 用途 |
|
|
200
|
+
|------|------|
|
|
201
|
+
| `name` | lib 文件名 |
|
|
202
|
+
| `system` | 是否系统 lib |
|
|
203
|
+
|
|
204
|
+
### 4.6 code 配置
|
|
205
|
+
|
|
206
|
+
每个代码注入项解析为:
|
|
207
|
+
|
|
208
|
+
| 字段 | 用途 |
|
|
209
|
+
|------|------|
|
|
210
|
+
| `type` | `header` 表示插入头部 import;其他值表示插入方法代码 |
|
|
211
|
+
| `method` | 目标 Objective-C 方法签名 |
|
|
212
|
+
| `content` | 要插入的代码 |
|
|
213
|
+
| `addToReturn` | 是否把代码合并到方法 return 结果中 |
|
|
214
|
+
|
|
215
|
+
## 5. 资源完整性检查
|
|
216
|
+
|
|
217
|
+
入口在 `checkEnv()`。
|
|
218
|
+
|
|
219
|
+
### 5.1 SDK 目录检查
|
|
220
|
+
|
|
221
|
+
如果 `sdk/` 不存在:
|
|
222
|
+
|
|
223
|
+
```text
|
|
224
|
+
error: sdk目录不存在
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
返回 `False`,主流程随后退出。
|
|
228
|
+
|
|
229
|
+
### 5.2 plugins 目录检查
|
|
230
|
+
|
|
231
|
+
如果 `plugins/` 不存在或为空,只打印 warning:
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
warning:没有任何插件资源
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
不会退出。
|
|
238
|
+
|
|
239
|
+
### 5.3 插件资源检查
|
|
240
|
+
|
|
241
|
+
对 `plugins/` 下每个非隐藏目录执行 `checkPlugin(pluginDirName)`。
|
|
242
|
+
|
|
243
|
+
检查项:
|
|
244
|
+
|
|
245
|
+
1. `plugins/<PluginName>/config.json` 必须存在。
|
|
246
|
+
2. `config.json` 必须是合法 JSON object。
|
|
247
|
+
3. `config.name` 必须等于插件目录名。
|
|
248
|
+
4. `sources[]` 中每个资源必须存在于:
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
plugins/<PluginName>/source/<sourceName>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
5. `frameworks[]` 中 `system=false` 的资源必须存在于:
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
plugins/<PluginName>/source/<frameworkName>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
6. `libs[]` 中 `system=false` 的资源必须存在于:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
plugins/<PluginName>/source/<libName>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
注意:旧工具会把错误插件收集到 `errorPlugins`,但 `checkEnv()` 最后仍然返回 `True`。这意味着某个插件校验失败不会真正阻止后续流程。TS 迁移时建议修正为明确失败,避免产物半接入。
|
|
267
|
+
|
|
268
|
+
## 6. 获取服务端渠道参数
|
|
269
|
+
|
|
270
|
+
入口在 `getOnlineConfig(pluginConfigs)`。
|
|
271
|
+
|
|
272
|
+
### 6.1 无插件场景
|
|
273
|
+
|
|
274
|
+
如果 `pluginConfigs` 为空:
|
|
275
|
+
|
|
276
|
+
1. 只要求输入 `appId`。
|
|
277
|
+
2. 返回:
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
onlineConfig = None
|
|
281
|
+
appId = inputAppId
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 6.2 有插件场景
|
|
285
|
+
|
|
286
|
+
如果存在插件:
|
|
287
|
+
|
|
288
|
+
1. 收集所有 `pluginConfig.key` 到 `pluginKeys`。
|
|
289
|
+
2. 汇总所有 `pluginConfig.requireConfigs` 到 `needOnlineParams`。
|
|
290
|
+
3. 如果 `needOnlineParams` 为空,不请求服务端。
|
|
291
|
+
4. 如果 `needOnlineParams` 非空,循环要求输入 `appId`、`appSecret`,直到服务端返回有效配置。
|
|
292
|
+
|
|
293
|
+
### 6.3 请求接口
|
|
294
|
+
|
|
295
|
+
`ChannelConfigManager.getSdkConfig(appId, appSecret, types)` 请求:
|
|
296
|
+
|
|
297
|
+
```text
|
|
298
|
+
GET {baseUrl}/console/openSDK/getSDKConfig
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
生产 / 预发布 base url 当前都指向:
|
|
302
|
+
|
|
303
|
+
```text
|
|
304
|
+
https://pre-api-sdk-gameplus.meetsocial.com/
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
测试环境 base url:
|
|
308
|
+
|
|
309
|
+
```text
|
|
310
|
+
https://test-api-sdk-gameplus.meetsocial.com:1157/
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
请求参数:
|
|
314
|
+
|
|
315
|
+
| 参数 | 来源 |
|
|
316
|
+
|------|------|
|
|
317
|
+
| `appId` | 用户输入 |
|
|
318
|
+
| `authType` | 插件 key 列表,排除 `GUEST`、`UI`、`IAPPAY` |
|
|
319
|
+
| `channelType` | 固定 `"apple"` |
|
|
320
|
+
| `timestamp` | 当前毫秒时间戳 |
|
|
321
|
+
| `sign` | `base64(md5(appId + appSecret + timestamp))` |
|
|
322
|
+
|
|
323
|
+
### 6.4 返回解析
|
|
324
|
+
|
|
325
|
+
仅当 HTTP status 为 `200` 且业务 `code == 200` 时解析:
|
|
326
|
+
|
|
327
|
+
```text
|
|
328
|
+
data.channelAuthConfig[]
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
每项用 `authType.upper()` 作为 key 存入 `sdkConfig`。
|
|
332
|
+
|
|
333
|
+
特殊处理:
|
|
334
|
+
|
|
335
|
+
- `MESSENGER` 会归并为 `FACEBOOK`,并设置 `openMessenger = "1"`。
|
|
336
|
+
- `FACEBOOK` 会设置 `openMessenger = "0"`。
|
|
337
|
+
|
|
338
|
+
最终结构类似:
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"GOOGLE": {
|
|
343
|
+
"authType": "GOOGLE",
|
|
344
|
+
"clientId": "...",
|
|
345
|
+
"scheme": "..."
|
|
346
|
+
},
|
|
347
|
+
"FACEBOOK": {
|
|
348
|
+
"authType": "FACEBOOK",
|
|
349
|
+
"clientId": "...",
|
|
350
|
+
"name": "...",
|
|
351
|
+
"scheme": "...",
|
|
352
|
+
"secret": "...",
|
|
353
|
+
"openMessenger": "0"
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### 6.5 requireConfigs 校验
|
|
359
|
+
|
|
360
|
+
服务端返回后,旧工具会把所有非空字段转换成:
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
<CHANNEL_KEY>.<fieldName>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
例如:
|
|
367
|
+
|
|
368
|
+
```text
|
|
369
|
+
GOOGLE.clientId
|
|
370
|
+
GOOGLE.scheme
|
|
371
|
+
FACEBOOK.clientId
|
|
372
|
+
FACEBOOK.name
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
然后逐个检查 `needOnlineParams` 是否都存在。不完整时输出:
|
|
376
|
+
|
|
377
|
+
```text
|
|
378
|
+
参数缺失,请与SDK方沟通确认配置完整性,缺失配置包括:...
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
并退出。
|
|
382
|
+
|
|
383
|
+
### 6.6 `GOOGLE.scheme` 与 `FACEBOOK.name` 的旧逻辑位置
|
|
384
|
+
|
|
385
|
+
这两个字段不是写死在 `topsdk-tool-ios` 主流程代码里,而是来自旧 iOS SDK 下载包中的插件配置文件。`topsdk-tool-ios` 仓库本体只包含工具源码;运行时会以 `rootPath` 为根读取下载包资源:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
<rootPath>/sdk/*.json
|
|
389
|
+
<rootPath>/plugins/<PluginName>/config.json
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
对应源码入口:
|
|
393
|
+
|
|
394
|
+
| 行为 | 旧工程位置 |
|
|
395
|
+
|------|------------|
|
|
396
|
+
| 读取插件配置中的 `requireConfigs`、`infoParams`、`pluginParams`、`urlScheme`、`key` | `TOPSDKUtils/PluginConfig.py` |
|
|
397
|
+
| 汇总所有插件的 `requireConfigs` 到 `needOnlineParams` | `TopSDKTool.py#getOnlineConfig()` |
|
|
398
|
+
| 请求服务端 `console/openSDK/getSDKConfig`,固定 `channelType = "apple"` | `TOPSDKUtils/ChannelConfigManager.py#getSdkConfig()` |
|
|
399
|
+
| 将 `channelAuthConfig[]` 以 `authType.upper()` 存入 `sdkConfig` | `TOPSDKUtils/ChannelConfigManager.py#getSdkConfig()` |
|
|
400
|
+
| 校验 `needOnlineParams` 是否都在服务端返回字段中 | `TopSDKTool.py#getOnlineConfig()` |
|
|
401
|
+
| 用 `checkStr()` 替换 `{$C.GOOGLE.scheme}`、`{$C.FACEBOOK.name}` 等占位符 | `TopSDKTool.py#checkStr()`、`TopSDKTool.py#setPlugin()` |
|
|
402
|
+
|
|
403
|
+
旧插件配置中这两个字段的使用方式如下。当前 `meet-sdk-tool` 的 `bundled/ios-sdk/ios--V1.6.0.4` 是该旧下载包资源的迁移副本,文件名从旧包常见的 `config.json` 保留为工具内使用的 `config.t.json`:
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
// plugins/GoogleSignin/config.json
|
|
407
|
+
{
|
|
408
|
+
"name": "GoogleSignin",
|
|
409
|
+
"key": "GOOGLE",
|
|
410
|
+
"requireConfigs": [
|
|
411
|
+
"GOOGLE.scheme",
|
|
412
|
+
"GOOGLE.clientId"
|
|
413
|
+
],
|
|
414
|
+
"pluginParams": {
|
|
415
|
+
"CLIENT_ID": "{$C.GOOGLE.clientId}",
|
|
416
|
+
"REVERSED_CLIENT_ID": "{$C.GOOGLE.scheme}"
|
|
417
|
+
},
|
|
418
|
+
"urlScheme": "{$C.GOOGLE.scheme}"
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
`GOOGLE.scheme` 在旧逻辑中有两个作用:
|
|
423
|
+
|
|
424
|
+
1. 写入 `TOPSDK -> Plugins[] -> params.REVERSED_CLIENT_ID`,供 `GoogleSignin` 插件运行时读取。
|
|
425
|
+
2. 作为 `urlScheme` 写入宿主 `Info.plist` 的 `CFBundleURLTypes[].CFBundleURLSchemes[]`,供 Google 登录回跳 App。
|
|
426
|
+
|
|
427
|
+
```json
|
|
428
|
+
// plugins/FacebookSignin/config.json
|
|
429
|
+
{
|
|
430
|
+
"name": "FacebookSignin",
|
|
431
|
+
"key": "FACEBOOK",
|
|
432
|
+
"infoParams": {
|
|
433
|
+
"FacebookAppID": "{$C.FACEBOOK.clientId}",
|
|
434
|
+
"FacebookDisplayName": "{$C.FACEBOOK.name}",
|
|
435
|
+
"FacebookClientToken": "{$C.FACEBOOK.secret}"
|
|
436
|
+
},
|
|
437
|
+
"requireConfigs": [
|
|
438
|
+
"FACEBOOK.clientId",
|
|
439
|
+
"FACEBOOK.name",
|
|
440
|
+
"FACEBOOK.scheme",
|
|
441
|
+
"FACEBOOK.secret",
|
|
442
|
+
"FACEBOOK.openMessenger"
|
|
443
|
+
],
|
|
444
|
+
"pluginParams": {
|
|
445
|
+
"OPEN_MESSENGER": "{$C.FACEBOOK.openMessenger}"
|
|
446
|
+
},
|
|
447
|
+
"urlScheme": "{$C.FACEBOOK.scheme}"
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
`FACEBOOK.name` 在旧逻辑中只用于 `infoParams`,最终写入宿主 `Info.plist` 顶层的 `FacebookDisplayName`。旧工具不会自动从 `packageName`、App 名称或 `facebookAppId` 推导它;如果服务端 `channelAuthConfig` 没有返回非空 `name` 字段,`requireConfigs` 校验会失败并退出。
|
|
452
|
+
|
|
453
|
+
字段名要求是旧 iOS 插件配置决定的:Google 要求服务端返回 `scheme` 和 `clientId`;Facebook 要求服务端返回 `clientId`、`name`、`scheme`、`secret`。旧工具本身只做 `MESSENGER -> FACEBOOK` 归并和 `openMessenger` 补值,不会把 `googleClientId` 映射成 `clientId`,也不会把 `fbLoginProtocolScheme` 映射成 `scheme`。
|
|
454
|
+
|
|
455
|
+
### 6.7 bundled iOS 插件配置矩阵
|
|
456
|
+
|
|
457
|
+
后续 `meet-sdk-tool` 的 `bundled/ios-sdk` 会提供完整 iOS SDK 包,包内每个插件目录包含 `config.json`(当前仓库测试包使用 `config.t.json`)。旧 Python 工具对这些配置的处理是统一的:
|
|
458
|
+
|
|
459
|
+
1. `PluginConfig.py` 读取配置字段。
|
|
460
|
+
2. `getOnlineConfig()` 汇总所有启用插件的 `requireConfigs`。
|
|
461
|
+
3. `ChannelConfigManager.getSdkConfig()` 按插件 `key` 拉取在线配置。
|
|
462
|
+
4. `setPlugin()` 根据 `performSettings` 依次处理 `sources`、`frameworks`、`libs`、`buildSettings`、`OtherLinkerFlags`、`queriesSchemes`、`infoParams`、`urlScheme`。
|
|
463
|
+
5. 遍历插件后,将 `pluginParams` 写入 `TOPSDK -> Plugins[]` 或 `TOPSDK -> dataPlugins[]`。
|
|
464
|
+
|
|
465
|
+
当前 `bundled/ios-sdk/topSDK-ios--V1.6.0.5/plugins` 中的配置要求如下:
|
|
466
|
+
|
|
467
|
+
| 插件目录 | config.name | key | type | requireConfigs | 写入/作用 |
|
|
468
|
+
|----------|-------------|-----|------|----------------|-----------|
|
|
469
|
+
| `GuestSignin` | `GuestSignin` | `GUEST` | 登录 | 无 | 复制 `TOPGuestSigninPlugin.framework`;注册到 `TOPSDK.Plugins` |
|
|
470
|
+
| `EmailSignin` | `EmailSignin` | `EMAIL` | 登录 | 无 | 复制 `TOPEmailSigninPlugin.framework`;注册到 `TOPSDK.Plugins` |
|
|
471
|
+
| `AppleSignin` | `AppleSignin` | `APPLE` | 登录 | 无 | 复制 `TOPAppleSigninPlugin.framework`;额外开启 Sign in with Apple entitlement;注册到 `TOPSDK.Plugins` |
|
|
472
|
+
| `GoogleSignin` | `GoogleSignin` | `GOOGLE` | 登录 | `GOOGLE.scheme`, `GOOGLE.clientId` | `pluginParams.CLIENT_ID = GOOGLE.clientId`;`pluginParams.REVERSED_CLIENT_ID = GOOGLE.scheme`;`urlScheme = GOOGLE.scheme` |
|
|
473
|
+
| `FacebookSignin` | `FacebookSignin` | `FACEBOOK` | 登录 | `FACEBOOK.clientId`, `FACEBOOK.name`, `FACEBOOK.scheme`, `FACEBOOK.secret`, `FACEBOOK.openMessenger` | `Info.plist` 写 `FacebookAppID`、`FacebookDisplayName`、`FacebookClientToken`;`pluginParams.OPEN_MESSENGER`;`urlScheme = FACEBOOK.scheme`;写入 Facebook 查询 schemes |
|
|
474
|
+
| `SnapchatSignin` | `SnapchatSignin` | `SNAPCHAT` | 登录 | `SNAPCHAT.clientId`, `SNAPCHAT.redirect`, `SNAPCHAT.scheme` | `Info.plist` 写 `SCSDKClientId`、`SCSDKRedirectUrl`、`SCSDKScopes`;`pluginParams.CLIENT_ID/REDIRECT_URL/URL_SCHEME`;`urlScheme = SNAPCHAT.scheme`;写入 Snapchat 查询 schemes |
|
|
475
|
+
| `LineSignin` | `LineSignin` | `LINE` | 登录 | `LINE.clientId`, `LINE.scheme` | `pluginParams.CHANNEL_ID = LINE.clientId`;`pluginParams.URL_SCHEME = LINE.scheme`;`urlScheme = LINE.scheme`;写入 `lineauth2` |
|
|
476
|
+
| `NaverSignin` | `NaverSignin` | `NAVER` | 登录 | `NAVER.name`, `NAVER.clientId`, `NAVER.secret`, `NAVER.scheme` | `pluginParams.APP_NAME/CLIENT_ID/CLIENT_SECRET/URL_SCHEME`;`urlScheme = NAVER.scheme`;写入 Naver 查询 schemes |
|
|
477
|
+
| `KakaoSignin` | `KakaoSignin` | `KAKAO` | 登录 | `KAKAO.clientId`, `KAKAO.scheme` | `pluginParams.NATIVE_APP_KEY = KAKAO.clientId`;`pluginParams.URL_SCHEME = KAKAO.scheme`;`urlScheme = KAKAO.scheme`;写入 Kakao 查询 schemes |
|
|
478
|
+
| `TiktokSignin` | `TiktokSignin` | `TIKTOK` | 登录 | `TIKTOK.clientId`, `TIKTOK.secret`, `TIKTOK.redirect` | `Info.plist` 写 `TikTokClientKey`;`pluginParams.CLIENT_KEY/CLIENT_SECRET/REDIRECT_URL`;`urlScheme = TIKTOK.redirect`;写入 TikTok 查询 schemes |
|
|
479
|
+
| `IAPPay` | `IAPPay` | `IAPPAY` | 支付 | 无 | 复制 `TOPIAPPayPlugin.framework`;注册到 `TOPSDK.Plugins` |
|
|
480
|
+
| `UI` | `UI` | `UI` | UI | 无 | 复制 `TOPUIPlugin.framework`;注册到 `TOPSDK.Plugins` |
|
|
481
|
+
| `AppsFlyerManager` | `AppsFlyerManager` | `APPSFLYER` | data | `APPSFLYER.clientId`, `APPSFLYER.secret` | `Info.plist` 写 `NSAdvertisingAttributionReportEndpoint`;`pluginParams.DEV_KEY = APPSFLYER.secret`;`pluginParams.APPLE_APP_ID = APPSFLYER.clientId`;注册到 `TOPSDK.dataPlugins` |
|
|
482
|
+
| `FirebaseManager` | `FirebaseManager` | `FIREBASE` | data | 无 | 复制 Firebase 相关 frameworks 和 `GoogleService-Info.plist`;注册到 `TOPSDK.dataPlugins` |
|
|
483
|
+
| `AdjustManager` | `AdjustManager` | `ADJUST` | data | `ADJUST.clientId` | `pluginParams.APP_TOKEN = ADJUST.clientId`;注册到 `TOPSDK.dataPlugins` |
|
|
484
|
+
| `FacebookManager` | `FacebookSignin` | `FACEBOOK` | data | `FACEBOOK.clientId`, `FACEBOOK.name`, `FACEBOOK.scheme`, `FACEBOOK.secret` | `Info.plist` 写 `FacebookAppID`、`FacebookDisplayName`、`FacebookClientToken`、`FacebookAutoLogAppEventsEnabled = false`;`urlScheme = FACEBOOK.scheme`;注册到 `TOPSDK.dataPlugins` |
|
|
485
|
+
|
|
486
|
+
`meet-sdk-tool` 迁移实现要求:
|
|
487
|
+
|
|
488
|
+
- 插件是否接入只看 `meetsdk-remote-config.json` 中 `sdkModules` 是否存在对应子键。
|
|
489
|
+
- iOS 阶段会读取 `bundled/ios-sdk/**/plugins/<Plugin>/config.json|config.t.json`,并按旧配置的 `requireConfigs` 做校验。
|
|
490
|
+
- 远端字段会归一化为旧 iOS 插件需要的 key;`downloadSDKConfig` 输出只使用 `DTOChannelAuth` / `ChannelThirdDataPlatform` 原字段名:
|
|
491
|
+
- `login.facebook.clientId -> FACEBOOK.clientId`
|
|
492
|
+
- `login.facebook.scheme -> FACEBOOK.scheme`
|
|
493
|
+
- `login.facebook.secret -> FACEBOOK.secret`
|
|
494
|
+
- `login.facebook.name -> FACEBOOK.name`
|
|
495
|
+
- `login.google.clientId -> GOOGLE.clientId`
|
|
496
|
+
- `login.google.scheme -> GOOGLE.scheme`
|
|
497
|
+
- `analytics.appsflyer.devKey -> APPSFLYER.secret`
|
|
498
|
+
- `analytics.appsflyer.appleAppId -> APPSFLYER.clientId`
|
|
499
|
+
- `analytics.adjust.appCode -> ADJUST.clientId`
|
|
500
|
+
- `analytics.facebookdata.* -> FACEBOOK.*`
|
|
501
|
+
- `infoParams` 支持字符串、布尔值、数组和对象;其中字符串会执行 `{$C...}` 占位符替换。
|
|
502
|
+
- `pluginParams` 会写入 `TOPSDK.Plugins[].params` 或 `TOPSDK.dataPlugins[].params`。
|
|
503
|
+
- `urlScheme` 会写入 `CFBundleURLTypes`;`queriesSchemes` 会写入 `LSApplicationQueriesSchemes`。
|
|
504
|
+
|
|
505
|
+
当前仍需确认或补齐的项:
|
|
506
|
+
|
|
507
|
+
| 项 | 当前状态 | 需要确认/处理 |
|
|
508
|
+
|----|----------|---------------|
|
|
509
|
+
| `FirebaseManager/source/GoogleService-Info.plist` | 当前测试包 `topSDK-ios--V1.6.0.5` 中缺失,但配置声明需要复制 | 完整 SDK 包需要提供该文件;如果改为从 `meetsdk-remote-config.analytics.firebase.firebaseUrl` 下载,需要新增 iOS Firebase 下载步骤 |
|
|
510
|
+
| `FacebookManager/config.t.json` | 目录名是 `FacebookManager`,但 `config.name` 是 `FacebookSignin` | 旧 `checkPlugin()` 严格要求目录名等于 `config.name`;当前 TS 已按 data manager 目录兼容处理,但建议确认最终 SDK 包配置是否会修正 |
|
|
511
|
+
| `discord` / `twitter` | 当前 iOS 包没有 `DiscordSignin` / `TwitterSignin` 插件目录 | `meetsdk-remote-config` 即使返回这些子键,iOS 阶段也只能 warning 跳过,除非后续补插件资源 |
|
|
512
|
+
| `GOOGLE.scheme` | 不能从 `clientId` 可靠推导 | 服务端需返回 `scheme` |
|
|
513
|
+
| `FACEBOOK.name` | 不能从 `clientId` 可靠推导 | 服务端需返回 `name` |
|
|
514
|
+
| `SNAPCHAT.scheme` / `LINE.scheme` / `NAVER.scheme` | 仅当 `redirect` 是非 http(s) URL 时可推导 scheme,否则不可推导 | 服务端最好显式返回 `scheme` |
|
|
515
|
+
| `APPSFLYER.clientId` | 旧配置中表示 Apple App ID,不是 devKey | 服务端需返回 `clientId`、`appleAppId` 或 `appId` |
|
|
516
|
+
|
|
517
|
+
## 7. 模板变量替换
|
|
518
|
+
|
|
519
|
+
入口在 `checkStr(string, config)`。
|
|
520
|
+
|
|
521
|
+
旧工具支持在配置字符串中写:
|
|
522
|
+
|
|
523
|
+
```text
|
|
524
|
+
{$C.GOOGLE.clientId}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
替换规则:
|
|
528
|
+
|
|
529
|
+
1. 只处理字符串类型。
|
|
530
|
+
2. 查找第一个 `{$C` 和第一个 `}`。
|
|
531
|
+
3. 取中间路径,去掉前缀后按 `.` 拆分。
|
|
532
|
+
4. 从 `channelConfig` 中逐级读取值。
|
|
533
|
+
5. 读到 `None` 时替换为空字符串。
|
|
534
|
+
6. 返回替换后的字符串。
|
|
535
|
+
|
|
536
|
+
限制:
|
|
537
|
+
|
|
538
|
+
- 单次调用只替换一个占位符。
|
|
539
|
+
- 如果路径不存在,可能直接抛异常。
|
|
540
|
+
- 不支持默认值、转义、多占位符。
|
|
541
|
+
|
|
542
|
+
TS 迁移时如果追求旧逻辑等价,应先保持单占位符行为;如果要增强,需要单独记录兼容策略。
|
|
543
|
+
|
|
544
|
+
## 8. 选择 Xcode 工程和 target
|
|
545
|
+
|
|
546
|
+
### 8.1 输入 `.xcodeproj`
|
|
547
|
+
|
|
548
|
+
旧工具要求输入 `.xcodeproj` 路径:
|
|
549
|
+
|
|
550
|
+
```python
|
|
551
|
+
getPath(tips="请输入工程(.xcodeproj)文件路径:", end=".xcodeproj")
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
校验:
|
|
555
|
+
|
|
556
|
+
- 输入不能为空。
|
|
557
|
+
- 路径必须存在。
|
|
558
|
+
- 必须以 `.xcodeproj` 结尾。
|
|
559
|
+
|
|
560
|
+
### 8.2 读取 target
|
|
561
|
+
|
|
562
|
+
`XcodeManager(projPath)` 加载:
|
|
563
|
+
|
|
564
|
+
```text
|
|
565
|
+
<project>.xcodeproj/project.pbxproj
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
再通过 `getNativeTarget()` 读取所有 `PBXNativeTarget`。
|
|
569
|
+
|
|
570
|
+
### 8.3 选择目标 target
|
|
571
|
+
|
|
572
|
+
`selectTargetAndStartSetting()` 会过滤这些测试 target:
|
|
573
|
+
|
|
574
|
+
```text
|
|
575
|
+
layaboxTests
|
|
576
|
+
layaboxUITests
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
逻辑:
|
|
580
|
+
|
|
581
|
+
1. 过滤后只剩一个 target:自动选中。
|
|
582
|
+
2. 过滤后多个 target:要求用户选择。
|
|
583
|
+
3. 没有可用 target:退出。
|
|
584
|
+
|
|
585
|
+
注意:旧代码在只剩一个有效 target 时写的是 `targetName = targetNames[0]`,不是 `effectiveTargetNames[0]`。如果第一个 target 刚好是被过滤的测试 target,可能选错。TS 迁移时建议修正。
|
|
586
|
+
|
|
587
|
+
## 9. 初始化 XcodeManager
|
|
588
|
+
|
|
589
|
+
`setupProject()` 内部重新创建 `XcodeManager(projectPath)`,并调用:
|
|
590
|
+
|
|
591
|
+
```python
|
|
592
|
+
manager.setTarget(targetName)
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### 9.1 setTarget 做的事情
|
|
596
|
+
|
|
597
|
+
1. 通过 target 名称查找 `PBXNativeTarget`。
|
|
598
|
+
2. 读取 target 的 build configurations。
|
|
599
|
+
3. 计算工程源码根目录 `srcRoot`。
|
|
600
|
+
4. 初始化 `FileManager(projectPath, srcRoot)`。
|
|
601
|
+
5. 从 build settings 中解析 `INFOPLIST_FILE`。
|
|
602
|
+
6. 初始化 `InfoPlistManager(infoPlistPaths)`。
|
|
603
|
+
7. 创建或获取名为 `CopyFiles` 的 `PBXCopyFilesBuildPhase`。
|
|
604
|
+
8. 保存一次工程。
|
|
605
|
+
|
|
606
|
+
### 9.2 srcRoot 计算
|
|
607
|
+
|
|
608
|
+
默认:
|
|
609
|
+
|
|
610
|
+
```text
|
|
611
|
+
srcRoot = dirname(.xcodeproj)
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
如果 pbxproj root object 的 `projectDirPath` 非空,则改用 `projectDirPath`。
|
|
615
|
+
|
|
616
|
+
这个逻辑主要用于兼容部分 Cocos 工程。原生 iOS 迁移时仍应保留,因为它影响资源复制和文件搜索根目录。
|
|
617
|
+
|
|
618
|
+
### 9.3 Info.plist 路径解析
|
|
619
|
+
|
|
620
|
+
从每个 build configuration 的:
|
|
621
|
+
|
|
622
|
+
```text
|
|
623
|
+
INFOPLIST_FILE
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
解析真实路径。
|
|
627
|
+
|
|
628
|
+
处理规则:
|
|
629
|
+
|
|
630
|
+
- 如果包含 `$(SRCROOT)`,替换为 `srcRoot`。
|
|
631
|
+
- 如果已经包含 `srcRoot`,直接使用。
|
|
632
|
+
- 否则拼接:
|
|
633
|
+
|
|
634
|
+
```text
|
|
635
|
+
srcRoot + INFOPLIST_FILE
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
多个 configuration 指向同一个 plist 时会去重。
|
|
639
|
+
|
|
640
|
+
找不到任何 plist 会退出。
|
|
641
|
+
|
|
642
|
+
## 10. 资源复制目录
|
|
643
|
+
|
|
644
|
+
`FileManager` 会在游戏工程源码根目录创建:
|
|
645
|
+
|
|
646
|
+
```text
|
|
647
|
+
<srcRoot>/topSDK/
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
所有 SDK 和插件资源都会先复制到这个目录,再加入 Xcode 工程。
|
|
651
|
+
|
|
652
|
+
复制规则:
|
|
653
|
+
|
|
654
|
+
| 方法 | 行为 |
|
|
655
|
+
|------|------|
|
|
656
|
+
| `copyFramework` | 只接受路径包含 `.framework` 或 `.bundle` 的目录;目标已存在则先删除再复制 |
|
|
657
|
+
| `copyDir` | 复制目录;目标已存在则先删除再复制 |
|
|
658
|
+
| `copyFile` | 复制单文件;目标已存在则先删除再复制 |
|
|
659
|
+
|
|
660
|
+
注意:旧 `copyFramework` 不支持 `.xcframework`。如果配置里出现 `.xcframework`,旧逻辑会打印错误并返回 `None`。TS 迁移时需要明确是否兼容旧行为,还是补齐 `.xcframework` 支持。
|
|
661
|
+
|
|
662
|
+
## 11. SDK 核心接入流程
|
|
663
|
+
|
|
664
|
+
`setupProject()` 中,如果 `sdkConfig is not None`,会遍历全局 `sdkConfigs` 调用 `setPlugin()`。
|
|
665
|
+
|
|
666
|
+
默认执行的 `performSettings`:
|
|
667
|
+
|
|
668
|
+
```python
|
|
669
|
+
[
|
|
670
|
+
"sources",
|
|
671
|
+
"frameworks",
|
|
672
|
+
"libs",
|
|
673
|
+
"buildSettings",
|
|
674
|
+
"OtherLinkerFlags",
|
|
675
|
+
"queriesSchemes",
|
|
676
|
+
"infoParams",
|
|
677
|
+
"urlScheme"
|
|
678
|
+
]
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
SDK 核心配置的 `type == 0`,资源根目录使用:
|
|
682
|
+
|
|
683
|
+
```text
|
|
684
|
+
sdk/source/
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
## 12. 插件接入流程
|
|
688
|
+
|
|
689
|
+
`setupProject()` 接着遍历 `pluginConfigs`:
|
|
690
|
+
|
|
691
|
+
1. 调用 `setPlugin(pluginConfig, manager, channelConfig, performSettings, engineType, engineVersion)` 完成资源和工程配置。
|
|
692
|
+
2. 如果插件名是 `AppleSignin`,标记 `hasAppleSignIn = True`。
|
|
693
|
+
3. 构造写入 Info.plist 的插件注册信息:
|
|
694
|
+
|
|
695
|
+
```json
|
|
696
|
+
{
|
|
697
|
+
"name": "PluginName",
|
|
698
|
+
"params": {}
|
|
699
|
+
}
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
4. 如果服务端返回了该插件 `key` 对应的配置,并且插件配置里有 `pluginParams`,则对每个参数执行 `checkStr()` 替换。
|
|
703
|
+
5. `type == 4` 的插件放入 `dataPluginsInfo`。
|
|
704
|
+
6. 其他插件放入 `pluginsInfo`。
|
|
705
|
+
|
|
706
|
+
## 13. setPlugin 详细行为
|
|
707
|
+
|
|
708
|
+
`setPlugin()` 是旧工具资源和配置接入的核心方法。
|
|
709
|
+
|
|
710
|
+
### 13.1 资源根目录
|
|
711
|
+
|
|
712
|
+
普通插件:
|
|
713
|
+
|
|
714
|
+
```text
|
|
715
|
+
plugins/<PluginName>/source/
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
SDK 核心:
|
|
719
|
+
|
|
720
|
+
```text
|
|
721
|
+
sdk/source/
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### 13.2 frameworks
|
|
725
|
+
|
|
726
|
+
仅当 `performSettings` 包含 `"frameworks"` 时执行。
|
|
727
|
+
|
|
728
|
+
对每个 `framework`:
|
|
729
|
+
|
|
730
|
+
#### 非系统 framework
|
|
731
|
+
|
|
732
|
+
路径:
|
|
733
|
+
|
|
734
|
+
```text
|
|
735
|
+
<sourcePath>/<framework.name>
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
普通原生 iOS 逻辑:
|
|
739
|
+
|
|
740
|
+
1. 调用 `manager.addThirdFramework(path, embed=framework.embed)`。
|
|
741
|
+
2. 如果 `framework.copyFile == True`,再调用 `manager.addCopyFramework(framework.name)`。
|
|
742
|
+
|
|
743
|
+
`addThirdFramework()` 行为:
|
|
744
|
+
|
|
745
|
+
1. 按文件名查找工程中是否已存在。
|
|
746
|
+
2. 不存在时:
|
|
747
|
+
- 复制到 `<srcRoot>/topSDK/`。
|
|
748
|
+
- 加入 Xcode `Frameworks` group。
|
|
749
|
+
- 使用 `SOURCE_ROOT` 引用。
|
|
750
|
+
- `weak=True`。
|
|
751
|
+
- `code_sign_on_copy=True`。
|
|
752
|
+
3. 如果 `embed=True`:
|
|
753
|
+
- 创建或获取 `Embed Frameworks` phase。
|
|
754
|
+
- 如果 phase 中不存在该 framework,则添加 build file。
|
|
755
|
+
|
|
756
|
+
#### 系统 framework
|
|
757
|
+
|
|
758
|
+
调用:
|
|
759
|
+
|
|
760
|
+
```python
|
|
761
|
+
manager.addSystemFramework(framework.name)
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
行为:
|
|
765
|
+
|
|
766
|
+
1. 从 `System/Library/Frameworks/<frameworkName>` 添加。
|
|
767
|
+
2. 如果工程中已有同名系统 framework,先移除再添加。
|
|
768
|
+
|
|
769
|
+
### 13.3 libs
|
|
770
|
+
|
|
771
|
+
仅当 `performSettings` 包含 `"libs"` 时执行。
|
|
772
|
+
|
|
773
|
+
#### 非系统 lib
|
|
774
|
+
|
|
775
|
+
路径:
|
|
776
|
+
|
|
777
|
+
```text
|
|
778
|
+
<sourcePath>/<lib.name>
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
调用 `manager.addFile(path)`:
|
|
782
|
+
|
|
783
|
+
- 已存在同名文件引用时先移除。
|
|
784
|
+
- 复制到 `<srcRoot>/topSDK/`。
|
|
785
|
+
- 添加到 Xcode 工程。
|
|
786
|
+
|
|
787
|
+
#### 系统 lib
|
|
788
|
+
|
|
789
|
+
调用:
|
|
790
|
+
|
|
791
|
+
```python
|
|
792
|
+
manager.addSystemLib(lib.name)
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
从:
|
|
796
|
+
|
|
797
|
+
```text
|
|
798
|
+
usr/lib/<libName>
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
添加。
|
|
802
|
+
|
|
803
|
+
### 13.4 sources
|
|
804
|
+
|
|
805
|
+
仅当 `performSettings` 包含 `"sources"` 时执行。
|
|
806
|
+
|
|
807
|
+
对每个 `source`:
|
|
808
|
+
|
|
809
|
+
```text
|
|
810
|
+
<sourcePath>/<source>
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
判断规则:
|
|
814
|
+
|
|
815
|
+
- 如果是目录,且不是 `.bundle`、`.framework`、`.xcdatamodeld`,调用 `manager.addDir(path)`。
|
|
816
|
+
- 否则调用 `manager.addFile(path)`。
|
|
817
|
+
|
|
818
|
+
`addDir()` 行为:
|
|
819
|
+
|
|
820
|
+
1. 整个目录复制到 `<srcRoot>/topSDK/<dirname>`。
|
|
821
|
+
2. 创建或获取同名 group。
|
|
822
|
+
3. 遍历复制后的目录。
|
|
823
|
+
4. 跳过 `.bundle` 和 `.framework` 内部文件。
|
|
824
|
+
5. 添加这些文件类型:
|
|
825
|
+
- `.h`
|
|
826
|
+
- `.m`
|
|
827
|
+
- `.mm`
|
|
828
|
+
- `.plist`
|
|
829
|
+
- `.a`
|
|
830
|
+
6. 遇到 `.bundle` 目录时,作为资源整体加入工程。
|
|
831
|
+
|
|
832
|
+
`addFile()` 行为:
|
|
833
|
+
|
|
834
|
+
- 普通文件:复制到 `topSDK/` 后加入工程。
|
|
835
|
+
- `.bundle` / `.xcdatamodeld` 目录:复制目录后作为文件引用加入工程。
|
|
836
|
+
|
|
837
|
+
### 13.5 buildSettings
|
|
838
|
+
|
|
839
|
+
仅当 `performSettings` 包含 `"buildSettings"` 时执行。
|
|
840
|
+
|
|
841
|
+
对 `config.buildSettings` 中每个 key:
|
|
842
|
+
|
|
843
|
+
```python
|
|
844
|
+
manager.setBuildSetting(key, value)
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
会写入当前 target 的所有 build configurations。
|
|
848
|
+
|
|
849
|
+
### 13.6 OtherLinkerFlags
|
|
850
|
+
|
|
851
|
+
仅当 `performSettings` 包含 `"OtherLinkerFlags"` 时执行。
|
|
852
|
+
|
|
853
|
+
调用:
|
|
854
|
+
|
|
855
|
+
```python
|
|
856
|
+
manager.addOtherLinkFlag(flag)
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
处理规则:
|
|
860
|
+
|
|
861
|
+
- 如果 `OTHER_LDFLAGS` 是字符串:不存在该 flag 时拼接到字符串末尾。
|
|
862
|
+
- 如果是数组:不存在该 flag 时 append。
|
|
863
|
+
- 如果不存在或类型异常:设置为 `[flag]`。
|
|
864
|
+
|
|
865
|
+
### 13.7 queriesSchemes
|
|
866
|
+
|
|
867
|
+
仅当 `performSettings` 包含 `"queriesSchemes"` 时执行。
|
|
868
|
+
|
|
869
|
+
调用:
|
|
870
|
+
|
|
871
|
+
```python
|
|
872
|
+
manager.addQueriesScheme(scheme)
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
写入 `Info.plist` 的:
|
|
876
|
+
|
|
877
|
+
```text
|
|
878
|
+
LSApplicationQueriesSchemes
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
已存在则跳过。
|
|
882
|
+
|
|
883
|
+
### 13.8 infoParams
|
|
884
|
+
|
|
885
|
+
仅当 `performSettings` 包含 `"infoParams"` 时执行。
|
|
886
|
+
|
|
887
|
+
对 `config.infoParams` 中每个 key:
|
|
888
|
+
|
|
889
|
+
1. 对 value 执行 `checkStr(value, channelConfig)`。
|
|
890
|
+
2. 写入 `Info.plist` 顶层:
|
|
891
|
+
|
|
892
|
+
```python
|
|
893
|
+
plist[key] = value
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
如果已有同名 key,会直接覆盖。
|
|
897
|
+
|
|
898
|
+
对 `FacebookSignin` 来说,`infoParams` 中的:
|
|
899
|
+
|
|
900
|
+
```json
|
|
901
|
+
{
|
|
902
|
+
"FacebookDisplayName": "{$C.FACEBOOK.name}"
|
|
903
|
+
}
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
会通过 `checkStr()` 读取 `channelConfig["FACEBOOK"]["name"]`,然后写入:
|
|
907
|
+
|
|
908
|
+
```text
|
|
909
|
+
Info.plist -> FacebookDisplayName
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
因此 `FACEBOOK.name` 缺失时,旧工具会在 `requireConfigs` 阶段失败;如果绕过校验,`checkStr()` 在路径不存在时可能直接抛异常。
|
|
913
|
+
|
|
914
|
+
### 13.9 urlScheme
|
|
915
|
+
|
|
916
|
+
仅当 `performSettings` 包含 `"urlScheme"` 时执行。
|
|
917
|
+
|
|
918
|
+
处理规则:
|
|
919
|
+
|
|
920
|
+
1. 对 `config.urlScheme` 执行 `checkStr()`。
|
|
921
|
+
2. 如果结果以 `://` 结尾,移除 `://`。
|
|
922
|
+
3. 调用 `manager.addUrlScheme(urlScheme)`。
|
|
923
|
+
|
|
924
|
+
写入 `Info.plist`:
|
|
925
|
+
|
|
926
|
+
```text
|
|
927
|
+
CFBundleURLTypes[]
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
格式:
|
|
931
|
+
|
|
932
|
+
```json
|
|
933
|
+
{
|
|
934
|
+
"CFBundleTypeRole": "Editor",
|
|
935
|
+
"CFBundleURLSchemes": ["scheme"]
|
|
936
|
+
}
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
已存在同名 scheme 时跳过。
|
|
940
|
+
|
|
941
|
+
对 `GoogleSignin` 来说,`urlScheme` 为:
|
|
942
|
+
|
|
943
|
+
```text
|
|
944
|
+
{$C.GOOGLE.scheme}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
会通过 `checkStr()` 读取 `channelConfig["GOOGLE"]["scheme"]`,然后写入 `CFBundleURLTypes`。同时同一个值还会通过 `pluginParams.REVERSED_CLIENT_ID` 写入 `TOPSDK -> Plugins[] -> params`。
|
|
948
|
+
|
|
949
|
+
### 13.10 保存
|
|
950
|
+
|
|
951
|
+
`setPlugin()` 末尾会调用:
|
|
952
|
+
|
|
953
|
+
```python
|
|
954
|
+
manager.save()
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
保存:
|
|
958
|
+
|
|
959
|
+
- `.xcodeproj/project.pbxproj`
|
|
960
|
+
- 所有关联 `Info.plist`
|
|
961
|
+
|
|
962
|
+
## 14. TOPSDK 插件注册信息
|
|
963
|
+
|
|
964
|
+
插件遍历完成后,如果 `performSettings` 包含 `"infoParams"`,旧工具会写入:
|
|
965
|
+
|
|
966
|
+
```python
|
|
967
|
+
manager.addInfoConfig("TOPSDK", {
|
|
968
|
+
"APP_ID": appId,
|
|
969
|
+
"Plugins": pluginsInfo,
|
|
970
|
+
"dataPlugins": dataPluginsInfo
|
|
971
|
+
})
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
写入位置是 `Info.plist` 顶层 key:
|
|
975
|
+
|
|
976
|
+
```text
|
|
977
|
+
TOPSDK
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
结构:
|
|
981
|
+
|
|
982
|
+
```json
|
|
983
|
+
{
|
|
984
|
+
"APP_ID": "xxx",
|
|
985
|
+
"Plugins": [
|
|
986
|
+
{
|
|
987
|
+
"name": "GoogleSignin",
|
|
988
|
+
"params": {
|
|
989
|
+
"CLIENT_ID": "...",
|
|
990
|
+
"REVERSED_CLIENT_ID": "..."
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
],
|
|
994
|
+
"dataPlugins": [
|
|
995
|
+
{
|
|
996
|
+
"name": "TOPData",
|
|
997
|
+
"params": {}
|
|
998
|
+
}
|
|
999
|
+
]
|
|
1000
|
+
}
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
这里会直接覆盖已有 `TOPSDK` 字段,不做深度合并。
|
|
1004
|
+
|
|
1005
|
+
## 15. Apple Sign In entitlements
|
|
1006
|
+
|
|
1007
|
+
旧工具根据是否接入 `AppleSignin` 插件调用:
|
|
1008
|
+
|
|
1009
|
+
```python
|
|
1010
|
+
manager.openSigninWithApple(hasAppleSignIn)
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
### 15.1 已接入 AppleSignin
|
|
1014
|
+
|
|
1015
|
+
对当前 target 的每个 build configuration:
|
|
1016
|
+
|
|
1017
|
+
1. 读取 `CODE_SIGN_ENTITLEMENTS`。
|
|
1018
|
+
2. 如果为空:
|
|
1019
|
+
- 创建目录:
|
|
1020
|
+
|
|
1021
|
+
```text
|
|
1022
|
+
<srcRoot>/<targetName>/
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
- 设置:
|
|
1026
|
+
|
|
1027
|
+
```text
|
|
1028
|
+
CODE_SIGN_ENTITLEMENTS = <targetName>/<targetName>.entitlements
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
3. 打开或创建 entitlements 文件。
|
|
1032
|
+
4. 写入:
|
|
1033
|
+
|
|
1034
|
+
```json
|
|
1035
|
+
{
|
|
1036
|
+
"com.apple.developer.applesignin": ["Default"]
|
|
1037
|
+
}
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
如果 entitlements 已存在,会保留其他 key,只覆盖 `com.apple.developer.applesignin`。
|
|
1041
|
+
|
|
1042
|
+
### 15.2 未接入 AppleSignin
|
|
1043
|
+
|
|
1044
|
+
如果 `isOpen == False`:
|
|
1045
|
+
|
|
1046
|
+
1. 如果 entitlements 文件存在,删除其中的 `com.apple.developer.applesignin`。
|
|
1047
|
+
2. 如果 entitlements 文件不存在,创建空 plist。
|
|
1048
|
+
3. 然后直接 `return`。
|
|
1049
|
+
|
|
1050
|
+
注意:旧工具每次都会调用该方法。也就是说,如果工程原本手动开启了 Apple Sign In,但本次 SDK 插件列表没有 `AppleSignin`,旧工具可能移除该 entitlement。TS 迁移时需要确认是否继续保持这个副作用。
|
|
1051
|
+
|
|
1052
|
+
## 16. AppDelegate / SceneDelegate 自动注入
|
|
1053
|
+
|
|
1054
|
+
插件和 plist 配置完成后,如果:
|
|
1055
|
+
|
|
1056
|
+
```python
|
|
1057
|
+
executeAppDelegate == True and sdkConfig
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
旧工具会遍历 SDK 核心配置 `sdkConfigs`,读取其中的:
|
|
1061
|
+
|
|
1062
|
+
- `appDelegateCodes`
|
|
1063
|
+
- `sceneDelegateCodes`
|
|
1064
|
+
|
|
1065
|
+
然后自动查找并修改源码文件。
|
|
1066
|
+
|
|
1067
|
+
### 16.1 查找 UIApplicationDelegate
|
|
1068
|
+
|
|
1069
|
+
`manager.findDelegateFile()` 在 `srcRoot` 下递归扫描:
|
|
1070
|
+
|
|
1071
|
+
- `.m`
|
|
1072
|
+
- `.mm`
|
|
1073
|
+
- `.h`
|
|
1074
|
+
|
|
1075
|
+
如果文件内容包含:
|
|
1076
|
+
|
|
1077
|
+
```text
|
|
1078
|
+
UIApplicationDelegate
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
则认为是候选。
|
|
1082
|
+
|
|
1083
|
+
如果命中的是 `.h` 文件,会尝试查找同名 `.m` 或 `.mm`,把实现文件加入候选列表。
|
|
1084
|
+
|
|
1085
|
+
之后会排除这些文件:
|
|
1086
|
+
|
|
1087
|
+
```text
|
|
1088
|
+
Unity_iPhone_Tests.m
|
|
1089
|
+
UnityAppController+ViewHandling.mm
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
处理逻辑:
|
|
1093
|
+
|
|
1094
|
+
- 只有一个候选:自动注入。
|
|
1095
|
+
- 多个候选:要求用户选择。
|
|
1096
|
+
- 没有候选:提示参考 wiki 手动接入。
|
|
1097
|
+
|
|
1098
|
+
### 16.2 查找 UIWindowSceneDelegate
|
|
1099
|
+
|
|
1100
|
+
`manager.findSceneDelegateFile()` 在 `srcRoot` 下递归扫描 `.m`、`.mm`、`.h`。
|
|
1101
|
+
|
|
1102
|
+
如果文件内容包含:
|
|
1103
|
+
|
|
1104
|
+
```text
|
|
1105
|
+
UIWindowSceneDelegate
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
则认为是候选。
|
|
1109
|
+
|
|
1110
|
+
`.h` 命中时同样会查找同名 `.m` / `.mm`。
|
|
1111
|
+
|
|
1112
|
+
处理逻辑:
|
|
1113
|
+
|
|
1114
|
+
- 只有一个候选:自动注入。
|
|
1115
|
+
- 多个候选:要求用户选择。
|
|
1116
|
+
- 没有候选:不处理,也不退出。
|
|
1117
|
+
|
|
1118
|
+
### 16.3 代码注入入口
|
|
1119
|
+
|
|
1120
|
+
`addCodes(filePath, codeConfigs)` 对每个 code config:
|
|
1121
|
+
|
|
1122
|
+
- `type == "header"`:调用 `CodeUtils.addHeader(content)`。
|
|
1123
|
+
- 其他类型:调用 `CodeUtils.addCodeToMethod(method, content, addToReturn)`。
|
|
1124
|
+
|
|
1125
|
+
只要有一个 code config 注入失败,最终输出“自动接入失败,请参照在线文档自行接入”。
|
|
1126
|
+
|
|
1127
|
+
## 17. CodeUtils 注入规则
|
|
1128
|
+
|
|
1129
|
+
### 17.1 重复判断
|
|
1130
|
+
|
|
1131
|
+
`checkExisted(code)`:
|
|
1132
|
+
|
|
1133
|
+
1. 读取整个文件。
|
|
1134
|
+
2. 移除所有空格 `" "`。
|
|
1135
|
+
3. 将目标 code 也移除空格。
|
|
1136
|
+
4. 用字符串包含判断是否已存在。
|
|
1137
|
+
|
|
1138
|
+
注意:只移除普通空格,不移除 tab、换行。
|
|
1139
|
+
|
|
1140
|
+
### 17.2 添加 header
|
|
1141
|
+
|
|
1142
|
+
`addHeader(code)`:
|
|
1143
|
+
|
|
1144
|
+
1. 如果代码已存在,直接成功。
|
|
1145
|
+
2. 否则把 code 插入到文件最顶部:
|
|
1146
|
+
|
|
1147
|
+
```text
|
|
1148
|
+
<code>
|
|
1149
|
+
<原文件内容>
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
### 17.3 添加方法代码
|
|
1153
|
+
|
|
1154
|
+
`addCodeToMethod(method, code, addToReturn=False)`:
|
|
1155
|
+
|
|
1156
|
+
前置处理:
|
|
1157
|
+
|
|
1158
|
+
- 如果目标 code 已存在,直接成功。
|
|
1159
|
+
- 删除 `code` 中所有分号 `;`。
|
|
1160
|
+
- 删除 `method` 中的 `{` 和 `}`。
|
|
1161
|
+
|
|
1162
|
+
#### 方法已存在,且 `addToReturn == False`
|
|
1163
|
+
|
|
1164
|
+
1. 找到包含 method 的行。
|
|
1165
|
+
2. 从该位置开始,找到第一个 `{`。
|
|
1166
|
+
3. 在 `{` 后插入:
|
|
1167
|
+
|
|
1168
|
+
```objc
|
|
1169
|
+
<code>;
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
#### 方法已存在,且 `addToReturn == True`
|
|
1173
|
+
|
|
1174
|
+
1. 找到包含 method 的行。
|
|
1175
|
+
2. 从该位置开始,找到第一行包含 `return` 的代码。
|
|
1176
|
+
3. 如果原 return 是:
|
|
1177
|
+
|
|
1178
|
+
```objc
|
|
1179
|
+
return YES;
|
|
1180
|
+
return NO;
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
则替换为:
|
|
1184
|
+
|
|
1185
|
+
```objc
|
|
1186
|
+
return <code>;
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
4. 否则取原 return 表达式,改为:
|
|
1190
|
+
|
|
1191
|
+
```objc
|
|
1192
|
+
return (<原return表达式> && <code>);
|
|
1193
|
+
```
|
|
1194
|
+
|
|
1195
|
+
#### 方法不存在
|
|
1196
|
+
|
|
1197
|
+
1. 找到 `@implementation`。
|
|
1198
|
+
2. 在后续第一个 `@end` 前插入完整方法:
|
|
1199
|
+
|
|
1200
|
+
```objc
|
|
1201
|
+
<method> {
|
|
1202
|
+
<code>;
|
|
1203
|
+
}
|
|
1204
|
+
@end
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
如果 `addToReturn == True`,方法体为:
|
|
1208
|
+
|
|
1209
|
+
```objc
|
|
1210
|
+
return <code>;
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
### 17.4 注入限制
|
|
1214
|
+
|
|
1215
|
+
旧实现是纯文本插入,没有 Objective-C AST:
|
|
1216
|
+
|
|
1217
|
+
- 不理解注释、宏、多行方法签名等复杂情况。
|
|
1218
|
+
- 方法匹配依赖字符串包含。
|
|
1219
|
+
- `return` 替换只找方法后的第一行 `return`。
|
|
1220
|
+
- 只处理 Objective-C / Objective-C++,不处理 Swift AppDelegate。
|
|
1221
|
+
|
|
1222
|
+
TS 迁移时如果保持等价,可以先复刻文本策略;如果提升可靠性,应把差异写入迁移说明,并补 golden diff。
|
|
1223
|
+
|
|
1224
|
+
## 18. 幂等性和覆盖行为
|
|
1225
|
+
|
|
1226
|
+
旧工具具备部分幂等能力,但不是所有操作都安全。
|
|
1227
|
+
|
|
1228
|
+
| 操作 | 旧工具行为 |
|
|
1229
|
+
|------|------------|
|
|
1230
|
+
| 复制到 `topSDK/` | 目标已存在则删除后重新复制 |
|
|
1231
|
+
| 普通文件加入工程 | 已有同名引用时先移除再添加 |
|
|
1232
|
+
| system framework / lib | 已有同名引用时先移除再添加 |
|
|
1233
|
+
| third framework | 已有同名 framework 时跳过复制和添加 |
|
|
1234
|
+
| embed framework | phase 中已有同名项时跳过 |
|
|
1235
|
+
| CopyFiles framework | phase 中已有同名项时跳过 |
|
|
1236
|
+
| `LSApplicationQueriesSchemes` | 已存在 scheme 时跳过 |
|
|
1237
|
+
| `CFBundleURLTypes` | 已存在 scheme 时跳过 |
|
|
1238
|
+
| `OTHER_LDFLAGS` | 已存在 flag 时跳过 |
|
|
1239
|
+
| `Info.plist` 普通 key | 直接覆盖 |
|
|
1240
|
+
| `TOPSDK` | 直接覆盖整个字典 |
|
|
1241
|
+
| header / method code | 通过去空格字符串包含判断,已存在则跳过 |
|
|
1242
|
+
| Apple Sign In entitlement | 有插件则写入;无插件可能删除 |
|
|
1243
|
+
|
|
1244
|
+
TS 迁移验收时要重点验证重复执行:
|
|
1245
|
+
|
|
1246
|
+
- 不重复添加 framework。
|
|
1247
|
+
- 不重复添加 URL Scheme。
|
|
1248
|
+
- 不重复添加 Queries Schemes。
|
|
1249
|
+
- 不重复添加 linker flags。
|
|
1250
|
+
- 不重复注入 Delegate 代码。
|
|
1251
|
+
- `TOPSDK` 字段被稳定更新,不产生重复插件项。
|
|
1252
|
+
|
|
1253
|
+
## 19. 原生 iOS 完整执行顺序
|
|
1254
|
+
|
|
1255
|
+
下面是旧工具在选择 `ios` 后的实际主流程。
|
|
1256
|
+
|
|
1257
|
+
1. 计算 `rootPath`。
|
|
1258
|
+
2. 设置:
|
|
1259
|
+
|
|
1260
|
+
```text
|
|
1261
|
+
sdkPath = <rootPath>/sdk
|
|
1262
|
+
pluginsPath = <rootPath>/plugins
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
3. 读取 `sdk/*.json`,生成 `sdkConfigs`。
|
|
1266
|
+
4. 读取 `plugins/*/config.json`,生成 `pluginConfigs`。
|
|
1267
|
+
5. 根据插件 `requireConfigs` 判断是否需要请求服务端。
|
|
1268
|
+
6. 如需要,输入 `appId`、`appSecret`。
|
|
1269
|
+
7. 请求 `/console/openSDK/getSDKConfig`。
|
|
1270
|
+
8. 校验 `requireConfigs` 是否全部返回。
|
|
1271
|
+
9. 选择游戏引擎,原生 iOS 选择 `ios`。
|
|
1272
|
+
10. 输入 `.xcodeproj` 路径。
|
|
1273
|
+
11. 检查 `sdk/` 和 `plugins/` 资源完整性。
|
|
1274
|
+
12. `checkEngineSource("ios", None)` 直接返回 `True`。
|
|
1275
|
+
13. 加载 `.xcodeproj/project.pbxproj`。
|
|
1276
|
+
14. 读取所有 `PBXNativeTarget`。
|
|
1277
|
+
15. 过滤测试 target。
|
|
1278
|
+
16. 自动选择唯一 target,或由用户选择 target。
|
|
1279
|
+
17. 调用 `setupProject()`。
|
|
1280
|
+
18. `XcodeManager.setTarget()`:
|
|
1281
|
+
- 读取 build configurations。
|
|
1282
|
+
- 解析 `srcRoot`。
|
|
1283
|
+
- 创建 `topSDK/`。
|
|
1284
|
+
- 解析 Info.plist。
|
|
1285
|
+
- 创建 CopyFiles phase。
|
|
1286
|
+
19. 遍历 `sdkConfigs`,调用 `setPlugin()` 接入 SDK 核心。
|
|
1287
|
+
20. 遍历 `pluginConfigs`,调用 `setPlugin()` 接入插件。
|
|
1288
|
+
21. 根据插件生成 `pluginsInfo` / `dataPluginsInfo`。
|
|
1289
|
+
22. 根据是否存在 `AppleSignin` 修改 entitlements。
|
|
1290
|
+
23. 写入 `Info.plist` 顶层 `TOPSDK`。
|
|
1291
|
+
24. 保存 Xcode 工程和 Info.plist。
|
|
1292
|
+
25. 查找 AppDelegate 文件。
|
|
1293
|
+
26. 根据 `sdkConfigs.appDelegateCodes` 注入 import / 方法代码。
|
|
1294
|
+
27. 查找 SceneDelegate 文件。
|
|
1295
|
+
28. 根据 `sdkConfigs.sceneDelegateCodes` 注入方法代码。
|
|
1296
|
+
29. 输出完成或失败提示。
|
|
1297
|
+
|
|
1298
|
+
## 20. TS 迁移建议
|
|
1299
|
+
|
|
1300
|
+
为了在 `meet-sdk-tool` 中实现等价能力,建议拆成这些模块:
|
|
1301
|
+
|
|
1302
|
+
| TS 模块 | 对应旧逻辑 |
|
|
1303
|
+
|---------|------------|
|
|
1304
|
+
| `sdkBundle` | 解析 bundled iOS SDK 包,定位 `sdk/`、`plugins/` |
|
|
1305
|
+
| `pluginConfig` | 解析旧 `config.json` / 新 `config.t.json` |
|
|
1306
|
+
| `remoteConfig` | 请求 `downloadSDKConfig` 或兼容旧 `getSDKConfig` |
|
|
1307
|
+
| `templateResolver` | 实现 `{$C.xxx}` 参数替换 |
|
|
1308
|
+
| `pbxprojEditor` | 修改 target、build settings、frameworks、libs、build phases |
|
|
1309
|
+
| `fileManager` | 复制资源到 `<projectRoot>/topSDK/` |
|
|
1310
|
+
| `infoPlist` | 写入普通字段、`TOPSDK`、URL Scheme、Queries Schemes |
|
|
1311
|
+
| `entitlements` | 创建 / 修改 Apple Sign In capability |
|
|
1312
|
+
| `delegateInjector` | 查找并修改 AppDelegate / SceneDelegate |
|
|
1313
|
+
| `iosIntegrator` | 编排完整流程 |
|
|
1314
|
+
|
|
1315
|
+
实现时建议优先做这些等价约束:
|
|
1316
|
+
|
|
1317
|
+
1. 固定输入,不依赖实时后台接口做单元测试。
|
|
1318
|
+
2. 同一份 sample 工程分别跑旧 Python 和新 TS,比较 golden output。
|
|
1319
|
+
3. 重复执行两次,确认不重复插入。
|
|
1320
|
+
4. 缺少资源、缺少 Info.plist、多 target、多 Delegate 时给明确错误。
|
|
1321
|
+
5. 保留旧工具输出目录 `topSDK/`,避免接入文档和 CP 预期变化。
|
|
1322
|
+
6. 对 `.xcframework` 做明确决策:要么兼容旧工具不支持,要么新增支持并写入差异说明。
|
|
1323
|
+
7. Apple Sign In 无插件时是否删除 entitlement,需要业务确认;不建议默认删除用户已有能力。
|
|
1324
|
+
|
|
1325
|
+
## 21. 与现有 meet-sdk-tool 的迁移关系
|
|
1326
|
+
|
|
1327
|
+
当前 `meet-sdk-tool` 中已有 iOS MVP 实现,但不能简单认为等价于旧 Python 工具。迁移时应以本文档和 `ios-topsdk-tool-feature-test-plan.md` 为基准逐项对齐。
|
|
1328
|
+
|
|
1329
|
+
最低完成标准:
|
|
1330
|
+
|
|
1331
|
+
1. 同一输入下,Python 工具和 TS 工具产物语义等价。
|
|
1332
|
+
2. `.xcodeproj` 中 framework / lib / source / build setting / build phase 等修改一致。
|
|
1333
|
+
3. `Info.plist` 中 `TOPSDK`、URL Scheme、Queries Schemes、插件参数一致。
|
|
1334
|
+
4. Delegate / SceneDelegate 注入结果一致或有明确差异说明。
|
|
1335
|
+
5. 重复执行不会重复插入 framework、plist、code。
|
|
1336
|
+
6. 缺少配置或资源时,TS 工具能给出明确错误,而不是生成半成品工程。
|
|
1337
|
+
|
|
1338
|
+
---
|
|
1339
|
+
|
|
1340
|
+
## 功能点与测试方法
|
|
1341
|
+
|
|
1342
|
+
本文档用于迁移 `topsdk-tool-ios` 到 `meet-sdk-tool` 前的行为梳理。范围只覆盖:
|
|
1343
|
+
|
|
1344
|
+
- 下载 TOPSDK 包后的本地资源要求与校验
|
|
1345
|
+
- 将 TOPSDK 接入 iOS 原生 `.xcodeproj`
|
|
1346
|
+
|
|
1347
|
+
明确不覆盖:
|
|
1348
|
+
|
|
1349
|
+
- Unity / Cocos Creator / LayaNative 等非 iOS 原生工程接入
|
|
1350
|
+
- `upload.py` 资源上传到下载页
|
|
1351
|
+
- `update.py` 将编译产物更新回 TOPSDK 资源目录
|
|
1352
|
+
|
|
1353
|
+
## 1. 旧工具入口与范围
|
|
1354
|
+
|
|
1355
|
+
旧工具主入口是 `topsdk-tool-ios/TopSDKTool.py`。
|
|
1356
|
+
|
|
1357
|
+
运行时默认用 `sys.argv[0]` 所在目录作为 TOPSDK 包根目录,并要求包内存在:
|
|
1358
|
+
|
|
1359
|
+
```text
|
|
1360
|
+
<topsdk-package>/
|
|
1361
|
+
sdk/
|
|
1362
|
+
*.json
|
|
1363
|
+
source/
|
|
1364
|
+
plugins/
|
|
1365
|
+
<PluginName>/
|
|
1366
|
+
config.json
|
|
1367
|
+
source/
|
|
1368
|
+
```
|
|
1369
|
+
|
|
1370
|
+
`currentEnv != ENV.prod` 时,旧代码会把 `rootPath` 强制写死为开发者本机路径 `/Users/lvyunjie/Downloads/topSDK-ios--V1.6.0.2`。迁移时不应保留这个本机路径行为。
|
|
1371
|
+
|
|
1372
|
+
iOS 原生工程接入分支位于:
|
|
1373
|
+
|
|
1374
|
+
```text
|
|
1375
|
+
TopSDKTool.py
|
|
1376
|
+
__main__
|
|
1377
|
+
-> engineType == "ios"
|
|
1378
|
+
-> selectTargetAndStartSetting(...)
|
|
1379
|
+
-> setupProject(...)
|
|
1380
|
+
-> setPlugin(...)
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
非原生分支只作为排除项记录,不迁移。
|
|
1384
|
+
|
|
1385
|
+
## 2. 下载 TOPSDK
|
|
1386
|
+
|
|
1387
|
+
### 2.1 旧工具实际行为
|
|
1388
|
+
|
|
1389
|
+
`topsdk-tool-ios` 主工具本身没有实现“从服务端下载 TOPSDK 包”的网络逻辑。它假设用户已经从下载页拿到了一个本地 TOPSDK 包,然后执行:
|
|
1390
|
+
|
|
1391
|
+
1. 读取包内 `sdk/` 目录下的 SDK 配置 JSON。
|
|
1392
|
+
2. 读取包内 `plugins/*/config.json`。
|
|
1393
|
+
3. 校验 `sdk/` 和 `plugins/` 资源完整性。
|
|
1394
|
+
4. 使用这些本地资源修改目标 Xcode 工程。
|
|
1395
|
+
|
|
1396
|
+
与“下载页”相关的脚本是 `upload.py`,它负责把 `TopSDK` 目录内资源打包并上传到下载页;这属于资源发布流程,不属于接入工具运行时能力,本次不迁移。
|
|
1397
|
+
|
|
1398
|
+
### 2.2 资源完整性校验
|
|
1399
|
+
|
|
1400
|
+
旧代码位置:
|
|
1401
|
+
|
|
1402
|
+
- `TopSDKTool.py::checkEnv`
|
|
1403
|
+
- `TopSDKTool.py::checkPlugin`
|
|
1404
|
+
- `PluginConfig.py::PluginConfig`
|
|
1405
|
+
|
|
1406
|
+
校验规则:
|
|
1407
|
+
|
|
1408
|
+
| 功能点 | 旧行为 | 测试方法 |
|
|
1409
|
+
|---|---|---|
|
|
1410
|
+
| `sdk/` 存在性 | `sdkPath` 不存在时打印 `error: sdk目录不存在`,返回 `False` | 构造缺少 `sdk/` 的 TOPSDK 包,断言迁移工具失败且错误信息明确 |
|
|
1411
|
+
| `plugins/` 存在性 | 不存在或为空时只打印 warning,不中断 | 构造只有 `sdk/`、无 `plugins/` 的包,断言可继续接入核心 SDK |
|
|
1412
|
+
| 插件 `config.json` 存在性 | 插件目录缺配置时认为插件异常 | 构造缺少 `plugins/GoogleSignin/config.json` 的包,断言报告具体插件名 |
|
|
1413
|
+
| 插件名一致性 | `config.name` 必须等于插件目录名 | 构造目录名与 `config.name` 不一致,断言失败 |
|
|
1414
|
+
| `sources` 资源存在性 | `config.sources` 中每一项必须存在于 `source/` | 删除一个 source 文件/目录,断言失败并指出缺失资源 |
|
|
1415
|
+
| 非系统 framework 存在性 | `framework.system == false` 时,`source/<framework.name>` 必须存在 | 删除一个三方 framework,断言失败 |
|
|
1416
|
+
| 非系统 lib 存在性 | `lib.system == false` 时,`source/<lib.name>` 必须存在 | 删除一个三方 lib,断言失败 |
|
|
1417
|
+
| JSON 格式 | `PluginConfig` 解析失败直接退出 | 提供非法 JSON,断言失败且错误可读 |
|
|
1418
|
+
|
|
1419
|
+
### 2.3 在线参数拉取
|
|
1420
|
+
|
|
1421
|
+
旧工具会根据插件配置中的 `requireConfigs` 判断是否需要在线拉参数。这里拉取的是“渠道配置”,不是 SDK 包下载。
|
|
1422
|
+
|
|
1423
|
+
旧代码位置:
|
|
1424
|
+
|
|
1425
|
+
- `TopSDKTool.py::getOnlineConfig`
|
|
1426
|
+
- `ChannelConfigManager.py::getSdkConfig`
|
|
1427
|
+
|
|
1428
|
+
旧接口:
|
|
1429
|
+
|
|
1430
|
+
```text
|
|
1431
|
+
GET {baseUrl}/console/openSDK/getSDKConfig
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
请求参数:
|
|
1435
|
+
|
|
1436
|
+
```text
|
|
1437
|
+
appId
|
|
1438
|
+
authType[]
|
|
1439
|
+
channelType=apple
|
|
1440
|
+
sign=base64(md5(appId + appSecret + timestamp))
|
|
1441
|
+
timestamp
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
特殊处理:
|
|
1445
|
+
|
|
1446
|
+
- `GUEST`、`UI`、`IAPPAY` 会从 `authType` 中移除。
|
|
1447
|
+
- `MESSENGER` 会映射为 `FACEBOOK`,并设置 `openMessenger = "1"`。
|
|
1448
|
+
- `FACEBOOK` 会设置 `openMessenger = "0"`。
|
|
1449
|
+
- 如果缺少 `requireConfigs` 中声明的参数,旧工具会打印缺失项并退出。
|
|
1450
|
+
|
|
1451
|
+
迁移测试方法:
|
|
1452
|
+
|
|
1453
|
+
| 功能点 | 测试方法 |
|
|
1454
|
+
|---|---|
|
|
1455
|
+
| 签名算法 | 固定 `appId/appSecret/timestamp`,断言输出 sign 与 Python `md5_base64_byte` 一致 |
|
|
1456
|
+
| authType 过滤 | 输入 `GUEST/UI/IAPPAY/GOOGLE`,断言请求中只包含需要服务端配置的登录渠道 |
|
|
1457
|
+
| MESSENGER 映射 | mock 返回 `authType=MESSENGER`,断言迁移后的配置归入 `FACEBOOK` 且 `openMessenger=1` |
|
|
1458
|
+
| FACEBOOK 默认值 | mock 返回 `authType=FACEBOOK`,断言 `openMessenger=0` |
|
|
1459
|
+
| 缺配置失败 | 插件 `requireConfigs` 声明 `GOOGLE.clientId`,mock 返回缺失该字段,断言失败并列出缺失参数 |
|
|
1460
|
+
| 无需在线配置 | 所有插件 `requireConfigs` 为空时,不发起网络请求,只要求用户/命令提供 `appId` |
|
|
1461
|
+
|
|
1462
|
+
## 3. iOS 原生工程接入
|
|
1463
|
+
|
|
1464
|
+
### 3.1 输入
|
|
1465
|
+
|
|
1466
|
+
迁移后的命令输入应至少包含:
|
|
1467
|
+
|
|
1468
|
+
```text
|
|
1469
|
+
--project-root <iOS 工程根目录或 .xcodeproj 路径>
|
|
1470
|
+
--app-id <APP_ID>
|
|
1471
|
+
--app-secret <APP_SECRET> # 仅在需要拉在线渠道配置时使用
|
|
1472
|
+
--channel-type APPLE # 或沿用 iOS 固定 apple/APPLE 约定
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
旧工具交互输入:
|
|
1476
|
+
|
|
1477
|
+
- 选择游戏引擎:本次迁移固定为 iOS 原生,不再提供选择。
|
|
1478
|
+
- 输入 `.xcodeproj` 路径:迁移后使用 `--project-root` 检测。
|
|
1479
|
+
- 多 target 时选择打包 App target:迁移后应支持参数或明确报错。
|
|
1480
|
+
- 多 AppDelegate / SceneDelegate 时选择目标文件:迁移后应支持参数或明确报错。
|
|
1481
|
+
|
|
1482
|
+
### 3.2 Target 选择
|
|
1483
|
+
|
|
1484
|
+
旧代码位置:
|
|
1485
|
+
|
|
1486
|
+
- `XcodeManager.py::getNativeTarget`
|
|
1487
|
+
- `TopSDKTool.py::selectTargetAndStartSetting`
|
|
1488
|
+
|
|
1489
|
+
旧行为:
|
|
1490
|
+
|
|
1491
|
+
1. 读取 `project.pbxproj` 中所有 `PBXNativeTarget`。
|
|
1492
|
+
2. 过滤固定测试 target:`layaboxTests`、`layaboxUITests`。
|
|
1493
|
+
3. 有 1 个有效 target 时自动选择。
|
|
1494
|
+
4. 有多个有效 target 时交互选择。
|
|
1495
|
+
5. 没有有效 target 时退出。
|
|
1496
|
+
|
|
1497
|
+
迁移测试方法:
|
|
1498
|
+
|
|
1499
|
+
| 场景 | 断言 |
|
|
1500
|
+
|---|---|
|
|
1501
|
+
| 单 App target | 自动选择该 target 并完成接入 |
|
|
1502
|
+
| 多 App target | 无显式 target 参数时给出明确错误,或按迁移设计进入可配置选择 |
|
|
1503
|
+
| 只有测试 target | 失败并提示没有有效 App target |
|
|
1504
|
+
| 指定不存在 target | 失败并提示 target 不存在 |
|
|
1505
|
+
|
|
1506
|
+
### 3.3 读取 Info.plist
|
|
1507
|
+
|
|
1508
|
+
旧代码位置:
|
|
1509
|
+
|
|
1510
|
+
- `XcodeManager.py::findInfoPlistPath`
|
|
1511
|
+
- `InfoPlistManager.py`
|
|
1512
|
+
|
|
1513
|
+
旧行为:
|
|
1514
|
+
|
|
1515
|
+
1. 从 target 的 build settings 读取 `INFOPLIST_FILE`。
|
|
1516
|
+
2. 支持 `$(SRCROOT)` 替换。
|
|
1517
|
+
3. 同一个 target 的 Debug/Release 可能对应多个 plist,旧工具会全部写入。
|
|
1518
|
+
4. 找不到 Info.plist 时退出。
|
|
1519
|
+
|
|
1520
|
+
迁移测试方法:
|
|
1521
|
+
|
|
1522
|
+
| 场景 | 断言 |
|
|
1523
|
+
|---|---|
|
|
1524
|
+
| `INFOPLIST_FILE` 使用相对路径 | 能解析到真实 plist 并写入 |
|
|
1525
|
+
| `INFOPLIST_FILE` 使用 `$(SRCROOT)` | 能正确替换 |
|
|
1526
|
+
| Debug/Release 使用不同 plist | 两个 plist 都写入相同 SDK 配置 |
|
|
1527
|
+
| plist 不存在或无法解析 | 失败并提示具体路径 |
|
|
1528
|
+
|
|
1529
|
+
### 3.4 复制 SDK 与插件资源
|
|
1530
|
+
|
|
1531
|
+
旧代码位置:
|
|
1532
|
+
|
|
1533
|
+
- `FileManager.py`
|
|
1534
|
+
- `XcodeManager.py::addFile`
|
|
1535
|
+
- `XcodeManager.py::addDir`
|
|
1536
|
+
- `XcodeManager.py::addThirdFramework`
|
|
1537
|
+
|
|
1538
|
+
旧行为:
|
|
1539
|
+
|
|
1540
|
+
1. 在宿主工程根目录创建 `topSDK/`。
|
|
1541
|
+
2. framework / bundle / xcdatamodeld / lib / 源码文件都会复制到 `topSDK/`。
|
|
1542
|
+
3. 同名目录已存在时先删除再复制。
|
|
1543
|
+
4. 同名文件已存在时先删除再复制。
|
|
1544
|
+
5. `addDir` 只把 `.h/.m/.mm/.plist/.a` 和 `.bundle` 加入 Xcode 工程,跳过 `.framework` 和 `.bundle` 内部遍历。
|
|
1545
|
+
|
|
1546
|
+
迁移测试方法:
|
|
1547
|
+
|
|
1548
|
+
| 场景 | 断言 |
|
|
1549
|
+
|---|---|
|
|
1550
|
+
| 首次接入 | 工程根目录生成 `topSDK/`,资源被复制 |
|
|
1551
|
+
| 重复接入 | `topSDK/` 下同名资源被替换,不产生重复文件引用 |
|
|
1552
|
+
| 复制 framework | `project.pbxproj` 中存在 framework 文件引用 |
|
|
1553
|
+
| 复制 bundle | bundle 被复制并加入资源引用 |
|
|
1554
|
+
| 复制 `.xcdatamodeld` | 被复制并加入工程引用 |
|
|
1555
|
+
| 复制源码目录 | 目录内 `.h/.m/.mm/.plist/.a` 被加入工程 |
|
|
1556
|
+
| 缺资源 | 失败并提示缺失资源路径 |
|
|
1557
|
+
|
|
1558
|
+
### 3.5 Framework 接入
|
|
1559
|
+
|
|
1560
|
+
旧代码位置:
|
|
1561
|
+
|
|
1562
|
+
- `TopSDKTool.py::setPlugin`
|
|
1563
|
+
- `XcodeManager.py::addThirdFramework`
|
|
1564
|
+
- `XcodeManager.py::addSystemFramework`
|
|
1565
|
+
- `XcodeManager.py::addCopyFramework`
|
|
1566
|
+
|
|
1567
|
+
配置字段:
|
|
1568
|
+
|
|
1569
|
+
```json
|
|
1570
|
+
{
|
|
1571
|
+
"frameworks": [
|
|
1572
|
+
{
|
|
1573
|
+
"name": "Some.framework",
|
|
1574
|
+
"system": false,
|
|
1575
|
+
"embed": true,
|
|
1576
|
+
"copyFile": true
|
|
1577
|
+
}
|
|
1578
|
+
]
|
|
1579
|
+
}
|
|
1580
|
+
```
|
|
1581
|
+
|
|
1582
|
+
旧行为:
|
|
1583
|
+
|
|
1584
|
+
| 类型 | 行为 |
|
|
1585
|
+
|---|---|
|
|
1586
|
+
| 三方 framework | 从 SDK 包复制到 `topSDK/`,加入 `Frameworks` group |
|
|
1587
|
+
| `embed=true` | 加入 `Embed Frameworks` build phase |
|
|
1588
|
+
| `copyFile=true` | 加入名为 `CopyFiles` 的 `PBXCopyFilesBuildPhase` |
|
|
1589
|
+
| 系统 framework | 以 `SDKROOT/System/Library/Frameworks/<name>` 加入工程 |
|
|
1590
|
+
| 重复 framework | 已存在时避免重复加入 |
|
|
1591
|
+
|
|
1592
|
+
迁移测试方法:
|
|
1593
|
+
|
|
1594
|
+
| 场景 | 断言 |
|
|
1595
|
+
|---|---|
|
|
1596
|
+
| 三方 framework | 文件复制到 `topSDK/`,`pbxproj` 有文件引用 |
|
|
1597
|
+
| embed framework | `Embed Frameworks` phase 中有对应 build file |
|
|
1598
|
+
| copyFile framework | `CopyFiles` phase 中有对应 build file |
|
|
1599
|
+
| 系统 framework | `pbxproj` 中引用 `System/Library/Frameworks/<name>` |
|
|
1600
|
+
| 重复执行 | framework、Embed phase、CopyFiles phase 均不重复 |
|
|
1601
|
+
|
|
1602
|
+
### 3.6 Library 接入
|
|
1603
|
+
|
|
1604
|
+
旧代码位置:
|
|
1605
|
+
|
|
1606
|
+
- `TopSDKTool.py::setPlugin`
|
|
1607
|
+
- `XcodeManager.py::addSystemLib`
|
|
1608
|
+
- `XcodeManager.py::addFile`
|
|
1609
|
+
|
|
1610
|
+
旧行为:
|
|
1611
|
+
|
|
1612
|
+
| 类型 | 行为 |
|
|
1613
|
+
|---|---|
|
|
1614
|
+
| 三方 lib | 从 SDK 包复制到 `topSDK/` 并加入工程 |
|
|
1615
|
+
| 系统 lib | 以 `SDKROOT/usr/lib/<name>` 加入工程 |
|
|
1616
|
+
| 重复 lib | 先移除已有引用,再加入 |
|
|
1617
|
+
|
|
1618
|
+
迁移测试方法:
|
|
1619
|
+
|
|
1620
|
+
| 场景 | 断言 |
|
|
1621
|
+
|---|---|
|
|
1622
|
+
| 三方 `.a` | 文件复制到 `topSDK/`,`pbxproj` 有引用 |
|
|
1623
|
+
| 系统 `libz.tbd` / `libsqlite3.tbd` | `pbxproj` 有 `usr/lib/<name>` 引用 |
|
|
1624
|
+
| 重复执行 | 不产生重复引用 |
|
|
1625
|
+
|
|
1626
|
+
### 3.7 Build Settings
|
|
1627
|
+
|
|
1628
|
+
旧代码位置:
|
|
1629
|
+
|
|
1630
|
+
- `TopSDKTool.py::setPlugin`
|
|
1631
|
+
- `XcodeManager.py::setBuildSetting`
|
|
1632
|
+
|
|
1633
|
+
旧行为:
|
|
1634
|
+
|
|
1635
|
+
`config.buildSettings` 中的每个 key/value 会写入当前 target 的所有 build configurations。
|
|
1636
|
+
|
|
1637
|
+
迁移测试方法:
|
|
1638
|
+
|
|
1639
|
+
| 场景 | 断言 |
|
|
1640
|
+
|---|---|
|
|
1641
|
+
| 设置单个 build setting | Debug/Release 都写入对应值 |
|
|
1642
|
+
| 覆盖已有值 | 旧值被替换为配置值 |
|
|
1643
|
+
| 多插件设置同一 key | 迁移设计需定义优先级;旧工具后执行的插件覆盖前者 |
|
|
1644
|
+
|
|
1645
|
+
### 3.8 Other Linker Flags
|
|
1646
|
+
|
|
1647
|
+
旧代码位置:
|
|
1648
|
+
|
|
1649
|
+
- `TopSDKTool.py::setPlugin`
|
|
1650
|
+
- `XcodeManager.py::addOtherLinkFlag`
|
|
1651
|
+
|
|
1652
|
+
旧行为:
|
|
1653
|
+
|
|
1654
|
+
1. 对所有 build configurations 写入。
|
|
1655
|
+
2. 如果 `OTHER_LDFLAGS` 是字符串,则拼接追加。
|
|
1656
|
+
3. 如果是数组,则 append。
|
|
1657
|
+
4. 已存在相同 flag 时不重复添加。
|
|
1658
|
+
5. 如果原字段不存在或类型异常,则创建数组。
|
|
1659
|
+
|
|
1660
|
+
迁移测试方法:
|
|
1661
|
+
|
|
1662
|
+
| 场景 | 断言 |
|
|
1663
|
+
|---|---|
|
|
1664
|
+
| 原值为字符串 | 追加 flag,不破坏原内容 |
|
|
1665
|
+
| 原值为数组 | append flag |
|
|
1666
|
+
| 原值为空 | 创建 `OTHER_LDFLAGS` |
|
|
1667
|
+
| 重复执行 | flag 不重复 |
|
|
1668
|
+
|
|
1669
|
+
### 3.9 Info.plist 普通参数
|
|
1670
|
+
|
|
1671
|
+
旧代码位置:
|
|
1672
|
+
|
|
1673
|
+
- `TopSDKTool.py::setPlugin`
|
|
1674
|
+
- `InfoPlistManager.py::addParams`
|
|
1675
|
+
|
|
1676
|
+
旧行为:
|
|
1677
|
+
|
|
1678
|
+
1. `config.infoParams` 的 key/value 写入 Info.plist 顶层。
|
|
1679
|
+
2. value 支持 `{$C.xxx.yyy}` 占位符替换。
|
|
1680
|
+
3. 当前 `checkStr` 只处理一个占位符。
|
|
1681
|
+
4. 缺失路径在旧代码中可能抛异常;迁移后应给出明确错误。
|
|
1682
|
+
|
|
1683
|
+
迁移测试方法:
|
|
1684
|
+
|
|
1685
|
+
| 场景 | 断言 |
|
|
1686
|
+
|---|---|
|
|
1687
|
+
| 普通字符串 | plist 顶层写入 key/value |
|
|
1688
|
+
| 字典/数组值 | 保持 plist 结构写入 |
|
|
1689
|
+
| 占位符替换 | `{$C.GOOGLE.clientId}` 替换为在线配置值 |
|
|
1690
|
+
| 缺少占位符数据 | 失败并提示缺少哪个配置路径 |
|
|
1691
|
+
| 重复执行 | 同一 key 被更新,不重复产生结构 |
|
|
1692
|
+
|
|
1693
|
+
### 3.10 URL Scheme
|
|
1694
|
+
|
|
1695
|
+
旧代码位置:
|
|
1696
|
+
|
|
1697
|
+
- `TopSDKTool.py::setPlugin`
|
|
1698
|
+
- `InfoPlistManager.py::addUrlScheme`
|
|
1699
|
+
|
|
1700
|
+
旧行为:
|
|
1701
|
+
|
|
1702
|
+
1. `config.urlScheme` 写入 `CFBundleURLTypes`。
|
|
1703
|
+
2. 支持占位符替换。
|
|
1704
|
+
3. 如果 scheme 以 `://` 结尾,会去掉 `://`,用于兼容 Twitter callback_url。
|
|
1705
|
+
4. 已存在相同 scheme 时不重复添加。
|
|
1706
|
+
|
|
1707
|
+
迁移测试方法:
|
|
1708
|
+
|
|
1709
|
+
| 场景 | 断言 |
|
|
1710
|
+
|---|---|
|
|
1711
|
+
| 普通 scheme | `CFBundleURLTypes` 添加该 scheme |
|
|
1712
|
+
| `scheme://` | 写入时去掉 `://` |
|
|
1713
|
+
| 占位符 scheme | 正确替换为渠道配置值 |
|
|
1714
|
+
| 重复执行 | 不重复添加 |
|
|
1715
|
+
|
|
1716
|
+
### 3.11 LSApplicationQueriesSchemes
|
|
1717
|
+
|
|
1718
|
+
旧代码位置:
|
|
1719
|
+
|
|
1720
|
+
- `TopSDKTool.py::setPlugin`
|
|
1721
|
+
- `InfoPlistManager.py::addQueriesScheme`
|
|
1722
|
+
|
|
1723
|
+
旧行为:
|
|
1724
|
+
|
|
1725
|
+
`config.queriesSchemes` 中每个值写入 `LSApplicationQueriesSchemes`,已存在时不重复添加。
|
|
1726
|
+
|
|
1727
|
+
迁移测试方法:
|
|
1728
|
+
|
|
1729
|
+
| 场景 | 断言 |
|
|
1730
|
+
|---|---|
|
|
1731
|
+
| 添加新 scheme | plist 数组新增 |
|
|
1732
|
+
| 已存在 scheme | 不重复 |
|
|
1733
|
+
| 多插件相同 scheme | 最终只保留一份 |
|
|
1734
|
+
|
|
1735
|
+
### 3.12 TOPSDK 插件注册
|
|
1736
|
+
|
|
1737
|
+
旧代码位置:
|
|
1738
|
+
|
|
1739
|
+
- `TopSDKTool.py::setupProject`
|
|
1740
|
+
|
|
1741
|
+
旧行为:
|
|
1742
|
+
|
|
1743
|
+
接入完所有插件后,在 Info.plist 顶层写入:
|
|
1744
|
+
|
|
1745
|
+
```plist
|
|
1746
|
+
TOPSDK = {
|
|
1747
|
+
APP_ID = <appId>;
|
|
1748
|
+
Plugins = (
|
|
1749
|
+
{
|
|
1750
|
+
name = <PluginName>;
|
|
1751
|
+
params = { ... };
|
|
1752
|
+
}
|
|
1753
|
+
);
|
|
1754
|
+
dataPlugins = (
|
|
1755
|
+
{
|
|
1756
|
+
name = <PluginName>;
|
|
1757
|
+
params = { ... };
|
|
1758
|
+
}
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
```
|
|
1762
|
+
|
|
1763
|
+
分类规则:
|
|
1764
|
+
|
|
1765
|
+
- `pluginConfig.type == 4` 进入 `dataPlugins`
|
|
1766
|
+
- 其它插件进入 `Plugins`
|
|
1767
|
+
|
|
1768
|
+
`params` 规则:
|
|
1769
|
+
|
|
1770
|
+
- 如果 `pluginConfig.key` 存在于在线配置中,则根据 `pluginParams` 模板生成。
|
|
1771
|
+
- `pluginParams` 为 `None` 时写空对象。
|
|
1772
|
+
- 不存在对应在线配置时,只写 `name`,不写 `params`。
|
|
1773
|
+
|
|
1774
|
+
迁移测试方法:
|
|
1775
|
+
|
|
1776
|
+
| 场景 | 断言 |
|
|
1777
|
+
|---|---|
|
|
1778
|
+
| 登录插件 | 出现在 `TOPSDK.Plugins` |
|
|
1779
|
+
| 数据插件 | 出现在 `TOPSDK.dataPlugins` |
|
|
1780
|
+
| 插件参数模板 | `params` 被正确替换 |
|
|
1781
|
+
| 无在线参数 | 插件仍注册 `name` |
|
|
1782
|
+
| 重复执行 | `TOPSDK` 整体被更新,不产生重复插件 |
|
|
1783
|
+
|
|
1784
|
+
### 3.13 Apple Sign In Entitlements
|
|
1785
|
+
|
|
1786
|
+
旧代码位置:
|
|
1787
|
+
|
|
1788
|
+
- `TopSDKTool.py::setupProject`
|
|
1789
|
+
- `XcodeManager.py::openSigninWithApple`
|
|
1790
|
+
|
|
1791
|
+
旧行为:
|
|
1792
|
+
|
|
1793
|
+
1. 如果接入插件名为 `AppleSignin`,则开启 Apple Sign In entitlement。
|
|
1794
|
+
2. 如果 target 没有 `CODE_SIGN_ENTITLEMENTS`,创建 `<targetName>/<targetName>.entitlements`。
|
|
1795
|
+
3. 对所有 build configurations 设置 `CODE_SIGN_ENTITLEMENTS`。
|
|
1796
|
+
4. 在 entitlements plist 中写入:
|
|
1797
|
+
|
|
1798
|
+
```plist
|
|
1799
|
+
com.apple.developer.applesignin = (Default)
|
|
1800
|
+
```
|
|
1801
|
+
|
|
1802
|
+
5. 如果没有 AppleSignin 插件,则旧代码会调用 `openSigninWithApple(False)`,移除已有 `com.apple.developer.applesignin`。
|
|
1803
|
+
|
|
1804
|
+
迁移测试方法:
|
|
1805
|
+
|
|
1806
|
+
| 场景 | 断言 |
|
|
1807
|
+
|---|---|
|
|
1808
|
+
| 有 AppleSignin | entitlements 文件存在并包含 applesignin |
|
|
1809
|
+
| 原来没有 entitlements | 自动创建并写入 build setting |
|
|
1810
|
+
| 原来已有 entitlements | 保留其它 entitlement,只新增 applesignin |
|
|
1811
|
+
| 无 AppleSignin | 按迁移设计决定是否保留旧工具“移除 applesignin”的行为;若保留,则断言被移除 |
|
|
1812
|
+
|
|
1813
|
+
迁移建议:旧工具在无 AppleSignin 时删除 applesignin,风险较高,可能误删游戏已有能力。迁移时建议改为只管理工具自己添加的能力,或至少在文档/日志中明确提示。
|
|
1814
|
+
|
|
1815
|
+
### 3.14 AppDelegate / SceneDelegate 代码注入
|
|
1816
|
+
|
|
1817
|
+
旧代码位置:
|
|
1818
|
+
|
|
1819
|
+
- `TopSDKTool.py::addCodes`
|
|
1820
|
+
- `TopSDKTool.py::setupProject`
|
|
1821
|
+
- `XcodeManager.py::findDelegateFile`
|
|
1822
|
+
- `XcodeManager.py::findSceneDelegateFile`
|
|
1823
|
+
- `CodeUtils.py`
|
|
1824
|
+
|
|
1825
|
+
旧行为:
|
|
1826
|
+
|
|
1827
|
+
1. 遍历工程目录,查找包含 `UIApplicationDelegate` 的 `.h/.m/.mm`。
|
|
1828
|
+
2. 如果命中 `.h`,尝试定位同名 `.m` 或 `.mm`。
|
|
1829
|
+
3. 排除固定文件:`Unity_iPhone_Tests.m`、`UnityAppController+ViewHandling.mm`。
|
|
1830
|
+
4. 找到 1 个 AppDelegate 实现文件时自动注入。
|
|
1831
|
+
5. 找到多个时交互选择。
|
|
1832
|
+
6. 找不到时提示用户参考文档手动接入。
|
|
1833
|
+
7. SceneDelegate 逻辑类似,查找 `UIWindowSceneDelegate`。
|
|
1834
|
+
8. `CodeUtils.addHeader` 将 header 插入文件头部。
|
|
1835
|
+
9. `CodeUtils.addCodeToMethod`:
|
|
1836
|
+
- 如果目标方法存在,则在方法 `{` 后插入代码。
|
|
1837
|
+
- 如果 `addToReturn=true`,则把返回语句改写为 SDK 代码参与返回。
|
|
1838
|
+
- 如果目标方法不存在,则在 `@end` 前新增方法。
|
|
1839
|
+
- 插入前会去掉空格检查代码是否已存在,避免重复。
|
|
1840
|
+
|
|
1841
|
+
迁移测试方法:
|
|
1842
|
+
|
|
1843
|
+
| 场景 | 断言 |
|
|
1844
|
+
|---|---|
|
|
1845
|
+
| AppDelegate 单文件 | header 和方法调用被插入 |
|
|
1846
|
+
| AppDelegate 多文件 | 无参数时明确失败或要求指定,不能随机选择 |
|
|
1847
|
+
| 无 AppDelegate | 不修改代码,输出明确提示 |
|
|
1848
|
+
| SceneDelegate 单文件 | scene delegate code 被插入 |
|
|
1849
|
+
| 方法已存在 | 在方法体开头插入代码 |
|
|
1850
|
+
| 方法不存在 | 在 `@end` 前新增方法 |
|
|
1851
|
+
| `addToReturn=true` 且原来 `return YES;` | 改为返回 SDK 代码 |
|
|
1852
|
+
| `addToReturn=true` 且原来 `return xxx;` | 改为 `return (xxx && sdkCode);` |
|
|
1853
|
+
| 重复执行 | header 和代码不重复 |
|
|
1854
|
+
| Swift AppDelegate | 旧工具不支持;迁移范围需明确是否不支持 |
|
|
1855
|
+
|
|
1856
|
+
### 3.15 保存行为
|
|
1857
|
+
|
|
1858
|
+
旧代码位置:
|
|
1859
|
+
|
|
1860
|
+
- `XcodeManager.py::save`
|
|
1861
|
+
- `InfoPlistManager.py::save`
|
|
1862
|
+
|
|
1863
|
+
旧行为:
|
|
1864
|
+
|
|
1865
|
+
每次 `setPlugin` 后都会保存 `project.pbxproj` 和 Info.plist。最终工程中会落地:
|
|
1866
|
+
|
|
1867
|
+
```text
|
|
1868
|
+
<project-root>/topSDK/*
|
|
1869
|
+
<project>.xcodeproj/project.pbxproj
|
|
1870
|
+
<Info.plist>
|
|
1871
|
+
<target>.entitlements # 有 AppleSignin 或需要处理 entitlement 时
|
|
1872
|
+
AppDelegate.m/.mm
|
|
1873
|
+
SceneDelegate.m/.mm
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
迁移测试方法:
|
|
1877
|
+
|
|
1878
|
+
| 场景 | 断言 |
|
|
1879
|
+
|---|---|
|
|
1880
|
+
| dry-run | 不写磁盘,只输出预期 diff |
|
|
1881
|
+
| apply | 写入上述目标文件 |
|
|
1882
|
+
| 中途失败 | 尽量不产生半成品;如不能事务化,错误信息需列出已改文件 |
|
|
1883
|
+
|
|
1884
|
+
## 4. 迁移 Golden Output 建议
|
|
1885
|
+
|
|
1886
|
+
为了保证迁移不遗漏业务逻辑,建议准备固定输入和 golden output。
|
|
1887
|
+
|
|
1888
|
+
### 4.1 固定输入
|
|
1889
|
+
|
|
1890
|
+
每个样例工程都应固定:
|
|
1891
|
+
|
|
1892
|
+
- `.xcodeproj`
|
|
1893
|
+
- target 名
|
|
1894
|
+
- Info.plist
|
|
1895
|
+
- AppDelegate / SceneDelegate
|
|
1896
|
+
- TOPSDK 包资源目录
|
|
1897
|
+
- `sdk/*.json`
|
|
1898
|
+
- `plugins/*/config.json`
|
|
1899
|
+
- mock 的 `getSDKConfig` 响应 JSON
|
|
1900
|
+
|
|
1901
|
+
不要在测试中依赖实时后台接口。
|
|
1902
|
+
|
|
1903
|
+
### 4.2 样例工程矩阵
|
|
1904
|
+
|
|
1905
|
+
| 样例 | 覆盖点 |
|
|
1906
|
+
|---|---|
|
|
1907
|
+
| `ios-native-minimal` | 单 target、单 Info.plist、无插件或 Guest/UI |
|
|
1908
|
+
| `ios-native-login` | Google/Facebook/Apple 登录、URL Scheme、queriesSchemes |
|
|
1909
|
+
| `ios-native-payment` | IAP 插件、系统库/framework |
|
|
1910
|
+
| `ios-native-data` | AppsFlyer/Firebase/Adjust 等 dataPlugins |
|
|
1911
|
+
| `ios-native-multi-target` | 多 target 错误或显式 target 选择 |
|
|
1912
|
+
| `ios-native-multi-plist` | Debug/Release 不同 plist |
|
|
1913
|
+
| `ios-native-scene` | SceneDelegate 注入 |
|
|
1914
|
+
| `ios-native-repeat` | 重复执行幂等性 |
|
|
1915
|
+
|
|
1916
|
+
### 4.3 Golden 文件
|
|
1917
|
+
|
|
1918
|
+
每个样例至少保存:
|
|
1919
|
+
|
|
1920
|
+
```text
|
|
1921
|
+
golden/
|
|
1922
|
+
topSDK-file-list.txt
|
|
1923
|
+
project.pbxproj
|
|
1924
|
+
Info.plist.json
|
|
1925
|
+
Entitlements.plist.json
|
|
1926
|
+
AppDelegate.m
|
|
1927
|
+
SceneDelegate.m
|
|
1928
|
+
```
|
|
1929
|
+
|
|
1930
|
+
plist 建议转成 JSON 后比较,避免二进制 plist 或 key 顺序影响 diff。
|
|
1931
|
+
|
|
1932
|
+
### 4.4 断言重点
|
|
1933
|
+
|
|
1934
|
+
测试重点不是“函数调用成功”,而是断言输出:
|
|
1935
|
+
|
|
1936
|
+
- `topSDK/` 文件列表完全符合预期。
|
|
1937
|
+
- `project.pbxproj` 中文件引用、build phase、build settings 正确。
|
|
1938
|
+
- Info.plist 中 `TOPSDK`、`CFBundleURLTypes`、`LSApplicationQueriesSchemes` 正确。
|
|
1939
|
+
- Entitlements 正确。
|
|
1940
|
+
- AppDelegate / SceneDelegate 代码正确且重复执行不重复。
|
|
1941
|
+
- 缺少资源、缺少配置、target 不明确时错误信息明确。
|
|
1942
|
+
|
|
1943
|
+
## 5. 不迁移清单
|
|
1944
|
+
|
|
1945
|
+
以下旧逻辑不迁移到本轮 `meet-sdk-tool`:
|
|
1946
|
+
|
|
1947
|
+
| 旧逻辑 | 位置 | 不迁移原因 |
|
|
1948
|
+
|---|---|---|
|
|
1949
|
+
| Unity target 拆分接入 | `TopSDKTool.py` Unity 分支 | 只支持 iOS 原生工程 |
|
|
1950
|
+
| Cocos Creator target 处理 | `TopSDKTool.py` Cocos 分支 | 只支持 iOS 原生工程 |
|
|
1951
|
+
| LayaNative 分支 | `TopSDKTool.py` `engineType == layaNative` | 本轮不支持其他引擎 |
|
|
1952
|
+
| 引擎桥接资源 `sdkBridge` | `checkEngineSource` / `setupProject` | 非原生引擎能力 |
|
|
1953
|
+
| Unity 旧版本 Swift bridging 提示 | Unity 分支 | 非原生引擎能力 |
|
|
1954
|
+
| 上传 TOPSDK 资源到下载页 | `upload.py` | 用户明确排除上传 |
|
|
1955
|
+
| 更新本地 TOPSDK 资源目录 | `update.py` | 用户明确排除更新 |
|
|
1956
|
+
| 开发者本机 `rootPath` 覆盖 | `TopSDKTool.py` `currentEnv != ENV.prod` | 本机硬编码,不应迁移 |
|
|
1957
|
+
|
|
1958
|
+
## 6. 迁移完成标准
|
|
1959
|
+
|
|
1960
|
+
迁移完成不能只以“命令跑通”为准,应满足:
|
|
1961
|
+
|
|
1962
|
+
1. 同一份固定输入下,Python 工具和 `meet-sdk-tool` 的产物等价。
|
|
1963
|
+
2. 重复执行不会重复插入 framework、lib、plist、URL Scheme、代码。
|
|
1964
|
+
3. 缺少 SDK 包资源时错误信息明确。
|
|
1965
|
+
4. 缺少后台配置时错误信息明确,列出缺失配置项。
|
|
1966
|
+
5. 多 target、多 delegate 文件时行为确定,不依赖交互式随机选择。
|
|
1967
|
+
6. 不触碰 Unity/Cocos/LayaNative 相关逻辑。
|
|
1968
|
+
7. 不包含上传和更新能力。
|
|
1969
|
+
|
|
1970
|
+
---
|
|
1971
|
+
|
|
1972
|
+
## Python 到 TypeScript 对照
|
|
1973
|
+
|
|
1974
|
+
This document tracks migration from `topsdk-tool-ios` Python tooling to `meet-sdk-tool`.
|
|
1975
|
+
|
|
1976
|
+
## Scope
|
|
1977
|
+
|
|
1978
|
+
- Supported host project: iOS `.xcodeproj`.
|
|
1979
|
+
- Unsupported in this migration: Python tool branches outside `engineType == "ios"` and SwiftUI-only entry injection.
|
|
1980
|
+
- No interactive prompts:
|
|
1981
|
+
- `appId` and `appSecret` come from existing `fetch-config` / `setup` command parameters or environment variables.
|
|
1982
|
+
- `.xcodeproj` can be provided directly as `--project-root`, or auto-detected when `--project-root` points to the iOS project directory.
|
|
1983
|
+
- Target selection is automatic. The current implementation uses the detected primary Xcode target unless recipe args provide `targetName`.
|
|
1984
|
+
|
|
1985
|
+
## CLI Contract
|
|
1986
|
+
|
|
1987
|
+
```bash
|
|
1988
|
+
meetgames setup \
|
|
1989
|
+
--project-root /path/to/ios-project/MyGame.xcodeproj \
|
|
1990
|
+
--app-id <appId> \
|
|
1991
|
+
--app-secret <appSecret> \
|
|
1992
|
+
--channel-type APPLE \
|
|
1993
|
+
--env test
|
|
1994
|
+
```
|
|
1995
|
+
|
|
1996
|
+
`--project-root` may point to either the iOS project directory or directly to the `.xcodeproj` directory.
|
|
1997
|
+
|
|
1998
|
+
## Python-To-TypeScript Mapping
|
|
1999
|
+
|
|
2000
|
+
| Python implementation | Behavior | TypeScript implementation |
|
|
2001
|
+
|---|---|---|
|
|
2002
|
+
| `TopSDKTool.py#setPlugin` | Apply plugin SDK resources and project settings | `src/ios/integrate.ts#applyPlugin` |
|
|
2003
|
+
| `PluginConfig.py` | Parse SDK/plugin config JSON | `src/ios/pluginConfig.ts` |
|
|
2004
|
+
| `FileManager.py` | Copy SDK files into `topSDK/` | `src/ios/fileManager.ts` |
|
|
2005
|
+
| `XcodeManager.py` | Edit `project.pbxproj`, target build phases, build settings | `src/ios/pbxprojEditor.ts` |
|
|
2006
|
+
| `InfoPlistManager.py` | Edit `Info.plist`, URL schemes, query schemes | `src/ios/infoPlist.ts` |
|
|
2007
|
+
| `CodeUtils.py` | Inject AppDelegate/SceneDelegate snippets | `src/ios/codeUtils.ts` |
|
|
2008
|
+
| `ChannelConfigManager.py` | Fetch remote channel config | `src/remote/*`, `src/config/*` |
|
|
2009
|
+
|
|
2010
|
+
## Required Behavior Checklist
|
|
2011
|
+
|
|
2012
|
+
- [ ] Load SDK core configs from `bundled/ios-sdk/**/sdk/*.json`.
|
|
2013
|
+
- [ ] Load enabled plugin configs from `bundled/ios-sdk/**/plugins/*/config.json` or `config.t.json`.
|
|
2014
|
+
- [ ] Copy non-system frameworks into host `topSDK/`.
|
|
2015
|
+
- [ ] Add non-system frameworks to `project.pbxproj`.
|
|
2016
|
+
- [ ] Respect framework `embed`.
|
|
2017
|
+
- [ ] Respect framework `copyFile`.
|
|
2018
|
+
- [ ] Add system frameworks from SDK/plugin config.
|
|
2019
|
+
- [ ] Copy and add non-system libs.
|
|
2020
|
+
- [ ] Add system libs.
|
|
2021
|
+
- [ ] Copy and add bundle/resource/source entries.
|
|
2022
|
+
- [ ] Apply build settings.
|
|
2023
|
+
- [ ] Apply `OtherLinkerFlags` idempotently.
|
|
2024
|
+
- [ ] Apply `LSApplicationQueriesSchemes` idempotently.
|
|
2025
|
+
- [ ] Apply `CFBundleURLTypes` idempotently.
|
|
2026
|
+
- [ ] Trim trailing `://` from URL scheme values.
|
|
2027
|
+
- [ ] Replace `{$C.xxx.yyy}` channel config placeholders.
|
|
2028
|
+
- [ ] Write the `TOPSDK` plist block with `APP_ID`, `Plugins`, and `dataPlugins`.
|
|
2029
|
+
- [ ] Enable Apple Sign In entitlements when Apple login is enabled.
|
|
2030
|
+
- [ ] Inject AppDelegate snippets idempotently.
|
|
2031
|
+
- [ ] Inject SceneDelegate snippets idempotently.
|
|
2032
|
+
- [ ] Dry-run reports all text changes and planned binary copies without writing files.
|
|
2033
|
+
- [ ] Apply mode is idempotent when run repeatedly on the same project.
|
|
2034
|
+
|
|
2035
|
+
## Golden Sample Strategy
|
|
2036
|
+
|
|
2037
|
+
Use iOS `.xcodeproj` sample projects only.
|
|
2038
|
+
|
|
2039
|
+
1. Run the Python tool with a fixed SDK package and fixed remote config.
|
|
2040
|
+
2. Save the resulting files as baseline:
|
|
2041
|
+
- `project.pbxproj`
|
|
2042
|
+
- `Info.plist`
|
|
2043
|
+
- `.entitlements`
|
|
2044
|
+
- `AppDelegate.m` / `.mm`
|
|
2045
|
+
- `SceneDelegate.m` / `.mm`
|
|
2046
|
+
- `topSDK/` file tree
|
|
2047
|
+
3. Run `meet-sdk-tool` with the same input.
|
|
2048
|
+
4. Compare behavior, not exact UUID ordering in `project.pbxproj`.
|
|
2049
|
+
|
|
2050
|
+
## Non-Goals
|
|
2051
|
+
|
|
2052
|
+
- Recreate Python interactive target selection.
|
|
2053
|
+
- Recreate Python branches for Unity, Cocos, LayaNative, or other game engine exports.
|
|
2054
|
+
- Support SwiftUI `@main` App entry injection in this migration.
|
|
2055
|
+
|
|
2056
|
+
---
|
|
2057
|
+
|
|
2058
|
+
## 差异与缺失备忘
|
|
2059
|
+
|
|
2060
|
+
本文记录当前 `meet-sdk-tool` iOS 接入实现与 `topsdk-tool-ios` Python 旧逻辑、[`ios-topsdk-tool-feature-test-plan.md`](./ios-topsdk-tool-feature-test-plan.md) 之间的主要缺失和不一致,后续按条目逐项处理。
|
|
2061
|
+
|
|
2062
|
+
## 当前结论
|
|
2063
|
+
|
|
2064
|
+
当前 `meet-sdk-tool` 已能跑通 iOS MVP:Core SDK + 部分插件 + `project.pbxproj` + Info.plist + AppDelegate/SceneDelegate 注入。
|
|
2065
|
+
|
|
2066
|
+
但它还不是 `topsdk-tool-ios` 的完整等价迁移,现有测试也主要覆盖 Core + GuestSignin,未覆盖完整插件和异常场景。
|
|
2067
|
+
|
|
2068
|
+
## 已处理
|
|
2069
|
+
|
|
2070
|
+
| 问题 | 处理结果 | 相关位置 |
|
|
2071
|
+
|---|---|---|
|
|
2072
|
+
| 资源完整性校验缺失 | 已在接入前校验 source/framework/lib,缺失时明确失败,不再静默跳过 | `src/ios/pluginConfig.ts`、`src/ios/integrate.ts` |
|
|
2073
|
+
| Apple Sign In entitlements 未实现 | 已在启用 `AppleSignin` 时创建/更新 `.entitlements`,写入 `CODE_SIGN_ENTITLEMENTS` 和 `com.apple.developer.applesignin`;未启用时不删除既有 entitlement | `src/ios/entitlements.ts`、`src/ios/integrate.ts` |
|
|
2074
|
+
| `.xcframework` 支持不完整 | 已允许 `.xcframework` 复制并加入 Xcode 工程 | `src/ios/fileManager.ts`、`src/ios/integrate.ts` |
|
|
2075
|
+
| `copyFile=true` 未实现 | 已映射到 `PBXCopyFilesBuildPhase` | `src/ios/pbxprojEditor.ts`、`src/ios/integrate.ts` |
|
|
2076
|
+
| 插件必需参数校验缺失 | 已按 `requireConfigs` 校验渠道参数,缺少时失败并列出插件名和参数名 | `src/ios/integrate.ts` |
|
|
2077
|
+
| `login.apple` 未进入远端配置模型 | 已作为简单登录模块加入配置解析,可启用 iOS `AppleSignin` 插件 | `src/config/meetSdkRemoteConfig.ts`、`src/ios/channelConfig.ts` |
|
|
2078
|
+
|
|
2079
|
+
## P0:优先处理
|
|
2080
|
+
|
|
2081
|
+
当前没有阻断 iOS 原生迁移的 P0 项。
|
|
2082
|
+
|
|
2083
|
+
## P1:行为一致性
|
|
2084
|
+
|
|
2085
|
+
| 问题 | 当前表现 | Python 旧逻辑 / 期望 | 相关位置 |
|
|
2086
|
+
|---|---|---|---|
|
|
2087
|
+
| 插件启用范围不完整 | 只映射 `guest/email/facebook/google/googleIap/apple` | 旧工具读取 `plugins/*/config.json`,按下载包和在线配置接入全部插件 | `src/ios/channelConfig.ts` |
|
|
2088
|
+
| Target 选择不一致 | 通过正则取第一个 `PBXNativeTarget` | 过滤测试 target;单 target 自动选,多 target 交互选择 | `src/ios/detect.ts`、旧 `selectTargetAndStartSetting` |
|
|
2089
|
+
| 多 AppDelegate/SceneDelegate 处理不一致 | 当前单文件自动注入,多文件 warning 并跳过 | 旧工具单文件自动注入,多文件要求用户选择;后续可增加参数指定路径 | `src/ios/integrate.ts`、旧 `XcodeManager.py::findDelegateFile` |
|
|
2090
|
+
| Info.plist 缺失行为不一致 | 找不到时会创建默认 Info.plist | 旧工具找不到 Info.plist 直接失败 | `src/ios/integrate.ts::ensureInfoPlists`、旧 `XcodeManager.py::setTarget` |
|
|
2091
|
+
| Swift AppDelegate/SwiftUI 不支持 | 当前只查 `.m/.mm/.h`,SwiftUI 只 warning | 旧工具也不支持 Swift;迁移需明确不支持或新增支持 | `src/ios/codeUtils.ts` |
|
|
2092
|
+
|
|
2093
|
+
## P2:需要确认是否保留旧行为
|
|
2094
|
+
|
|
2095
|
+
| 问题 | 当前表现 | 风险 / 决策点 | 相关位置 |
|
|
2096
|
+
|---|---|---|---|
|
|
2097
|
+
| `NSAppTransportSecurity` 自动打开 | 当前会给第一个 plist 写 `NSAllowsArbitraryLoads = true` | Python 主接入流程未显式调用;需确认是否应保留 | `src/ios/integrate.ts`、`src/ios/infoPlist.ts` |
|
|
2098
|
+
| 无 AppleSignin 时是否移除 applesignin entitlement | 当前未实现移除 | Python 会调用 `openSigninWithApple(False)`,但可能误删游戏自身能力;建议不要默认删除 | 旧 `XcodeManager.py::openSigninWithApple` |
|
|
2099
|
+
| 模板替换行为 | 当前支持多个 `{...}`,缺值替换为空字符串 | Python 只处理第一个 `{$C...}`;当前更强,但需确认是否允许 | `src/ios/template.ts` |
|
|
2100
|
+
| `infoParams` 非字符串值 | 类型定义为 `Record<string, string>`,但 plist 写入支持 unknown | 若插件配置有对象/数组值,需要放宽类型并补测试 | `src/ios/types.ts`、`src/ios/infoPlist.ts` |
|
|
2101
|
+
|
|
2102
|
+
## 测试缺口
|
|
2103
|
+
|
|
2104
|
+
当前已有 iOS 测试:
|
|
2105
|
+
|
|
2106
|
+
```text
|
|
2107
|
+
tests/pipeline.ios.test.ts
|
|
2108
|
+
tests/ios.codeUtils.test.ts
|
|
2109
|
+
tests/ios.sdkBundle.test.ts
|
|
2110
|
+
```
|
|
2111
|
+
|
|
2112
|
+
已验证:
|
|
2113
|
+
|
|
2114
|
+
- iOS sample 检测
|
|
2115
|
+
- `.xcodeproj` 作为 `--project-root`
|
|
2116
|
+
- bundled iOS SDK 根目录解析
|
|
2117
|
+
- dry-run 生成 Core + GuestSignin 计划
|
|
2118
|
+
- apply 后复制 Core + GuestSignin 并注入 AppDelegate
|
|
2119
|
+
- CodeUtils header 去重
|
|
2120
|
+
|
|
2121
|
+
缺少测试:
|
|
2122
|
+
|
|
2123
|
+
- FacebookSignin + `.xcframework`
|
|
2124
|
+
- GoogleSignin + URL Scheme + pluginParams
|
|
2125
|
+
- IAPPay + StoreKit
|
|
2126
|
+
- `copyFile=true` 独立 fixture
|
|
2127
|
+
- 缺 framework/source/lib 失败
|
|
2128
|
+
- 多 target
|
|
2129
|
+
- Debug/Release 多 Info.plist
|
|
2130
|
+
- SceneDelegate 注入
|
|
2131
|
+
- 重复执行完整幂等性
|
|
2132
|
+
- Swift/SwiftUI 明确不支持提示
|
|
2133
|
+
|
|
2134
|
+
## 建议处理顺序
|
|
2135
|
+
|
|
2136
|
+
1. 明确 target/delegate 多候选处理策略,非交互命令建议通过参数指定,否则失败。
|
|
2137
|
+
2. 补完整 iOS golden sample 和测试矩阵。
|
|
2138
|
+
3. 补 FacebookSignin / GoogleSignin / IAPPay 等真实插件组合测试。
|
|
2139
|
+
4. 对 `NSAppTransportSecurity`、模板替换增强、Info.plist 缺失时创建默认文件等差异做业务确认。
|