main commit

This commit is contained in:
2025-10-04 11:55:55 +09:00
parent c8c3274527
commit 4ceccae6ce
678 changed files with 95975 additions and 185 deletions

View File

@@ -0,0 +1,479 @@
# Техническое задание и промпт для создания Android приложения GodEye Signal Center
## 🎯 ТЕХНИЧЕСКОЕ ЗАДАНИЕ
### Назначение системы
Создать Android приложение для системы удаленного доступа к камерам смартфона "GodEye Signal Center". Приложение должно предоставлять операторам доступ к камерам устройства через WebRTC с возможностью переключения между различными типами камер.
### Архитектура системы
```
[Android App] ←→ [WebSocket/Socket.IO] ←→ [Backend Server] ←→ [Desktop Operator]
←→ [WebRTC P2P Connection] ←→ [Desktop Operator]
```
### Основные компоненты
1. **MainActivity** - главный экран с управлением подключением
2. **SocketService** - сервис для WebSocket соединения с backend
3. **CameraManager** - управление камерами устройства (Camera2 API)
4. **WebRTCManager** - обработка WebRTC соединений для видеопотока
5. **PermissionManager** - управление разрешениями приложения
6. **SessionManager** - управление активными сессиями с операторами
### Функциональные требования
- ✅ Подключение к backend серверу по WebSocket (Socket.IO)
- ✅ Регистрация устройства с передачей характеристик
- ✅ Получение и обработка запросов доступа к камере от операторов
- ✅ Диалоги согласия пользователя на доступ к камере
- ✅ WebRTC соединение для передачи видеопотока
- ✅ Переключение между камерами: основная, фронтальная, широкоугольная, телеобъектив
- ✅ Отображение активных сессий и их управление
- ✅ Автоматическое переподключение при обрыве соединения
- ✅ Работа в фоне (Foreground Service)
- ✅ Уведомления о статусе подключения
### Технические требования
- **Платформа**: Android API 24+ (Android 7.0+)
- **Язык**: Kotlin
- **Архитектура**: MVVM с LiveData
- **Сеть**: Socket.IO для сигнализации, WebRTC для медиа
- **Камера**: Camera2 API для работы с камерами
- **UI**: Material Design 3
- **Разрешения**: CAMERA, RECORD_AUDIO, INTERNET, FOREGROUND_SERVICE
## 📋 ПОЛНЫЙ ПРОМПТ ДЛЯ COPILOT
---
**Создай полное Android приложение на Kotlin для системы GodEye Signal Center со следующими требованиями:**
### 🚀 ОСНОВНАЯ ЗАДАЧА
Разработать Android приложение, которое подключается к backend серверу, получает запросы от операторов на доступ к камере устройства и предоставляет видеопоток через WebRTC с возможностью переключения между камерами.
### 📱 СТРУКТУРА ПРОЕКТА
```
app/
├── src/main/
│ ├── java/com/godeye/android/
│ │ ├── MainActivity.kt
│ │ ├── services/
│ │ │ ├── SocketService.kt
│ │ │ └── CameraService.kt
│ │ ├── managers/
│ │ │ ├── CameraManager.kt
│ │ │ ├── WebRTCManager.kt
│ │ │ ├── SessionManager.kt
│ │ │ └── PermissionManager.kt
│ │ ├── models/
│ │ │ ├── DeviceInfo.kt
│ │ │ ├── CameraSession.kt
│ │ │ └── SocketEvents.kt
│ │ ├── ui/
│ │ │ ├── dialogs/
│ │ │ │ └── CameraRequestDialog.kt
│ │ │ └── adapters/
│ │ │ └── SessionAdapter.kt
│ │ └── utils/
│ │ ├── Constants.kt
│ │ └── Extensions.kt
│ ├── res/
│ │ ├── layout/
│ │ │ ├── activity_main.xml
│ │ │ ├── dialog_camera_request.xml
│ │ │ └── item_session.xml
│ │ ├── values/
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ └── drawable/
│ └── AndroidManifest.xml
└── build.gradle (app)
```
### 🔧 BACKEND API ENDPOINTS
#### WebSocket События (Socket.IO на порту 3001):
```kotlin
// Регистрация устройства
socket.emit("register:android", JsonObject().apply {
addProperty("deviceId", deviceId)
add("deviceInfo", JsonObject().apply {
addProperty("model", Build.MODEL)
addProperty("androidVersion", Build.VERSION.RELEASE)
addProperty("appVersion", "1.0.0")
add("availableCameras", JsonArray().apply {
add("back"); add("front"); add("wide"); add("telephoto")
})
})
})
// Обработка входящих событий
socket.on("register:success") { /* успешная регистрация */ }
socket.on("camera:request") { /* запрос доступа к камере */ }
socket.on("camera:disconnect") { /* завершение сессии */ }
socket.on("camera:switch") { /* переключение камеры */ }
socket.on("webrtc:offer") { /* WebRTC offer от оператора */ }
socket.on("webrtc:ice-candidate") { /* ICE candidates */ }
// Отправка ответов
socket.emit("camera:response", JsonObject().apply {
addProperty("sessionId", sessionId)
addProperty("accepted", true)
})
socket.emit("webrtc:answer", JsonObject().apply {
addProperty("sessionId", sessionId)
add("answer", /* RTCSessionDescription */)
})
```
### 🎨 UI/UX ТРЕБОВАНИЯ
#### MainActivity.xml:
```xml
<!-- Основной экран с полями: -->
- TextView: Device ID (автогенерируемый)
- EditText: Server URL (по умолчанию: http://192.168.1.100:3001)
- TextView: Connection Status
- Button: Connect/Disconnect
- RecyclerView: Active Sessions
- ProgressBar: Connection progress
- FloatingActionButton: Settings
```
#### CameraRequestDialog.xml:
```xml
<!-- Диалог запроса доступа: -->
- ImageView: Operator avatar/icon
- TextView: "Оператор {operatorId} запрашивает доступ к камере {cameraType}"
- TextView: Session ID
- Button: "Разрешить" / "Отклонить"
- CheckBox: "Запомнить для этого оператора"
```
### 💾 DATA MODELS
```kotlin
data class DeviceInfo(
val model: String,
val androidVersion: String,
val appVersion: String,
val availableCameras: List<String>
)
data class CameraSession(
val sessionId: String,
val operatorId: String,
val cameraType: String,
val startTime: Long,
var isActive: Boolean = true,
var webRTCConnected: Boolean = false
)
sealed class SocketEvent {
data class RegisterAndroid(val deviceId: String, val deviceInfo: DeviceInfo) : SocketEvent()
data class CameraRequest(val sessionId: String, val operatorId: String, val cameraType: String) : SocketEvent()
data class CameraResponse(val sessionId: String, val accepted: Boolean) : SocketEvent()
data class WebRTCOffer(val sessionId: String, val offer: String) : SocketEvent()
data class WebRTCAnswer(val sessionId: String, val answer: String) : SocketEvent()
}
```
### 🔐 РАЗРЕШЕНИЯ (AndroidManifest.xml):
```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.microphone" android:required="true" />
```
### 📚 DEPENDENCIES (build.gradle):
```gradle
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.7.0'
implementation 'androidx.activity:activity-ktx:1.8.2'
// Socket.IO для WebSocket соединения
implementation 'io.socket:socket.io-client:2.1.0'
// WebRTC для видеопотока
implementation 'org.webrtc:google-webrtc:1.0.32006'
// Camera2 API
implementation 'androidx.camera:camera-core:1.3.1'
implementation 'androidx.camera:camera-camera2:1.3.1'
implementation 'androidx.camera:camera-lifecycle:1.3.1'
implementation 'androidx.camera:camera-view:1.3.1'
// JSON парсинг
implementation 'com.google.code.gson:gson:2.10.1'
// Корутины
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// RecyclerView
implementation 'androidx.recyclerview:recyclerview:1.3.2'
// Work Manager для фоновых задач
implementation 'androidx.work:work-runtime-ktx:2.9.0'
}
```
### 🏗️ ОСНОВНЫЕ КЛАССЫ
#### 1. MainActivity.kt - Основная логика:
```kotlin
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var socketService: SocketService
private lateinit var sessionAdapter: SessionAdapter
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
// Инициализация UI
// Проверка разрешений
// Настройка RecyclerView для сессий
// Подключение к SocketService
}
private fun connectToServer() {
val serverUrl = binding.etServerUrl.text.toString()
socketService.connect(serverUrl)
}
private fun showCameraRequestDialog(request: CameraRequest) {
CameraRequestDialog.newInstance(request).show(supportFragmentManager, "camera_request")
}
}
```
#### 2. SocketService.kt - WebSocket соединение:
```kotlin
class SocketService : Service() {
private lateinit var socket: Socket
private val binder = LocalBinder()
fun connect(serverUrl: String) {
socket = IO.socket(serverUrl)
socket.connect()
registerDevice()
setupEventListeners()
}
private fun registerDevice() {
val deviceInfo = DeviceInfo(
model = Build.MODEL,
androidVersion = Build.VERSION.RELEASE,
appVersion = BuildConfig.VERSION_NAME,
availableCameras = CameraManager.getAvailableCameraTypes()
)
socket.emit("register:android", gson.toJson(RegisterAndroid(deviceId, deviceInfo)))
}
private fun setupEventListeners() {
socket.on("camera:request") { args ->
val request = gson.fromJson(args[0].toString(), CameraRequest::class.java)
// Отправить broadcast для показа диалога
}
}
}
```
#### 3. CameraManager.kt - Управление камерами:
```kotlin
class CameraManager(private val context: Context) {
private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as android.hardware.camera2.CameraManager
private var currentCameraId: String? = null
private var captureSession: CameraCaptureSession? = null
fun getAvailableCameraTypes(): List<String> {
val cameras = mutableListOf<String>()
try {
for (cameraId in cameraManager.cameraIdList) {
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
val facing = characteristics.get(CameraCharacteristics.LENS_FACING)
when (facing) {
CameraCharacteristics.LENS_FACING_BACK -> cameras.add("back")
CameraCharacteristics.LENS_FACING_FRONT -> cameras.add("front")
}
// Проверка на wide и telephoto
}
} catch (e: Exception) {
Log.e("CameraManager", "Error getting cameras", e)
}
return cameras
}
@SuppressLint("MissingPermission")
fun startCamera(cameraType: String, surface: Surface) {
val cameraId = getCameraIdForType(cameraType) ?: return
cameraManager.openCamera(cameraId, cameraStateCallback, null)
}
}
```
#### 4. WebRTCManager.kt - WebRTC соединения:
```kotlin
class WebRTCManager(private val context: Context) {
private lateinit var peerConnectionFactory: PeerConnectionFactory
private var peerConnection: RTCPeerConnection? = null
private var localVideoSource: VideoSource? = null
fun initialize() {
val initializationOptions = PeerConnectionFactory.InitializationOptions.builder(context)
.setEnableInternalTracer(false)
.createInitializationOptions()
PeerConnectionFactory.initialize(initializationOptions)
val options = PeerConnectionFactory.Options()
peerConnectionFactory = PeerConnectionFactory.builder()
.setOptions(options)
.createPeerConnectionFactory()
}
fun createOffer(sessionId: String) {
val mediaConstraints = MediaConstraints()
peerConnection?.createOffer(object : SdpObserver {
override fun onCreateSuccess(sessionDescription: SessionDescription) {
// Отправить offer через WebSocket
}
}, mediaConstraints)
}
fun handleAnswer(sessionId: String, answer: SessionDescription) {
peerConnection?.setRemoteDescription(SimpleSdpObserver(), answer)
}
}
```
### 🔄 WORKFLOW ПРИЛОЖЕНИЯ
1. **Запуск приложения:**
- Проверка разрешений (CAMERA, AUDIO, INTERNET)
- Генерация уникального Device ID
- Определение доступных камер устройства
- Инициализация WebRTC
2. **Подключение к серверу:**
- Подключение Socket.IO к указанному URL
- Регистрация устройства с отправкой характеристик
- Ожидание подтверждения регистрации
- Запуск Foreground Service для фоновой работы
3. **Обработка запроса камеры:**
- Получение события "camera:request" от сервера
- Показ диалога пользователю с информацией об операторе
- При согласии - отправка "camera:response" с accepted: true
- Инициализация WebRTC соединения
4. **WebRTC соединение:**
- Создание RTCPeerConnection
- Настройка локального видеопотока с указанной камеры
- Обмен offer/answer/ice-candidates с оператором
- Начало передачи видеопотока
5. **Управление сессией:**
- Отображение активных сессий в RecyclerView
- Обработка команд переключения камеры
- Завершение сессии по команде оператора или пользователя
- Очистка ресурсов WebRTC
### ⚙️ НАСТРОЙКИ И КОНФИГУРАЦИЯ
#### SharedPreferences ключи:
```kotlin
object PreferenceKeys {
const val SERVER_URL = "server_url"
const val DEVICE_ID = "device_id"
const val AUTO_ACCEPT_REQUESTS = "auto_accept_requests"
const val CAMERA_QUALITY = "camera_quality"
const val NOTIFICATION_ENABLED = "notification_enabled"
}
```
#### Настройки WebRTC:
```kotlin
val iceServers = listOf(
RTCIceServer.builder("stun:stun.l.google.com:19302").build(),
RTCIceServer.builder("stun:stun1.l.google.com:19302").build()
)
val rtcConfig = RTCConfiguration(iceServers).apply {
tcpCandidatePolicy = RTCConfiguration.TcpCandidatePolicy.DISABLED
bundlePolicy = RTCConfiguration.BundlePolicy.MAXBUNDLE
rtcpMuxPolicy = RTCConfiguration.RtcpMuxPolicy.REQUIRE
}
```
### 🐛 ОБРАБОТКА ОШИБОК
```kotlin
sealed class AppError {
object NetworkError : AppError()
object CameraPermissionDenied : AppError()
object CameraNotAvailable : AppError()
object WebRTCConnectionFailed : AppError()
data class SocketError(val message: String) : AppError()
data class UnknownError(val throwable: Throwable) : AppError()
}
class ErrorHandler {
fun handleError(error: AppError, context: Context) {
when (error) {
is AppError.NetworkError -> showNetworkError(context)
is AppError.CameraPermissionDenied -> showPermissionDialog(context)
is AppError.WebRTCConnectionFailed -> restartWebRTC()
// и т.д.
}
}
}
```
### 📋 ТЕСТИРОВАНИЕ
1. **Запуск backend сервера**: `cd backend && node src/server.js`
2. **Веб-демо оператора**: `http://localhost:3001`
3. **Подключение Android**: указать URL `http://192.168.1.100:3001`
4. **Тестовые сценарии**:
- Регистрация устройства
- Запрос доступа к камере от веб-демо
- Переключение между камерами
- Разрыв и восстановление соединения
### 🚀 ФИНАЛЬНЫЕ ТРЕБОВАНИЯ
**Создай полный рабочий проект со всеми перечисленными файлами, который:**
- ✅ Компилируется без ошибок на API 24+
- ✅ Корректно подключается к backend серверу
- ✅ Отображает запросы операторов в диалогах
- ✅ Передает видеопоток через WebRTC
- ✅ Поддерживает переключение камер
- ✅ Работает в фоне с уведомлениями
- ✅ Имеет современный Material Design UI
- ✅ Обрабатывает все ошибки и исключения
**Backend server URL для тестирования**: `http://localhost:3001` или `http://192.168.1.100:3001`
---
### 📝 ДОПОЛНИТЕЛЬНЫЕ ПРИМЕЧАНИЯ
- Используй современный Kotlin синтаксис с корутинами
- Применяй MVVM архитектуру с LiveData/StateFlow
- Все строки выноси в strings.xml с поддержкой русского языка
- Добавь логирование всех важных событий
- Используй Material Design 3 компоненты
- Обеспечь backward compatibility с API 24
- Добавь комментарии к сложной логике WebRTC и Camera2
**Этот промпт содержит все необходимые технические детали для создания полнофункционального Android приложения GodEye Signal Center!**