添加版本更新弹窗

This commit is contained in:
林若思 2026-01-05 10:11:13 +08:00
parent 3143f4007e
commit 9e7d8ebb48
8 changed files with 259 additions and 18 deletions

View File

@ -56,6 +56,7 @@ import com.zs.smarthuman.utils.DangerousUtils
import com.zs.smarthuman.utils.UnityPlayerHolder
import com.zs.smarthuman.utils.ViewSlideAnimator
import com.zs.smarthuman.viewmodel.MainViewModel
import com.zs.smarthuman.widget.VersionUpdateDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -93,6 +94,8 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
private val audioFormat = AudioFormat.ENCODING_PCM_16BIT
private var mVerticalAnimator: ViewSlideAnimator? = null
private var versionUpdateDialog: VersionUpdateDialog? = null
override fun getViewBinding(): ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
override fun initView() {
UnityPlayerHolder.getInstance().initialize(this)
@ -101,6 +104,7 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
.setDirection(ViewSlideAnimator.Direction.VERTICAL)
.setAnimationDuration(300)
.build()
}
override fun initData() {
@ -168,9 +172,12 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
when (it) {
is ApiResult.Error -> {}
is ApiResult.Success<VersionUpdateResp> -> {
if (it.data.versionCode > BuildConfig.VERSION_CODE)
{//有新版本
if (it.data.versionCode > BuildConfig.VERSION_CODE) {//有新版本
versionUpdateDialog = VersionUpdateDialog(this, it.data)
versionUpdateDialog?.show()
lifecycleScope.launch(Dispatchers.IO) {
downloadApk(it.data.downloadUrl)
}
}
}
}
@ -190,7 +197,8 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
voiceInfo = mutableListOf<VoiceBeanResp>().apply {
add(
VoiceBeanResp(
audioUrl = UserInfoManager.userInfo?.wakeUpAudioUrl ?: "https://static.seerteach.net/aidialogue/systemVoice/aliyun-nv.mp3"
audioUrl = UserInfoManager.userInfo?.wakeUpAudioUrl
?: "https://static.seerteach.net/aidialogue/systemVoice/aliyun-nv.mp3"
)
)
}
@ -235,9 +243,11 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
VoiceState.WAIT_SPEECH -> {
}
VoiceState.RECORDING -> {
startRecording()
}
VoiceState.PLAYING_PROMPT -> {}
VoiceState.PLAYING_BACKEND -> {}
VoiceState.UPLOADING -> {}
@ -340,7 +350,11 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
if (isRecording) return
if (audioRecord == null && !initMicrophone()) return
try { audioRecord?.startRecording() } catch (e: IllegalStateException) { recreateAudioRecord(); return }
try {
audioRecord?.startRecording()
} catch (e: IllegalStateException) {
recreateAudioRecord(); return
}
isRecording = true
lifecycleScope.launch(Dispatchers.IO) {
@ -359,7 +373,6 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
}
private fun recreateAudioRecord() {
stopRecording()
try {
@ -403,8 +416,8 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
word: String,
audioUrl: String
) {
val wakeupUrl = UserInfoManager.userInfo?.wakeUpAudioUrl ?:
"https://static.seerteach.net/aidialogue/systemVoice/aliyun-nv.mp3"
val wakeupUrl = UserInfoManager.userInfo?.wakeUpAudioUrl
?: "https://static.seerteach.net/aidialogue/systemVoice/aliyun-nv.mp3"
if (audioUrl != wakeupUrl) return
@ -487,24 +500,24 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
.toDownloadFlow(destPath)
.onProgress {
lifecycleScope.launch(Dispatchers.Main) {
versionUpdateDialog?.updateProgress(it.progress)
}
}.catch {
lifecycleScope.launch(Dispatchers.Main) {
versionUpdateDialog?.dismiss()
}
}.collect {
//下载完成
if (AppUtils.isAppRoot()) {
lifecycleScope.launch(Dispatchers.Main) {
DangerousUtils.installAppSilent(it, "-r")
versionUpdateDialog?.dismiss()
}
} else {
lifecycleScope.launch(Dispatchers.Main) {
AppUtils.installApp(it)
versionUpdateDialog?.dismiss()
}
}

View File

@ -0,0 +1,65 @@
package com.zs.smarthuman.widget
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.viewbinding.ViewBinding
import com.zs.smarthuman.R
import kotlin.let
/**
* @author lrs
* @date 2025/4/12 19:35
* @description 基础dialog
*/
abstract class BaseDialog<T : ViewBinding>(context: Context) : Dialog(context,R.style.LightDialog) {
lateinit var binding: T
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = getViewBinding()
setContentView(binding.root)
initView()
}
protected abstract fun getViewBinding(): T
override fun show() {
this.window?.setFlags(
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
)
super.show()
window?.let {
fullScreenImmersive(it.decorView)
it.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
it.setDimAmount(0.85f)
}
//设置dialog弹窗宽高
val params: WindowManager.LayoutParams = window!!.attributes
params.height = ConstraintLayout.LayoutParams.MATCH_PARENT
params.width = ConstraintLayout.LayoutParams.MATCH_PARENT
window?.attributes = params
}
@SuppressLint("ObsoleteSdkInt")
private fun fullScreenImmersive(view: View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val uiOptions = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN)
view.systemUiVisibility = uiOptions
}
}
abstract fun initView()
}

View File

@ -0,0 +1,24 @@
package com.zs.smarthuman.widget
import android.content.Context
import com.zs.smarthuman.bean.VersionUpdateResp
import com.zs.smarthuman.databinding.DialogVersionUpdateBinding
/**
* @description:
* @author: lrs
* @date: 2026/1/5 9:41
*/
class VersionUpdateDialog(context: Context, val versionUpdateResp: VersionUpdateResp) :
BaseDialog<DialogVersionUpdateBinding>(context) {
override fun getViewBinding(): DialogVersionUpdateBinding =
DialogVersionUpdateBinding.inflate(layoutInflater)
override fun initView() {
binding.tvDesc.text = versionUpdateResp.updateLog
}
fun updateProgress(current: Int){
binding.pb.progress = current
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp" />
<gradient
android:angle="270"
android:endColor="#E0CBFE"
android:startColor="#FFFFFF" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置背景色(蓝色) -->
<item android:id="@android:id/background">
<shape>
<solid android:color="@color/white" />
<corners android:radius="20dp" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<gradient
android:endColor="#DCA5FE"
android:startColor="#7E7DFC" />
<corners android:radius="20dp" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/view_content_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="40dp"
android:background="@drawable/bg_version_update_dialog"
app:layout_constraintDimensionRatio="H,284:321"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_rocket"
app:layout_constraintWidth_percent="0.75" />
<ImageView
android:id="@+id/iv_rocket"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/icon_rocket"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="H,64:109"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.2"
app:layout_constraintWidth_percent="0.17" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="版本更新中"
android:textColor="#333333"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="@id/view_content_layout"
app:layout_constraintStart_toStartOf="@id/view_content_layout"
app:layout_constraintTop_toBottomOf="@id/iv_rocket" />
<TextView
android:id="@+id/tv_second_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginTop="6dp"
android:text="新版本更新内容如下:"
android:textColor="#333333"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/view_content_layout"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginHorizontal="25dp"
android:layout_marginVertical="3dp"
android:text="优化内容修复bug"
android:textColor="#4C4C4C"
android:textSize="10sp"
app:layout_constraintBottom_toTopOf="@id/pb"
app:layout_constraintEnd_toEndOf="@id/view_content_layout"
app:layout_constraintStart_toStartOf="@id/view_content_layout"
app:layout_constraintTop_toBottomOf="@id/tv_second_title" />
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginBottom="10dp"
android:max="100"
android:progress="50"
android:progressDrawable="@drawable/version_update_progress"
app:layout_constraintBottom_toTopOf="@id/tv_bottom_desc"
app:layout_constraintEnd_toEndOf="@id/view_content_layout"
app:layout_constraintStart_toStartOf="@id/view_content_layout"
app:layout_constraintWidth_percent="0.5" />
<TextView
android:id="@+id/tv_bottom_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="请耐心等候..."
android:textColor="#A3A3A3"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@id/view_content_layout"
app:layout_constraintEnd_toEndOf="@id/view_content_layout"
app:layout_constraintStart_toStartOf="@id/view_content_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -17,4 +17,15 @@
<item name="android:windowIsTranslucent">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="LightDialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item >
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan
</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>