Почему база данных реального времени ServerValue.TIMESTAMP записывает с таким большим смещением?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Почему база данных реального времени ServerValue.TIMESTAMP записывает с таким большим смещением?

Сообщение Anonymous »

Я реализую функцию онлайн-присутствия в приложении для Android, периодически записывая пульс, пока клиент активен. Для этого я использую временную метку RTDB. Но записанные данные в будущем будут порядка ~76 секунд.
Возможно, я не понимаю, как на самом деле работает эта временная метка RTDB. На этом скриншоте это именно тот момент, когда было написано. Справа время по ntp-серверу nist.time.gov; в центре находится еще одна страница, показывающая представление времени Unix для справки; слева — пульс, записанный с помощью ServerValue.TIMESTAMP; а ниже приведен журнал, показывающий смещение времени из dbRef.database.getReference(".info/serverTimeOffset").
Изображение

Эта запись была сделана с использованием реального устройства, а не эмулятора. Ниже приведен скриншот, показывающий, что часы устройства также синхронизированы со временем ntp-сервера.
Изображение

Код, выполняющий запись:

Код: Выделить всё

@HiltViewModel
class MainViewModel @Inject constructor(
private val prefsStore: PrefsStore,
private val currentUserManager: CurrentUserManager
) : ViewModel() {

/**Current user*/
private var currentUserJob: Job? = null
private var authJob: Job? = null
private val _mainUiState = MutableStateFlow(MainUiState())
val currentUserUiState = _mainUiState.asStateFlow()
private var presencaJob: Job? = null
private var heartbeatJob: Job? = null

init {
listenAuth()
}

fun listenAuth() {
authJob?.cancel()
authJob = viewModelScope.launch {
currentUserManager.listenAuth().onStart {
_mainUiState.update {
MainUiState(
isTimeOut = it.isTimeOut,
isLoading = true
)
}
}.collect { firebaseUser ->
logl(firebaseUser?.uid)
currentUserJob?.cancel()
when {
firebaseUser == null          -> _mainUiState.update {
MainUiState(
isTimeOut = it.isTimeOut,
signFlow = SignFlow.NeedLogin
)
}
!firebaseUser.isEmailVerified -> _mainUiState.update {
MainUiState(
isTimeOut = it.isTimeOut,
signFlow = SignFlow.NeedVerifyEmail
)
}
else                          -> listenCurrentUser(firebaseUser.uid)
}
}
}
}

fun listenCurrentUser(uid: UsuarioUid) {
currentUserJob = viewModelScope.launch {
currentUserManager.listenCurrentUser(uid).catch {
logout()
currentUserJob?.cancel()
logl("listenCurrentUser: catch:${it.message}")
}.collect { usuario ->
logl("listenCurrentUser: user>$usuario")
if (presencaJob?.isActive != true) listenPresenca(usuario.uid)
_mainUiState.update {
MainUiState(
isTimeOut = it.isTimeOut,
currentDrawerItemList = when (usuario.maxProfile) {
Profile.Gestor, Profile.GestorMestre -> if (usuario.empresaMap.isNotEmpty()) gestorDrawerItemList else consumidorDrawerItemList
Profile.Consumidor                   -> consumidorDrawerItemList
else                                 ->  emptyList()
},
signFlow = if (usuario == Usuario()) SignFlow.NeedRegisterDb else SignFlow.None,
usuario = usuario
)
}
}
}
}

fun listenPresenca(uid: DatabaseKey){
presencaJob?.cancel()
presencaJob = viewModelScope.launch {
currentUserManager.listenPresenca(uid = uid).collect {deviceId->
deviceId?.let {
if (heartbeatJob?.isActive != true) startHeartbeat(
uid = uid,
deviceId = deviceId
)
}
}
}
}

fun startHeartbeat(uid: String, deviceId: String) {
heartbeatJob?.cancel()
heartbeatJob = viewModelScope.launch {
while (isActive) {
currentUserManager.updateHeartbeat(uid,deviceId)
delay(30_000L)
}
}
}
override fun onCleared() {
heartbeatJob?.cancel()
super.onCleared()
}
}

override suspend fun updateHeartbeat(
uid: DatabaseKey,
deviceId: String
) {
dbRef.database.getReference(".info/serverTimeOffset").addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(s: DataSnapshot) {
val offset = s.getValue(Long::class.java) ?: 0L
Log.d(TAG, "serverTimeOffset = $offset ms.")
}

override fun onCancelled(e: DatabaseError) {}
})
dbRef.child(Nodes.USUARIOS_PRESENCA).child(uid).child("connections").child(deviceId).setValue(ServerValue.TIMESTAMP).await()
}
Итак, возникает вопрос: если время устройства синхронизировано, разве не должна быть синхронизирована и эта запись временной метки?
Хотелось бы понять:
  • Почему RTDB записывает будущую временную метку по отношению к текущему моменту по NTP-серверам?
  • Почему такое большое время разница?
  • У моего клиента проблемы? Что это может быть?
  • Как это исправить, чтобы не было разницы более чем в одну минуту?


Подробнее здесь: https://stackoverflow.com/questions/798 ... -large-off
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»