feat: 应用初始化模块 - 崩溃恢复与时间更新

新增:
- CrashHandler 崩溃日志记录+杀进程(系统自动重启Launcher)

修改:
- WatchApplication 注册 CrashHandler
- NavBarHelper 新增 updateTime() 方法
- HomeFragment 添加每秒时间更新定时器

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-04-27 14:56:23 +09:30
parent c7ae11a574
commit fb884ea816
4 changed files with 71 additions and 9 deletions

View File

@@ -0,0 +1,37 @@
package com.xiaoqu.watch.app
import android.content.Context
import timber.log.Timber
import kotlin.system.exitProcess
/**
* 全局崩溃处理器
* 捕获未处理的异常,记录崩溃日志后杀进程
* Launcher 模式下系统会自动重启应用,无需主动设置重启
*
* 注册时机WatchApplication.onCreate
*/
class CrashHandler(private val context: Context) : Thread.UncaughtExceptionHandler {
/** 系统默认的异常处理器(备用) */
private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
/** 注册为全局异常处理器 */
fun init() {
Thread.setDefaultUncaughtExceptionHandler(this)
Timber.d("CrashHandler 已注册")
}
/**
* 处理未捕获的异常
* 1. 记录崩溃日志Timber
* 2. 杀进程,让系统自动重启 Launcher
*/
override fun uncaughtException(thread: Thread, throwable: Throwable) {
Timber.e(throwable, "应用崩溃 [线程: ${thread.name}]")
// 杀进程,系统检测到 Launcher 退出后会自动重启
android.os.Process.killProcess(android.os.Process.myPid())
exitProcess(1)
}
}

View File

@@ -4,23 +4,25 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber
/**
* 应用入口(@HiltAndroidApp 触发 Hilt 代码生成)
*
* 初始化序列(必须保持 < 500ms
* 1. Timber 日志
* 2. CrashHandler 崩溃恢复
* 其他初始化延迟到 MainActivity/HomeFragment
*/
@HiltAndroidApp
class WatchApplication : Application() {
override fun onCreate() {
super.onCreate()
// 1. Timber 初始化
// 1. Timber 日志初始化
Timber.plant(Timber.DebugTree())
// 2-9 其他初始化在后续模块中逐步添加
// LogManager.init()
// CrashHandler.init()
// DeviceRepository.collectDeviceInfo()
// DeviceMonitor.start()
// ClockManager.start()
// WakeLockHelper.acquire()
// OtaManager.checkOnStartup()
// 2. 崩溃处理器(记录日志 + 杀进程,系统自动重启 Launcher
CrashHandler(this).init()
Timber.d("WatchApplication initialized")
}

View File

@@ -23,6 +23,8 @@ import com.xiaoqu.watch.util.DateUtil
import com.xiaoqu.watch.util.DeviceUtil
import com.xiaoqu.watch.util.NetworkUtil
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -73,6 +75,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
// 绑定测试按钮
setupButtons()
// 启动时间更新定时器(每秒刷新 NavBar 时间)
startTimeUpdater()
// 监听系统状态事件
observeSystemEvents()
}
@@ -173,6 +178,16 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
}
}
/** 每秒更新 NavBar 时间显示,跟随 Fragment 生命周期自动取消 */
private fun startTimeUpdater() {
viewLifecycleOwner.lifecycleScope.launch {
while (isActive) {
NavBarHelper.updateTime(binding.root)
delay(1000)
}
}
}
/** 监听系统状态事件电量、蓝牙<E78999><EFBC89><EFBFBD>更新 NavBar 和状态显示 */
private fun observeSystemEvents() {
viewLifecycleOwner.lifecycleScope.launch {

View File

@@ -103,6 +103,14 @@ object NavBarHelper {
))
}
/**
* 更新时间显示(首页模式下每秒调用)
* @param rootView 包含 layout_nav_bar 的根视图
*/
fun updateTime(rootView: View) {
rootView.findViewById<TextView>(R.id.navTitle)?.text = DateUtil.formatTimeShort()
}
/** 为 TextView 设置 iconfont 字体 */
private fun applyIconFont(rootView: View, viewId: Int, typeface: Typeface) {
rootView.findViewById<TextView>(viewId)?.typeface = typeface