Files
opendance-android/app/src/main/java/com/opendance/studio/data/AppSettings.kt
T
zijunchiang 264786134c docs: 新增「初次部署(从零跑起来)」;去混淆字符与真实内网信息
- README.md / README.txt 新增初次部署章节:前置条件(JDK 17 / SDK 34 / Gradle 8.9)、
  获取代码与本地配置(local.properties 不入仓)、Debug/Release 构建、装到手机与相机权限、
  连接配置(只连 Windows 客户端,默认 8765 / /pose)、第一次跑通、自检清单、常见问题
- 单测数量按实际(30 项)修正
- 三库同源契约:':=' 写法修回、去掉真实 MariaDB 版本串
- 全文去除易被 Gitea 判为「模棱两可 Unicode」的字符
- 本机 JDK 路径与内网示例地址改占位符 / RFC 5737 文档网段
2026-09-15 21:33:27 +08:00

95 lines
3.3 KiB
Kotlin
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.
package com.opendance.studio.data
import android.content.Context
import androidx.core.content.edit
/**
* 应用设置(SharedPreferences)。
*
* 契约 websocket-keypoints.md §3.3 的 config 字段与这里的前四项一一对应。
*/
class AppSettings(context: Context) {
private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
/** Windows 客户端主机地址 */
var host: String
get() = prefs.getString(KEY_HOST, DEFAULT_HOST) ?: DEFAULT_HOST
set(value) = prefs.edit { putString(KEY_HOST, value.trim()) }
var port: Int
get() = prefs.getInt(KEY_PORT, DEFAULT_PORT)
set(value) = prefs.edit { putInt(KEY_PORT, value.coerceIn(1, 65535)) }
/** 目标帧率(契约 config.targetFps) */
var targetFps: Int
get() = prefs.getInt(KEY_TARGET_FPS, DEFAULT_FPS)
set(value) = prefs.edit { putInt(KEY_TARGET_FPS, value.coerceIn(5, 60)) }
/** 是否镜像画面(契约 flags.bit0 / config.mirror) */
var mirror: Boolean
get() = prefs.getBoolean(KEY_MIRROR, true)
set(value) = prefs.edit { putBoolean(KEY_MIRROR, value) }
/** 仅上半身模式(契约 flags.bit2) */
var upperBodyOnly: Boolean
get() = prefs.getBoolean(KEY_UPPER_BODY, false)
set(value) = prefs.edit { putBoolean(KEY_UPPER_BODY, value) }
/** 分辨率档位,取值见 [Resolutions] */
var resolution: String
get() = prefs.getString(KEY_RESOLUTION, Resolutions.MEDIUM) ?: Resolutions.MEDIUM
set(value) = prefs.edit { putString(KEY_RESOLUTION, value) }
/** 上次连接的设备名(hello 上报用) */
var deviceLabel: String
get() = prefs.getString(KEY_DEVICE_LABEL, "") ?: ""
set(value) = prefs.edit { putString(KEY_DEVICE_LABEL, value) }
/** 自动重连 */
var autoReconnect: Boolean
get() = prefs.getBoolean(KEY_AUTO_RECONNECT, true)
set(value) = prefs.edit { putBoolean(KEY_AUTO_RECONNECT, value) }
fun webSocketUrl(): String = "ws://$host:$port/pose"
companion object {
const val PREFS_NAME = "opendance_settings"
const val DEFAULT_HOST = "192.0.2.100"
const val DEFAULT_PORT = 8765
const val DEFAULT_FPS = 30
private const val KEY_HOST = "host"
private const val KEY_PORT = "port"
private const val KEY_TARGET_FPS = "target_fps"
private const val KEY_MIRROR = "mirror"
private const val KEY_UPPER_BODY = "upper_body_only"
private const val KEY_RESOLUTION = "resolution"
private const val KEY_DEVICE_LABEL = "device_label"
private const val KEY_AUTO_RECONNECT = "auto_reconnect"
}
}
/** 分辨率档位 —— 与契约 config.resolution 的取值格式一致 */
object Resolutions {
const val LOW = "480x360"
const val MEDIUM = "640x480"
const val HIGH = "1280x720"
val ALL = listOf(LOW, MEDIUM, HIGH)
/** 返回 (宽, 高) */
fun parse(value: String): Pair<Int, Int> {
val parts = value.split("x")
val w = parts.getOrNull(0)?.toIntOrNull() ?: 640
val h = parts.getOrNull(1)?.toIntOrNull() ?: 480
return w to h
}
fun label(value: String): String = when (value) {
LOW -> "低(480×360,最省电)"
HIGH -> "高(1280×720,最清晰)"
else -> "中(640×480,推荐)"
}
}