From 3ced3c74cf4c76ca7e5153de7d88f07672eee431 Mon Sep 17 00:00:00 2001 From: dongliang Date: Thu, 30 Apr 2026 21:42:06 +0930 Subject: [PATCH] =?UTF-8?q?fix:=20OTA=20=E5=BC=B9=E7=AA=97=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=9D=A1=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 进度条宽度用 post{} 延迟设置,确保容器已布局(width>0) 2. 进度回调限频 200ms,避免主线程过载 3. 用 runOnUiThread 替代 launch(Main),更简单可靠 4. 各状态切换加日志 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../java/com/xiaoqu/watch/app/MainActivity.kt | 17 +++++++---- .../watch/ui/widget/UpdateDialogView.kt | 29 +++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt b/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt index c07d327..fb3ca8c 100644 --- a/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt +++ b/app/src/main/java/com/xiaoqu/watch/app/MainActivity.kt @@ -209,10 +209,13 @@ class MainActivity : AppCompatActivity() { /** 待下载的更新 URL */ private var pendingUpdateUrl: String? = null + /** 上次进度更新时间(限制频率,避免主线程过载) */ + private var lastProgressUpdate = 0L /** 开始下载并安装 APK */ private fun startDownloadAndInstall() { val url = pendingUpdateUrl ?: return + Timber.d("OTA: 开始下载安装流程, url=%s", url) updateManager.isUpdating = true // 保持屏幕常亮 screenController.turnOn() @@ -221,19 +224,23 @@ class MainActivity : AppCompatActivity() { activityScope.launch { val file = updateManager.downloadApk(url) { progress, bytes -> - // 进度回调在 IO 线程,切回主线程更新 UI - launch(kotlinx.coroutines.Dispatchers.Main) { - updateDialog.updateProgress(progress, bytes) + // 限制进度更新频率:最多每 200ms 更新一次 UI + val now = System.currentTimeMillis() + if (now - lastProgressUpdate >= 200 || progress >= 100) { + lastProgressUpdate = now + runOnUiThread { + updateDialog.updateProgress(progress, bytes) + } } } // 回到主线程处理结果 kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) { if (file != null) { - // 下载成功 → 触发安装 + Timber.d("OTA: 下载完成,触发安装") updateManager.installApk(file) } else { - // 下载失败 → 显示错误 + Timber.d("OTA: 下载失败") updateManager.isUpdating = false updateDialog.showError() } diff --git a/app/src/main/java/com/xiaoqu/watch/ui/widget/UpdateDialogView.kt b/app/src/main/java/com/xiaoqu/watch/ui/widget/UpdateDialogView.kt index 87cda86..b58f6ae 100644 --- a/app/src/main/java/com/xiaoqu/watch/ui/widget/UpdateDialogView.kt +++ b/app/src/main/java/com/xiaoqu/watch/ui/widget/UpdateDialogView.kt @@ -7,6 +7,7 @@ import android.view.View import android.widget.FrameLayout import android.widget.TextView import com.xiaoqu.watch.R +import timber.log.Timber /** * OTA 更新弹窗 View(全屏覆盖) @@ -59,18 +60,23 @@ class UpdateDialogView @JvmOverloads constructor( tvProgress.visibility = View.GONE btnAction.visibility = View.VISIBLE btnAction.text = "立即更新" + Timber.d("OTA弹窗: 显示发现新版本") } /** 显示"下载中"状态 */ fun showDownloading() { + visibility = View.VISIBLE tvIcon.text = "\ueb2c" tvTitle.text = "请勿关机!" tvDesc.visibility = View.VISIBLE tvDesc.text = "正在升级系统..." progressContainer.visibility = View.VISIBLE tvProgress.visibility = View.VISIBLE + tvProgress.text = "0%" 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) { if (percent >= 0) { - // 已知进度:显示百分比 - val params = progressBar.layoutParams - params.width = (progressContainer.width * percent / 100).coerceAtLeast(0) - progressBar.layoutParams = params + setProgressPercent(percent) tvProgress.text = "${percent}%" } else { // 未知进度:显示已下载大小 @@ -101,10 +104,26 @@ class UpdateDialogView @JvmOverloads constructor( tvProgress.visibility = View.GONE btnAction.visibility = View.VISIBLE btnAction.text = "重新下载" + Timber.d("OTA弹窗: 显示错误 %s", message) } /** 隐藏弹窗 */ fun hide() { 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 + } + } + } }