Files
tongxunruanjian/mobile/README.md
T
KIMI d481e1bc2f mobile: 提交 android/ios 平台脚手架与打包配置(B-58)
- flutter create 生成的 android/ ios/ 脚手架入库,服务器/使用者无需再装 Flutter
- AndroidManifest:补 INTERNET/录音/存储权限,应用名改「畅联」,开 usesCleartextTraffic(内网 http/ws)
- iOS Info.plist:麦克风/相册用途说明、ATS 放行内网明文、显示名「畅联」
- gradle:阿里云镜像优先(本网络 maven.google.com 不可达);统一 Java/Kotlin 编译目标 17;
  抬升 livekit_client compileSdk 到 36 以满足 flutter_webrtc 的 AAR 校验
- README 更新为「直接打包」流程
2026-08-15 13:22:25 +08:00

89 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 畅联 · 手机端(Flutter
公司内部通讯 App 的手机端源码。骨架配色走企业微信式办公风(主色蓝 `#3B87F5`),聊天手感照微信。仓库已带 `android/``ios/` 平台脚手架与全部权限声明,**不需要再跑 `flutter create`**。
## 打包 / 运行
打包是开发机上的事,**服务器上不需要装 Flutter**(服务器只跑 docker 后端)。在装好 Flutter 与 Android SDK 的开发机上:
```bash
cd mobile
flutter pub get
flutter build apk --release # 出安卓安装包 build/app/outputs/flutter-apk/app-release.apk
```
iOS 需要一台 Mac 搭配 Xcode 与开发者证书,另按苹果流程打包。
已声明的平台权限(勿删):
- `android/app/src/main/AndroidManifest.xml``INTERNET``RECORD_AUDIO`(语音消息/通话)、`MODIFY_AUDIO_SETTINGS`、存储/相册读取(发文件、发图片);并开启了 `usesCleartextTraffic`(内网服务器暂用 http/ws 明文,开通外网改 HTTPS 后应移除)。
- `ios/Runner/Info.plist``NSMicrophoneUsageDescription`(语音消息与通话)、`NSPhotoLibraryUsageDescription`(发图片)、`NSAppTransportSecurity/NSAllowsArbitraryLoads`(同上,内网明文)。
- `android/build.gradle.kts` / `settings.gradle.kts` 把阿里云 Maven 镜像放在最前(本网络访问 maven.google.com 不稳定)。
## 修改服务器地址
所有服务器地址集中在 `lib/config.dart`,改 `serverHost`(内网 IP/域名)和对应端口常量即可:
| 常量 | 用途 | 默认值 |
| --- | --- | --- |
| `apiAddr` | OpenIM API | `http://192.168.200.11:10002` |
| `wsAddr` | OpenIM WebSocket | `ws://192.168.200.11:10001` |
| `livekitUrl` | LiveKit 语音通话 | `ws://192.168.200.11:17880`(注意已重映射,非默认 7880) |
| `authApiBase` | 公司账号登录后端 | `http://192.168.200.11:10010` |
## 登录接口契约(后端:任务 B-60 account-service,已上线)
### 1. 账号登录
```
POST {authApiBase}/api/login
Content-Type: application/json
{"staffNo": "工号", "password": "...", "platformID": 1}
```
- `platformID`1 = iOS2 = Android。
- 响应统一包络 `{"code": 0, "msg": "", "data": {...}}`(业务失败也是 HTTP 200 + `code != 0`HTTP 401/400 时同样带 `msg`)。
- 成功 `data``{"userID": "...", "nickname": "...", "imToken": "...", "expireTimeSeconds": ...}`
- `userID` / `imToken` 直接传给 OpenIM SDK 的 `login`OpenIM 的登录 token 由后端用 OpenIM 管理端接口换取)。
- 失败:`msg` 会原样展示给用户。
App 登录流程:`AuthApi.login` → 拿到 userID/imToken → `IMService.login`SDK `initSDK` 在 App 启动时已执行一次)→ 进主页。userID/imToken 存 `shared_preferences`,下次启动自动登录;SDK 回调 `onUserTokenExpired` / `onKickedOffline` 时清凭证回登录页。
### 2. 语音通话 token
官方样板工程的 LiveKit token 取自 open-im-chat 业务服务端(`/user/rtc/get_token`,端口 10008),本项目服务端裁剪时移除了 open-im-chat,由 account-service 提供等价接口:
```
POST {authApiBase}/api/rtc_token
Authorization: Bearer {登录返回的 imToken}
Content-Type: application/json
{"room": "房间号", "identity": "当前用户 userID"}
```
- 成功 `data``{"token": "LiveKit 访问 token"}`App 使用 `config.dart` 中的 `livekitUrl` 作为连接地址;后端用与 livekit 容器同一对 `LIVEKIT_API_KEY` / `LIVEKIT_API_SECRET` 签发 HS256 JWT)。
- 后端会先拿 `Authorization` 里的 IM token 调 OpenIM `parse_token` 校验身份,且要求 `identity` 与 token 对应的 userID 一致。
- 通话信令(呼叫/接听/拒绝/取消/挂断)走 OpenIM 自定义消息(customType 200-204 的仅在线消息),与官方样板工程协议一致,不需要后端参与。
## 代码结构
```
lib/
main.dart 入口:主题、路由、启动页(自动登录)、被踢下线/来电处理
config.dart 服务器地址集中配置
theme.dart 颜色、字号阶梯(4 级)、间距常量(4 的倍数)
models/signaling.dart 通话信令数据模型(与官方样板一致)
utils/format.dart 时间格式化、文件大小、会话预览文案
services/
im_service.dart OpenIM SDK 封装:init/login/监听/会话列表(ChangeNotifier
auth_api.dart 公司账号登录 + LiveKit token 的 HTTP 客户端(dio
call_service.dart 一对一语音通话:信令 + LiveKit 房间
screens/ 登录、主页三 Tab(消息/通讯录/我的)、聊天、通话等页面
widgets/ 头像、消息气泡、输入栏、四态视图
```
## 测试账号
员工账号由管理员在 account-service 管理页批量导入(工号 + 姓名 + 初始密码),App 端不开放自助注册。联调时请管理员先导入测试名单。