164 lines
7.3 KiB
Markdown
164 lines
7.3 KiB
Markdown
# 创建新换皮应用 — 步骤清单
|
||
|
||
本文说明基于 `client_proxy_framework` **从零搭一个换皮应用**的推荐流程。配置以 **`skin_config.json`** 为主;更细的字段说明见 [`new_app_config_template.md`](new_app_config_template.md),原生侧见 [`sdk_integration_guide.md`](sdk_integration_guide.md)。更长篇的上下文与业务对接见 [`skin_app_development_guide.md`](skin_app_development_guide.md)。**`AuthServiceCallbacks` 所需的设备 ID 与 `computeSign`** 见 [`device_id_and_sign.md`](device_id_and_sign.md)。
|
||
|
||
***
|
||
|
||
## 1. 目录与仓库布局
|
||
|
||
建议将新应用与框架放在**同级目录**,便于 path 依赖:
|
||
|
||
```text
|
||
Workplace/
|
||
├── client_proxy_framework/ # 本框架
|
||
└── your_skin_app/ # 新换皮应用
|
||
```
|
||
|
||
***
|
||
|
||
## 2. 创建 Flutter 工程
|
||
|
||
```bash
|
||
cd Workplace
|
||
flutter create your_skin_app
|
||
cd your_skin_app
|
||
```
|
||
|
||
***
|
||
|
||
## 3. 接入框架依赖
|
||
|
||
在应用根目录 **`pubspec.yaml`** 中增加:
|
||
|
||
```yaml
|
||
dependencies:
|
||
flutter:
|
||
sdk: flutter
|
||
client_proxy_framework:
|
||
path: ../client_proxy_framework
|
||
```
|
||
|
||
换皮应用若实现自有登录回调(设备 ID、签名等),通常还需要:
|
||
|
||
```yaml
|
||
device_info_plus: ^11.1.0 # 常见:读 Android id / iOS identifierForVendor
|
||
crypto: ^3.0.3 # 常见:与后端约定的 MD5 签名
|
||
```
|
||
|
||
Android 侧通常还需要 [`android_id`](https://pub.dev/packages/android_id)(`Settings.Secure.ANDROID_ID`),与「仅用 device_info_plus 读到的 Android `id`」不是同一字段;**完整约定(含兜底 ID、`computeSign`)**见 [device_id_and_sign.md](device_id_and_sign.md)。
|
||
|
||
执行:
|
||
|
||
```bash
|
||
flutter pub get
|
||
```
|
||
|
||
框架已通过插件注册 **Adjust、Facebook、IAP、Play Install Referrer** 等依赖,宿主 **无需** 再单独声明 `adjust_sdk`、`facebook_app_events`,除非你有特殊版本要求。
|
||
|
||
***
|
||
|
||
## 4. 准备 `skin_config.json`
|
||
|
||
1. 在应用内创建目录 **`assets/`**。
|
||
2. 复制框架内的示例为起点:
|
||
- 源文件:框架仓库 [`lib/src/config/skin_config.example.json`](../lib/src/config/skin_config.example.json)
|
||
- 目标:`assets/skin_config.json`
|
||
3. 按后端交付的换皮参数填写 JSON,主要块包括:
|
||
- **`app`**:`name`、`id`(业务 appId)、`packageName`(渠道包名)
|
||
- **`backend`**:`iosAppType`、`androidAppType`(如 `HIOS` / `HAndroid`,与 fast_login 约定一致)
|
||
- **`api`**:预发/生产 URL、`proxyPath`、**16 字符** `aesKey`、`debugBaseUrlOverride`、`alwaysUsePreBaseUrl`(长期连预发时可 `true`)
|
||
- **`proxyKeys` / `v2`**:与后端约定的代理字段名、V2 包装路径与噪音键
|
||
- **`fieldMapping`**:原始字段 → V2 字段(可很大,整块放在 JSON)
|
||
- **`analytics`**:Adjust / Facebook(占位符会在运行时跳过初始化,并在控制台提醒)
|
||
- **`adjustEvents`**:可选,逻辑名 → Adjust 事件 Token
|
||
|
||
4. 在 **`pubspec.yaml`** 注册资源:
|
||
|
||
```yaml
|
||
flutter:
|
||
assets:
|
||
- assets/skin_config.json
|
||
```
|
||
|
||
***
|
||
|
||
## 5. 应用入口 `main.dart`(推荐顺序)
|
||
|
||
异步初始化与 **归因缓存** 须在启动登录前完成,推荐顺序如下:
|
||
|
||
```dart
|
||
import 'package:flutter/material.dart';
|
||
import 'package:client_proxy_framework/client_proxy_framework.dart';
|
||
|
||
void main() async {
|
||
WidgetsFlutterBinding.ensureInitialized();
|
||
|
||
await ClientBootstrap.initFromAsset('assets/skin_config.json');
|
||
await ClientBootstrap.initAnalytics();
|
||
await AnalyticsService.initAttribution();
|
||
|
||
runApp(MyApp(title: ClientBootstrap.skin.appName));
|
||
|
||
// 若使用 FrameworkAuthService 自动登录,在 runApp 之后或之前按产品要求调用
|
||
// MyAuthService.init(); // 内部:FrameworkAuthService.init(你的 AuthServiceCallbacks); start();
|
||
}
|
||
```
|
||
|
||
要点:
|
||
|
||
- **`ClientBootstrap.initFromAsset`**:加载 JSON 并 `ApiClient.init`。
|
||
- **`ClientBootstrap.initAnalytics`**:Adjust / Facebook(未配置或占位则降级,不卡死)。
|
||
- **`AnalyticsService.initAttribution`**:预取归因,供登录时 referer;框架内 **`FrameworkAuthService.init` 默认已注册** 与 Adjust 缓存一致的 **`AnalyticsAttributionCallbacks`**,应用侧一般**不用再写归因回调类**。
|
||
|
||
***
|
||
|
||
## 6. Android 配置
|
||
|
||
1. **包名**:`android/app/build.gradle.kts`(或 `build.gradle`)中的 `applicationId`、`namespace`,与 JSON 里 `app.packageName` 一致;Kotlin 目录与 `MainActivity` 包名同步修改。
|
||
2. **`MainActivity`**:使用默认 **`FlutterActivity`** 即可,**不要**再为 Facebook 单独写 `{packageName}/facebook_sdk` 的 MethodChannel;框架插件使用固定通道 **`client_proxy_framework/facebook_sdk`**。
|
||
3. **`AndroidManifest.xml`**:按 Adjust / Facebook 官方要求配置 `meta-data`(App Token、环境、Facebook AppId、ClientToken 等),并与 `strings.xml` 等引用一致。细节见 [`sdk_integration_guide.md`](sdk_integration_guide.md)。
|
||
4. **应用级 `Application` 子类**:一般不再需要仅为 Facebook 挂自定义 `Application`;若历史工程仍有,可评估删除后以默认 `Application` 运行。
|
||
|
||
***
|
||
|
||
## 7. iOS 配置
|
||
|
||
1. Xcode 中 **Bundle Identifier** 与 `skin_config.json` 的 `packageName` / 业务约定一致。
|
||
2. **`Info.plist`**:Facebook、Adjust 等键值与控制台一致;参见 [`sdk_integration_guide.md`](sdk_integration_guide.md)。
|
||
3. 工程根目录执行 **`pod install`** 后编译。
|
||
|
||
***
|
||
|
||
## 8. 登录与业务状态(应用侧最少代码)
|
||
|
||
框架负责:代理请求加解密、字段映射、**归因 referer 默认实现**、Adjust/Facebook 初始化(可配置)。
|
||
|
||
应用侧通常仍需:
|
||
|
||
1. 实现 **`AuthServiceCallbacks`**:`getDeviceId`、`computeSign`、`onLoginSuccess` / `onCommonInfoLoaded` / `onLoginFailed`(例如写入本地 `UserState`、路由)。**`getDeviceId` / `computeSign` 与 FunyMee、app_client 对齐的参考实现**见 [device_id_and_sign.md](device_id_and_sign.md)。
|
||
2. 调用 **`FrameworkAuthService.init(你的回调)`**,再 **`await FrameworkAuthService.start()`**(可参考示例工程里的薄封装 `AuthService.init()`)。
|
||
|
||
无需再实现 **`AttributionCallbacks`**,除非要自定义 referer 格式;此时用 **`FrameworkAuthService.init(callbacks, attributionCallbacks: 你的实现)`**。
|
||
|
||
***
|
||
|
||
## 9. 自检与上线前
|
||
|
||
1. **调试运行**:观察控制台是否出现 `[client_proxy_framework]` 的 SDK 配置提醒;占位 Token 会跳过对应 SDK,**不要**带着 TODO 配置上生产。
|
||
2. **接口**:确认 `debug` / `release` 下 `api.alwaysUsePreBaseUrl`、`debugBaseUrlOverride` 是否符合预期。
|
||
3. **发布**:补齐 Adjust/Facebook 真实参数;完成签名、隐私政策、应用商店物料等(不在本文范围)。
|
||
|
||
***
|
||
|
||
## 10. 相关文档索引
|
||
|
||
| 文档 | 用途 |
|
||
|------|------|
|
||
| [`new_app_config_template.md`](new_app_config_template.md) | 按表逐项填写换皮参数(可对照填入 JSON) |
|
||
| [`sdk_integration_guide.md`](sdk_integration_guide.md) | 原生工程 Adjust / Facebook 等集成要点 |
|
||
| [`skin_app_development_guide.md`](skin_app_development_guide.md) | 更长流程、业务/UI 后续对接说明 |
|
||
| [`device_id_and_sign.md`](device_id_and_sign.md) | 设备 ID 与 fast_login 签名(宿主参考实现) |
|
||
| 框架 `lib/src/config/skin_config.example.json` | JSON 最小结构示例 |
|
||
|
||
若本清单与旧文档冲突,**以本清单与当前框架代码为准**。
|