10 changed files with 537 additions and 68 deletions
@ -0,0 +1,67 @@
|
||||
package com.utun.chat.data |
||||
|
||||
import android.content.Context |
||||
import android.hardware.Sensor |
||||
import android.hardware.SensorEvent |
||||
import android.hardware.SensorEventListener |
||||
import android.hardware.SensorManager |
||||
import kotlinx.coroutines.flow.MutableStateFlow |
||||
import kotlinx.coroutines.flow.StateFlow |
||||
|
||||
/** |
||||
* Датчик приближения: отслеживает «поднесли к уху» (near) / «отвели» (far). |
||||
* |
||||
* Используется во время звонка на разговорном динамике (EARPIECE), чтобы заблокировать |
||||
* экран, когда телефон у уха, и разблокировать, когда его отвели. Не требует |
||||
* runtime-разрешений. На устройствах без датчика — тихий no-op (WARN в лог). |
||||
*/ |
||||
class ProximityManager(private val context: Context) { |
||||
|
||||
private val sensorManager: SensorManager = |
||||
context.getSystemService(Context.SENSOR_SERVICE) as SensorManager |
||||
private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) |
||||
|
||||
private val _near = MutableStateFlow(false) |
||||
val near: StateFlow<Boolean> = _near |
||||
|
||||
private var listener: SensorEventListener? = null |
||||
private var started = false |
||||
|
||||
/** Возвращает true, если датчик присутствует и удалось зарегистрировать слушатель. */ |
||||
val available: Boolean |
||||
get() = sensor != null |
||||
|
||||
fun start() { |
||||
if (started) return |
||||
started = true |
||||
val s = sensor |
||||
if (s == null) { |
||||
LogManager.addLog("WARN", "Proximity", "no proximity sensor on this device") |
||||
return |
||||
} |
||||
val l = object : SensorEventListener { |
||||
override fun onSensorChanged(event: SensorEvent) { |
||||
val nearNow = event.values[0] < event.sensor.maximumRange |
||||
if (_near.value != nearNow) { |
||||
_near.value = nearNow |
||||
LogManager.addLog("INFO", "Proximity", |
||||
"${if (nearNow) "NEAR" else "FAR"} v=${event.values[0]} max=${event.sensor.maximumRange}") |
||||
} |
||||
} |
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {} |
||||
} |
||||
listener = l |
||||
sensorManager.registerListener(l, s, SensorManager.SENSOR_DELAY_NORMAL) |
||||
LogManager.addLog("INFO", "Proximity", "started (maxRange=${s.maximumRange})") |
||||
} |
||||
|
||||
fun stop() { |
||||
if (!started) return |
||||
started = false |
||||
listener?.let { sensorManager.unregisterListener(it) } |
||||
listener = null |
||||
_near.value = false |
||||
LogManager.addLog("INFO", "Proximity", "stopped") |
||||
} |
||||
} |
||||
Loading…
Reference in new issue