feat: 组件解耦
This commit is contained in:
parent
4712855f6c
commit
0c122b9352
|
|
@ -1,25 +1,23 @@
|
|||
package com.yuanxuan.rokid
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.yuanxuan.rokid.databinding.ActivityMainBinding
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import com.yuanxuan.rokid.device.DeviceServiceManager
|
||||
import com.yuanxuan.rokid.extension.fadeIn
|
||||
import com.yuanxuan.rokid.extension.fadeOut
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private val viewModel by viewModels<MainViewModel>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -45,11 +43,9 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
return if (AppDependencies.deviceServiceManager.instructState.value ==
|
||||
DeviceServiceManager.InstructState.WaitingInstructState
|
||||
) {
|
||||
return if (viewModel.uiState.value.isVoiceInputVisible) {
|
||||
if (event.keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
AppDependencies.deviceServiceManager.quitInstructReceived()
|
||||
viewModel.quitInstructReceived()
|
||||
}
|
||||
true
|
||||
} else {
|
||||
|
|
@ -59,36 +55,17 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
private fun observer() {
|
||||
lifecycleScope.launch {
|
||||
/**
|
||||
* 监听电量
|
||||
*/
|
||||
AppDependencies.deviceServiceManager.batteryPercentage.collect {
|
||||
binding.batteryLevel.text = resources.getString(R.string.status_bar_battery, it)
|
||||
binding.batteryLevelIv.setImageLevel(it)
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
AppDependencies.deviceServiceManager.wifiState.collect {
|
||||
when (it) {
|
||||
is DeviceServiceManager.WifiState.Connected -> binding.wifiIv.setImageLevel(it.level)
|
||||
|
||||
DeviceServiceManager.WifiState.Unconnected -> binding.wifiIv.setImageLevel(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
AppDependencies.deviceServiceManager.instructState.collect {
|
||||
when (it) {
|
||||
DeviceServiceManager.InstructState.None -> {
|
||||
binding.lottieVoiceInput.cancelAnimation()
|
||||
binding.lottieVoiceInput.fadeOut(300)
|
||||
}
|
||||
|
||||
DeviceServiceManager.InstructState.WaitingInstructState -> {
|
||||
binding.lottieVoiceInput.playAnimation()
|
||||
binding.lottieVoiceInput.fadeIn(300)
|
||||
}
|
||||
viewModel.uiState.collect { uiState ->
|
||||
binding.batteryLevel.text =
|
||||
resources.getString(R.string.status_bar_battery, uiState.batteryLevel)
|
||||
binding.batteryLevelIv.setImageLevel(uiState.batteryLevel)
|
||||
binding.wifiIv.setImageLevel(uiState.wifiLevel)
|
||||
if (uiState.isVoiceInputVisible) {
|
||||
binding.lottieVoiceInput.playAnimation()
|
||||
binding.lottieVoiceInput.fadeIn(300)
|
||||
} else {
|
||||
binding.lottieVoiceInput.cancelAnimation()
|
||||
binding.lottieVoiceInput.fadeOut(300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
package com.yuanxuan.rokid
|
||||
|
||||
import androidx.activity.result.launch
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies.deviceServiceManager
|
||||
import com.yuanxuan.rokid.device.DeviceServiceManager
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainViewModel : ViewModel() {
|
||||
|
|
@ -12,6 +16,30 @@ class MainViewModel : ViewModel() {
|
|||
private val _keyEventFlow = MutableSharedFlow<KeyEvent>()
|
||||
val keyEventFlow = _keyEventFlow.asSharedFlow()
|
||||
|
||||
val uiState = combine(
|
||||
deviceServiceManager.batteryPercentage,
|
||||
deviceServiceManager.wifiState,
|
||||
deviceServiceManager.instructState
|
||||
) { battery, wifi, instruct ->
|
||||
MainUiState(
|
||||
batteryLevel = battery,
|
||||
wifiLevel = if (wifi is DeviceServiceManager.WifiState.Connected) wifi.level else 0,
|
||||
isVoiceInputVisible = instruct == DeviceServiceManager.InstructState.WaitingInstructState
|
||||
)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
initialValue = MainUiState(
|
||||
batteryLevel = 0,
|
||||
wifiLevel = 0,
|
||||
isVoiceInputVisible = false
|
||||
),
|
||||
started = SharingStarted.Eagerly,
|
||||
)
|
||||
|
||||
fun quitInstructReceived(){
|
||||
deviceServiceManager.quitInstructReceived()
|
||||
}
|
||||
|
||||
fun onKeyEventDispatched(event: KeyEvent) {
|
||||
viewModelScope.launch {
|
||||
_keyEventFlow.emit(event)
|
||||
|
|
@ -24,4 +52,10 @@ class MainViewModel : ViewModel() {
|
|||
data object Enter : KeyEvent //前滑
|
||||
}
|
||||
|
||||
data class MainUiState(
|
||||
val batteryLevel: Int,
|
||||
val wifiLevel: Int,
|
||||
val isVoiceInputVisible: Boolean,
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@ package com.yuanxuan.rokid
|
|||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import com.yuanxuan.rokid.dependencies.ApplicationDependencyProvider
|
||||
import com.yuanxuan.rokid.keeplive.KeepLiveService
|
||||
import com.yuanxuan.rokid.network.websocket.WebSocketReconnectWorker
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
@ -28,7 +28,7 @@ class RokidApplication : Application() {
|
|||
runCatching {
|
||||
AppDependencies.deviceServiceManager.getSn()
|
||||
}.onSuccess {
|
||||
AppDependencies.webSocketManager.connect()
|
||||
WebSocketReconnectWorker.schedule(this@RokidApplication)
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class DeviceServiceManager(val context: Application) : ConnectivityManager.Netwo
|
|||
/**
|
||||
* 系统电量
|
||||
*/
|
||||
private val _batteryPercentage = MutableStateFlow(-1)
|
||||
private val _batteryPercentage = MutableStateFlow(getBatteryLevel(context))
|
||||
val batteryPercentage = _batteryPercentage.asStateFlow()
|
||||
|
||||
/**
|
||||
|
|
@ -293,6 +293,11 @@ class DeviceServiceManager(val context: Application) : ConnectivityManager.Netwo
|
|||
}
|
||||
}
|
||||
|
||||
private fun getBatteryLevel(context: Context): Int {
|
||||
val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||
return bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||
}
|
||||
|
||||
inner class SysKeyReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val action = intent?.action ?: return
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import java.net.NetworkInterface
|
|||
|
||||
object NetUtils {
|
||||
|
||||
fun getBaseUrl() = "http://${getLocalIPV4address()}.70:7070"
|
||||
// fun getBaseUrl() = "http://${getLocalIPV4address()}.83:8765"
|
||||
// fun getBaseUrl() = "http://${getLocalIPV4address()}.70:7070"
|
||||
fun getBaseUrl() = "http://${getLocalIPV4address()}.52:8765"
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@ class OkHttpWebSocketConnection() : WebSocketListener(), WebSocketConnection {
|
|||
private var client: WebSocket? = null
|
||||
|
||||
@Synchronized
|
||||
override fun connect() {
|
||||
override fun connect(sn: String) {
|
||||
val okHttpClient = OkHttpClient.Builder()
|
||||
.readTimeout(DEFAULT_SEND_TIMEOUT)
|
||||
.pingInterval(PING_INTERVAL_TIME)
|
||||
.build()
|
||||
|
||||
val request = Request.Builder().url(NetUtils.getBaseUrl()).build()
|
||||
val request = Request.Builder().url(NetUtils.getBaseUrl())
|
||||
.addHeader("sn", sn).build()
|
||||
_webSocketConnectionStateFlow.update {
|
||||
WebSocketConnectionState.CONNECTING
|
||||
}
|
||||
|
|
@ -55,6 +56,7 @@ class OkHttpWebSocketConnection() : WebSocketListener(), WebSocketConnection {
|
|||
}
|
||||
|
||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||
_webSocketConnectionStateFlow.update { WebSocketConnectionState.CONNECTED }
|
||||
Timber.d("websocket onOpen")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.yuanxuan.rokid.network.websocket
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface WebSocketConnection {
|
||||
|
|
@ -10,7 +9,7 @@ interface WebSocketConnection {
|
|||
val PING_INTERVAL_TIME = 30.seconds
|
||||
}
|
||||
|
||||
fun connect()
|
||||
fun connect(sn: String)
|
||||
|
||||
fun isDead(): Boolean
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ class WebSocketManager(context: Context, scope: CoroutineScope) {
|
|||
}
|
||||
}
|
||||
|
||||
fun connect() {
|
||||
webSocketConnection.connect()
|
||||
fun connect(sn: String) {
|
||||
webSocketConnection.connect(sn)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class WebSocketReconnectWorker(context: Context, workerParams: WorkerParameters)
|
|||
override fun doWork(): Result {
|
||||
Timber.d("尝试开始重连")
|
||||
AppDependencies.deviceServiceManager.playTTS("开始重连")
|
||||
AppDependencies.webSocketManager.connect()
|
||||
AppDependencies.webSocketManager.connect(AppDependencies.deviceServiceManager.sn)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.yuanxuan.rokid.R
|
||||
import com.yuanxuan.rokid.databinding.FragmentSettingBinding
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class BrightnessFragment : Fragment() {
|
||||
|
|
@ -37,7 +36,6 @@ class BrightnessFragment : Fragment() {
|
|||
binding.tip.text = resources.getString(R.string.setting_brightness_tip)
|
||||
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.brightnessFlow.collect { data ->
|
||||
adapter.submitList(data)
|
||||
|
|
@ -49,12 +47,12 @@ class BrightnessFragment : Fragment() {
|
|||
return@setOnKeyListener if (event.action == KeyEvent.ACTION_UP) {
|
||||
when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT -> {
|
||||
AppDependencies.deviceServiceManager.brightnessAdd()
|
||||
viewModel.brightnessAdd()
|
||||
true
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_DPAD_LEFT -> {
|
||||
AppDependencies.deviceServiceManager.brightnessSubtract()
|
||||
viewModel.brightnessSubtract()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ class HomeFragment : Fragment() {
|
|||
binding.recyclerView.adapter = adapter
|
||||
binding.recyclerView.itemAnimator = null
|
||||
|
||||
lifecycleScope.launch {
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewModel.homeMenuBeans.collect {
|
||||
adapter.submitList(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,4 +47,22 @@ class SettingViewModel : ViewModel() {
|
|||
replay = 1
|
||||
)
|
||||
|
||||
fun brightnessAdd(){
|
||||
AppDependencies.deviceServiceManager.brightnessAdd()
|
||||
}
|
||||
|
||||
fun brightnessSubtract(){
|
||||
AppDependencies.deviceServiceManager.brightnessSubtract()
|
||||
}
|
||||
|
||||
fun volumeAdd(){
|
||||
AppDependencies.deviceServiceManager.volumeAdd()
|
||||
}
|
||||
|
||||
fun volumeSubtract(){
|
||||
AppDependencies.deviceServiceManager.volumeSubtract()
|
||||
}
|
||||
|
||||
fun deviceSn()= AppDependencies.deviceServiceManager.sn
|
||||
|
||||
}
|
||||
|
|
@ -5,14 +5,16 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.yuanxuan.rokid.BuildConfig
|
||||
import com.yuanxuan.rokid.R
|
||||
import com.yuanxuan.rokid.databinding.FragmentSnBinding
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
|
||||
class SnFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentSnBinding
|
||||
private val viewModel by viewModels<SettingViewModel>()
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
@ -26,7 +28,7 @@ class SnFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.sn.text =
|
||||
resources.getString(R.string.device_info_sn, AppDependencies.deviceServiceManager.sn)
|
||||
resources.getString(R.string.device_info_sn, viewModel.deviceSn())
|
||||
binding.appVersion.text =
|
||||
resources.getString(R.string.device_info_app_version, BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.yuanxuan.rokid.R
|
||||
import com.yuanxuan.rokid.databinding.FragmentSettingBinding
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class VolumeFragment : Fragment() {
|
||||
|
|
@ -49,12 +48,12 @@ class VolumeFragment : Fragment() {
|
|||
return@setOnKeyListener if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT -> {
|
||||
AppDependencies.deviceServiceManager.volumeAdd()
|
||||
viewModel.volumeAdd()
|
||||
true
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_DPAD_LEFT -> {
|
||||
AppDependencies.deviceServiceManager.volumeSubtract()
|
||||
viewModel.volumeSubtract()
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue