Files
sf-app-platform/VIDEOCALL_INTEGRATION.md

216 lines
7.2 KiB
Markdown
Raw Normal View History

# Integración Videollamadas — Juphoon jc_sdk
## Estado general
| Fase | Estado |
|---|---|
| 1. SDK wrapper (`videocall_sdk`) | ✅ Completado |
| 2. Configuración nativa (permisos) | ✅ Completado |
| 3. Configuración por entorno (AppKey) | ✅ Completado |
| 4. Feature videocall (UI + lógica) | ⏳ Pendiente |
| 5. Pruebas APP↔APP | ⏳ Pendiente |
| 6. Integración con backend (señalización) | ⏳ Pendiente |
| 7. Pruebas APP↔Reloj | ⏳ Pendiente |
| 8. Token auth (producción) | ⏳ Pendiente |
| 9. Push/background iOS | ⏳ Pendiente (sin doc del proveedor) |
| 10. Chat | ⏳ Pendiente (sin spec del proveedor) |
---
## Fase 1: SDK wrapper — ✅
Paquete `packages/videocall_sdk/` con wrap 100% de `jc_sdk` v2.16.5.
### Arquitectura (patrón sca_treezor)
- Constructor injection (no singletons estáticos)
- GetIt module (`videocallSdkModule(config)`)
- `VideocallSdkManager` orquestador de inicialización
- `VideocallSdkConfig` abstracto para config por entorno
- Riverpod providers + StreamProviders para UI reactiva
- Callbacks del SDK → Dart Streams
### Servicios (7 total, cobertura 100%)
- `VideocallClient` → JCClient (auth, login, logout, messaging)
- `VideocallCallService` → JCCall (llamadas 1-to-1)
- `VideocallDeviceService` → JCMediaDevice (cámara, mic, speaker)
- `VideocallChannelService` → JCMediaChannel (llamadas grupales)
- `VideocallPushService` → JCPush (push notifications)
- `VideocallNetService` → JCNet (estado de red)
- `VideocallLogService` → JCLog (logging)
### Estructura
```
packages/videocall_sdk/lib/src/
├── config/videocall_sdk_config.dart
├── di/videocall_sdk_module.dart
├── manager/videocall_sdk_manager.dart
├── models/ (call_state, call_direction, videocall_item, etc.)
├── services/ (7 servicios)
└── providers/videocall_providers.dart
```
---
## Fase 2: Permisos nativos — ✅
### Android (`AndroidManifest.xml`)
- [x] INTERNET (ya existía)
- [x] ACCESS_NETWORK_STATE (ya existía)
- [x] ACCESS_WIFI_STATE
- [x] CAMERA (ya existía)
- [x] RECORD_AUDIO
- [x] MODIFY_AUDIO_SETTINGS
- [x] BLUETOOTH
- [x] uses-feature: hardware.camera
- [x] uses-feature: hardware.camera.autofocus
- [x] uses-feature: hardware.bluetooth (optional)
### Android (`proguard-rules.pro`)
- [x] -keep com.juphoon.**
- [x] -keep com.justalk.**
- [x] -keepattributes InnerClasses
### iOS (`Info.plist`)
- [x] NSCameraUsageDescription (actualizado: QR + videollamadas)
- [x] NSMicrophoneUsageDescription
- [x] NSPhotoLibraryUsageDescription
### iOS (`Podfile`)
- [x] PERMISSION_CAMERA=1
- [x] PERMISSION_PHOTOS=1
- [x] PERMISSION_MICROPHONE=1
---
## Fase 3: Config por entorno — ✅
- [x] `juphoonAppKey` en development.json, staging.json, production.json
- [x] `Environment.juphoonAppKey` via `String.fromEnvironment()`
- [x] `SaveFamilyVideocallConfig` implementa `VideocallSdkConfig`
- [x] `videocallSdkModule(config)` llamado en `init_app.dart`
- [ ] AppKeys separadas por entorno (por ahora las 3 usan la misma clave de dev)
---
## Fase 4: Feature videocall — ⏳ SIGUIENTE
Feature en `modules/legacy/modules/device_management/lib/src/features/videocall/`
### Por hacer
- [ ] `videocall_builder.dart` — GoRouter builder
- [ ] `domain/entities/videocall_entity.dart` — Freezed entity
- [ ] `domain/entities/videocall_error.dart` — Error enum con i18n
- [ ] `presentation/state/videocall_view_model.dart` — Notifier
- [ ] `presentation/state/videocall_view_state.dart` — Freezed state
- [ ] `presentation/videocall_screen.dart` — Pantalla de llamada
- [ ] `presentation/widgets/local_video_view.dart` — Video local
- [ ] `presentation/widgets/remote_video_view.dart` — Video remoto
- [ ] `presentation/widgets/call_controls.dart` — Botones (colgar, mute, cámara)
- [ ] `presentation/widgets/incoming_call_dialog.dart` — Dialog llamada entrante
- [ ] Providers en `core/providers/`
- [ ] Ruta en GoRouter (`app_router.dart`)
- [ ] Runtime permissions (pedir cámara/mic en runtime)
---
## Fase 5: Pruebas APP↔APP — ⏳
- [ ] Login con 2 userIDs de prueba (`p_test1`, `p_test2`)
- [ ] Llamada de voz APP→APP
- [ ] Videollamada APP→APP
- [ ] Responder llamada entrante
- [ ] Rechazar llamada
- [ ] Colgar durante llamada
- [ ] Mute/unmute micrófono
- [ ] Cambiar cámara frontal/trasera
- [ ] Speaker on/off
- [ ] Llamada perdida (onMissedCallItem)
- [ ] Verificar desfase versión SDK (quickstart 1.0.2 vs pub.dev 2.16.5)
---
## Fase 6: Integración backend — ⏳
- [ ] Obtener documentación API REST del backend SaveFamily para señalización
- [ ] Endpoint para iniciar llamada → notificar al reloj
- [ ] Endpoint para recibir notificación de llamada entrante del reloj
- [ ] Formato userID definido con backend (`p_<cuenta>` vs `w_<IMEI>`)
- [ ] Sanitización de emails (@ → _ en userIDs)
---
## Fase 7: Pruebas APP↔Reloj — ⏳
- [ ] Llamada APP → Reloj
- [ ] Llamada Reloj → APP
- [ ] Videollamada grupal (JCMediaChannel)
- [ ] Límite 5 min de llamada
- [ ] Registro IMEI (protocolo RYIMEI) — lo hace el backend
---
## Fase 8: Token auth — ⏳
- [ ] Backend implementa generación de tokens Juphoon (usa AppSecret)
- [ ] App pide token al backend antes del login
- [ ] Token se pasa como `password` en `VideocallClient.login()`
- [ ] Activar Token鉴权 en consola Juphoon (ya está activo)
Nota: para dev/testing no es necesario — `autoCreateAccount = true` en LoginParam permite login con cualquier password.
---
## Fase 9: Push/Background iOS — ⏳ RIESGO
**Problema:** No hay documentación de cómo recibir llamadas con la app cerrada en iOS.
- [ ] Probar qué pasa cuando la app está cerrada y llega una llamada (fase 5)
- [ ] Si no funciona: investigar PushKit + CallKit
- [ ] Verificar si `JCPush` del SDK resuelve esto
- [ ] Consultar pestaña "消息通知服务" en la consola Juphoon
- [ ] Si es deal-breaker: escalar antes del pago ($8,835)
---
## Fase 10: Chat — ⏳ SIN SPEC
- [ ] Obtener especificación del módulo de chat del proveedor
- [ ] Determinar si usa JCMediaChannel (SDK) o API propia
- [ ] $2,950 pagados sin lista de features
---
## Credenciales Juphoon Cloud
| Campo | Valor | Quién lo usa |
|---|---|---|
| AppKey | `9efcf2d889dc8a0320925096` | App Flutter + Backend |
| AppSecret | `ui7pr73ggl5rr0gf01np` | Solo Backend |
| AES_KEY (IoT) | `8e3637pG7E9144E0` | Solo Backend |
| Consola | juphoon.com (+34 603675786) | Julián |
---
## Naming conventions (protocolo TCP)
| Tipo | Formato | Ejemplo |
|---|---|---|
| Watch userID | `w_` + IMEI | `w_000078932675810` |
| Mobile userID | `p_` + APP account | `p_abc10086` |
| Group room | `did` + `_group` | `0245423235_group` |
| Single room | `did` + `_` + APP account | `0245423235_abc10086` |
Nota: `@` y `.` se reemplazan por `_` en room numbers y userIDs.
---
## Documentación de referencia
- Quickstart V1.1: `~/Downloads/Video call API_ Juphoon Flutter SDK quickstart V1.1.pdf`
- TCP Protocol: `~/Downloads/Juphoon Video Call TCP Protocol.docx`
- Connection process: `~/Downloads/video call connection process Rev2.docx`
- Mutual dialing: `~/Downloads/video call mutual dialing process.docx`
- Schematics: `~/Downloads/schematics _2025.03.26 (2)/`
- pub.dev: https://pub.dev/packages/jc_sdk
- Consola: https://developer.juphoon.com