fix: OTA 弹窗进度条修复
1. 进度条宽度用 post{} 延迟设置,确保容器已布局(width>0)
2. 进度回调限频 200ms,避免主线程过载
3. 用 runOnUiThread 替代 launch(Main),更简单可靠
4. 各状态切换加日志
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,10 +209,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
/** 待下载的更新 URL */
|
/** 待下载的更新 URL */
|
||||||
private var pendingUpdateUrl: String? = null
|
private var pendingUpdateUrl: String? = null
|
||||||
|
/** 上次进度更新时间(限制频率,避免主线程过载) */
|
||||||
|
private var lastProgressUpdate = 0L
|
||||||
|
|
||||||
/** 开始下载并安装 APK */
|
/** 开始下载并安装 APK */
|
||||||
private fun startDownloadAndInstall() {
|
private fun startDownloadAndInstall() {
|
||||||
val url = pendingUpdateUrl ?: return
|
val url = pendingUpdateUrl ?: return
|
||||||
|
Timber.d("OTA: 开始下载安装流程, url=%s", url)
|
||||||
updateManager.isUpdating = true
|
updateManager.isUpdating = true
|
||||||
// 保持屏幕常亮
|
// 保持屏幕常亮
|
||||||
screenController.turnOn()
|
screenController.turnOn()
|
||||||
@@ -221,19 +224,23 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
activityScope.launch {
|
activityScope.launch {
|
||||||
val file = updateManager.downloadApk(url) { progress, bytes ->
|
val file = updateManager.downloadApk(url) { progress, bytes ->
|
||||||
// 进度回调在 IO 线程,切回主线程更新 UI
|
// 限制进度更新频率:最多每 200ms 更新一次 UI
|
||||||
launch(kotlinx.coroutines.Dispatchers.Main) {
|
val now = System.currentTimeMillis()
|
||||||
updateDialog.updateProgress(progress, bytes)
|
if (now - lastProgressUpdate >= 200 || progress >= 100) {
|
||||||
|
lastProgressUpdate = now
|
||||||
|
runOnUiThread {
|
||||||
|
updateDialog.updateProgress(progress, bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回到主线程处理结果
|
// 回到主线程处理结果
|
||||||
kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) {
|
kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
// 下载成功 → 触发安装
|
Timber.d("OTA: 下载完成,触发安装")
|
||||||
updateManager.installApk(file)
|
updateManager.installApk(file)
|
||||||
} else {
|
} else {
|
||||||
// 下载失败 → 显示错误
|
Timber.d("OTA: 下载失败")
|
||||||
updateManager.isUpdating = false
|
updateManager.isUpdating = false
|
||||||
updateDialog.showError()
|
updateDialog.showError()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.view.View
|
|||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.xiaoqu.watch.R
|
import com.xiaoqu.watch.R
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OTA 更新弹窗 View(全屏覆盖)
|
* OTA 更新弹窗 View(全屏覆盖)
|
||||||
@@ -59,18 +60,23 @@ class UpdateDialogView @JvmOverloads constructor(
|
|||||||
tvProgress.visibility = View.GONE
|
tvProgress.visibility = View.GONE
|
||||||
btnAction.visibility = View.VISIBLE
|
btnAction.visibility = View.VISIBLE
|
||||||
btnAction.text = "立即更新"
|
btnAction.text = "立即更新"
|
||||||
|
Timber.d("OTA弹窗: 显示发现新版本")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 显示"下载中"状态 */
|
/** 显示"下载中"状态 */
|
||||||
fun showDownloading() {
|
fun showDownloading() {
|
||||||
|
visibility = View.VISIBLE
|
||||||
tvIcon.text = "\ueb2c"
|
tvIcon.text = "\ueb2c"
|
||||||
tvTitle.text = "请勿关机!"
|
tvTitle.text = "请勿关机!"
|
||||||
tvDesc.visibility = View.VISIBLE
|
tvDesc.visibility = View.VISIBLE
|
||||||
tvDesc.text = "正在升级系统..."
|
tvDesc.text = "正在升级系统..."
|
||||||
progressContainer.visibility = View.VISIBLE
|
progressContainer.visibility = View.VISIBLE
|
||||||
tvProgress.visibility = View.VISIBLE
|
tvProgress.visibility = View.VISIBLE
|
||||||
|
tvProgress.text = "0%"
|
||||||
btnAction.visibility = View.GONE
|
btnAction.visibility = View.GONE
|
||||||
updateProgress(0)
|
// 进度条初始归零
|
||||||
|
setProgressPercent(0)
|
||||||
|
Timber.d("OTA弹窗: 显示下载中")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,10 +86,7 @@ class UpdateDialogView @JvmOverloads constructor(
|
|||||||
*/
|
*/
|
||||||
fun updateProgress(percent: Int, downloadedBytes: Long = 0) {
|
fun updateProgress(percent: Int, downloadedBytes: Long = 0) {
|
||||||
if (percent >= 0) {
|
if (percent >= 0) {
|
||||||
// 已知进度:显示百分比
|
setProgressPercent(percent)
|
||||||
val params = progressBar.layoutParams
|
|
||||||
params.width = (progressContainer.width * percent / 100).coerceAtLeast(0)
|
|
||||||
progressBar.layoutParams = params
|
|
||||||
tvProgress.text = "${percent}%"
|
tvProgress.text = "${percent}%"
|
||||||
} else {
|
} else {
|
||||||
// 未知进度:显示已下载大小
|
// 未知进度:显示已下载大小
|
||||||
@@ -101,10 +104,26 @@ class UpdateDialogView @JvmOverloads constructor(
|
|||||||
tvProgress.visibility = View.GONE
|
tvProgress.visibility = View.GONE
|
||||||
btnAction.visibility = View.VISIBLE
|
btnAction.visibility = View.VISIBLE
|
||||||
btnAction.text = "重新下载"
|
btnAction.text = "重新下载"
|
||||||
|
Timber.d("OTA弹窗: 显示错误 %s", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 隐藏弹窗 */
|
/** 隐藏弹窗 */
|
||||||
fun hide() {
|
fun hide() {
|
||||||
visibility = View.GONE
|
visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置进度条百分比(用 post 确保在布局完成后设置宽度)
|
||||||
|
*/
|
||||||
|
private fun setProgressPercent(percent: Int) {
|
||||||
|
progressContainer.post {
|
||||||
|
val containerWidth = progressContainer.width
|
||||||
|
if (containerWidth > 0) {
|
||||||
|
val barWidth = containerWidth * percent / 100
|
||||||
|
val params = progressBar.layoutParams
|
||||||
|
params.width = barWidth
|
||||||
|
progressBar.layoutParams = params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user