Получение данных об окружении устройства
Обновлено 27 июня 2023
С помощью интерфейса EnvironmentInfoRepository
приложение может получать информацию о состоянии устройства:
- включен ли детский режим;
- в каком состоянии находится экран (активен, заставка, включен режим сна);
- подключен ли HDMI;
- заблокированы камера и микрофон или нет;
- какая версия StarOS.
В демо-приложении использование интерфейса продемонстрировано на вкладке ENV.
Соответствующий код вы найдете классах EnvironmentInfoFragment.kt и EnvironmentInfoViewModel.kt:
EnvironmentInfoFragment.kt
/src/main/ru/sberdevices/pub/demoapp/ui/environmentinfo/EnvironmentInfoFragment.kt
package ru.sberdevices.pub.demoapp.ui.environmentinfo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.collect
import org.koin.androidx.viewmodel.ext.android.viewModel
import ru.sberdevices.services.pub.demoapp.databinding.FragmentEnvironmentInfoBinding
class EnvironmentInfoFragment : Fragment() {
private lateinit var viewBinding: FragmentEnvironmentInfoBinding
private val viewModel by viewModel<EnvironmentInfoViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
viewBinding = FragmentEnvironmentInfoBinding.inflate(layoutInflater, container, false)
return viewBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycleScope.launchWhenCreated {
viewModel.starOsVersionFlow.collect { viewBinding.environmentInfoVersionText.text = it ?: "old os" }
}
lifecycleScope.launchWhenCreated {
viewModel.deviceTypeFlow.collect { viewBinding.environmentInfoDeviceTypeText.text = it?.name ?: "old os" }
}
lifecycleScope.launchWhenCreated {
viewModel.screenStateFlow.collect {
viewBinding.environmentInfoDreamStateText.text = it?.dreamState?.name ?: "old os"
viewBinding.environmentInfoNoScreenModeEnabledText.text =
it?.isNoScreenModeEnabled?.toString() ?: "old os"
}
}
lifecycleScope.launchWhenCreated {
viewModel.userSettingsInfo.collect {
viewBinding.environmentInfoChildModeEnabledText.text = it?.isChildModeEnabled?.toString() ?: "old os"
viewBinding.environmentInfoDeviceLockModeText.text = it?.deviceLockMode?.name ?: "old os"
}
}
lifecycleScope.launchWhenCreated {
viewModel.cameraStateFlow.collect {
viewBinding.cameraStateText.text = it?.name ?: "old os"
}
}
lifecycleScope.launchWhenCreated {
viewModel.micStateFlow.collect {
viewBinding.microphoneStateText.text = it?.name ?: "old os"
}
}
lifecycleScope.launchWhenCreated {
viewModel.isCameraCovered.collect {
viewBinding.cameraCoveredStateText.text = "${it ?: "old os"}"
}
}
viewBinding.assistantServiceText.text = "${viewModel.assistantServiceVersion ?: "unsupported"}"
viewBinding.micCameraStateServiceText.text = "${viewModel.micCameraStateServiceVersion ?: "unsupported"}"
viewBinding.payLibServiceText.text = "${viewModel.paylibServiceVersion ?: "unsupported"}"
viewBinding.messagingServiceText.text = "${viewModel.messagingServiceVersion ?: "unsupported"}"
viewBinding.envInfoServiceText.text = "${viewModel.environmentInfoServiceVersion ?: "unsupported"}"
}
companion object {
fun newInstance() = EnvironmentInfoFragment()
}
}
EnvironmentInfoViewModel.kt
/src/main/ru/sberdevices/pub/demoapp/ui/environmentinfo/EnvironmentInfoViewModel.kt
package ru.sberdevices.pub.demoapp.ui.environmentinfo
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.shareIn
import ru.sberdevices.messaging.Messaging
import ru.sberdevices.services.assistant.PublicAssistantLib
import ru.sberdevices.services.mic.camera.state.MicCameraStateRepository
import ru.sberdevices.services.paylib.PayLib
import ru.sberdevices.services.published.environment.info.EnvironmentInfoRepository
import ru.sberdevices.services.published.environment.info.models.ScreenState
import ru.sberdevices.services.published.environment.info.models.UserSettingsInfo
class EnvironmentInfoViewModel(
private val environmentInfoRepository: EnvironmentInfoRepository,
private val micCameraStateRepository: MicCameraStateRepository,
assistantLib: PublicAssistantLib,
payLib: PayLib,
messaging: Messaging,
) : ViewModel() {
val starOsVersionFlow = flow {
emit(
checkVersionAndInvoke(
getServiceVersion = environmentInfoRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = null,
getValueIfCompatible = environmentInfoRepository::getStarOsVersion
)
)
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val deviceTypeFlow = flow {
emit(
checkVersionAndInvoke(
getServiceVersion = environmentInfoRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = null,
getValueIfCompatible = environmentInfoRepository::getDeviceType
)
)
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val screenStateFlow = flow {
emitAll(checkVersionAndInvoke(
getServiceVersion = environmentInfoRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = flowOf<ScreenState?>(null),
getValueIfCompatible = { environmentInfoRepository.screenStateFlow }
))
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val userSettingsInfo = flow {
emitAll(checkVersionAndInvoke(
getServiceVersion = environmentInfoRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = flowOf<UserSettingsInfo?>(null),
getValueIfCompatible = { environmentInfoRepository.userSettingsInfo }
))
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val cameraStateFlow = flow {
emitAll(checkVersionAndInvoke(
getServiceVersion = micCameraStateRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = flowOf<MicCameraStateRepository.State?>(null),
getValueIfCompatible = { micCameraStateRepository.cameraState }
))
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val micStateFlow = flow {
emitAll(checkVersionAndInvoke(
getServiceVersion = micCameraStateRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = flowOf<MicCameraStateRepository.State?>(null),
getValueIfCompatible = { micCameraStateRepository.micState }
))
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val isCameraCovered = flow {
emitAll(checkVersionAndInvoke(
getServiceVersion = micCameraStateRepository::getVersion,
minServiceVersion = 1,
valueIfIncompatible = flowOf<Boolean?>(null),
getValueIfCompatible = { micCameraStateRepository.isCameraCovered }
))
}.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)
val assistantServiceVersion = assistantLib.getVersion()
val micCameraStateServiceVersion = micCameraStateRepository.getVersion()
val environmentInfoServiceVersion = environmentInfoRepository.getVersion()
val paylibServiceVersion = payLib.getVersion()
val messagingServiceVersion = messaging.getVersion()
private suspend fun <T> checkVersionAndInvoke(
getServiceVersion: () -> Int?,
minServiceVersion: Int,
valueIfIncompatible: T,
getValueIfCompatible: suspend () -> T
): T {
val version = getServiceVersion() ?: return valueIfIncompatible
return if (version >= minServiceVersion) {
getValueIfCompatible()
} else {
valueIfIncompatible
}
}
}
Особенности детского режима
Детский режим работы устройства ограничивает доступ к неподходящему контенту в приложениях. Такой режим можно реализовать следующими способами:
- Если устройство работает в детском режиме, то в приложении становится доступен только детский профиль с соответствующим контентом. В таком профиле пользователь не может оплачивать покупки или переключиться на взрослый профиль. Пример сообщения, которое вы можете показать пользователям при работе в детском режиме: «Доступны только детские профили, так как включен детский режим».
- Если устройство работает в детском режиме, то в приложении нельзя запустить контент 18+ независимо от включенного профиля. Поверх карточек с таким контентом отображается текст: «18+ Включен детский режим».