package com.narutohuo.xindazhou.common.version import android.app.Activity import android.content.Context import android.content.pm.PackageManager import androidx.core.content.pm.PackageInfoCompat import androidx.fragment.app.FragmentActivity import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import com.narutohuo.xindazhou.common.log.LogHelper import com.narutohuo.xindazhou.common.network.ApiManager import com.narutohuo.xindazhou.common.version.datasource.remote.VersionRemoteDataSourceImpl import com.narutohuo.xindazhou.common.version.repository.VersionRepository import com.narutohuo.xindazhou.common.version.ui.UpdateDialogFragment import kotlinx.coroutines.launch /** * 版本更新管理器 * * 封装版本检查的完整逻辑,包括: * - 获取当前版本号 * - 检查服务器版本 * - 显示更新对话框 * - 处理强制更新 * * 使用方式: * ```kotlin * // 在 Application 中初始化 * VersionUpdateManager.init(context) * * // 在 Activity 中检查更新(自动获取版本号) * VersionUpdateManager.checkUpdate(activity) * * // 或者手动指定版本号 * VersionUpdateManager.checkUpdate(activity, platform = 1, versionCode = 100) * ``` */ object VersionUpdateManager { private const val PLATFORM_ANDROID = 1 // 平台类型:1-安卓,2-鸿蒙,3-iOS /** * 初始化版本更新管理器 * * 需要在 Application.onCreate() 中调用 * * @param context 上下文 * @param platform 平台类型(默认 1-安卓) */ fun init(context: Context, platform: Int = PLATFORM_ANDROID) { // 初始化 ApiManager 的 baseUrlProvider(如果还未设置) if (ApiManager.baseUrlProvider == null) { // 这里需要从 ServerConfigManager 获取,但为了避免循环依赖, // 建议在 Application 中先设置 ApiManager.baseUrlProvider LogHelper.w("VersionUpdateManager", "ApiManager.baseUrlProvider 未设置,版本检查可能失败") } } /** * 检查版本更新(自动获取当前版本号) * * @param activity Activity 实例(用于显示对话框和获取版本号) * @param platform 平台类型(默认 1-安卓) * @param onForceUpdateDismiss 强制更新时,用户关闭对话框的回调(可选,默认退出应用) */ fun checkUpdate( activity: FragmentActivity, platform: Int = PLATFORM_ANDROID, onForceUpdateDismiss: (() -> Unit)? = null ) { val currentVersionCode = getCurrentVersionCode(activity) checkUpdate(activity, platform, currentVersionCode, onForceUpdateDismiss) } /** * 检查版本更新(手动指定版本号) * * @param activity Activity 实例(用于显示对话框) * @param platform 平台类型(默认 1-安卓) * @param currentVersionCode 当前版本号 * @param onForceUpdateDismiss 强制更新时,用户关闭对话框的回调(可选,默认退出应用) */ fun checkUpdate( activity: FragmentActivity, platform: Int, currentVersionCode: Int, onForceUpdateDismiss: (() -> Unit)? = null ) { // 使用 LifecycleOwner 的 lifecycleScope,自动管理协程生命周期 activity.lifecycleScope.launch { try { // 创建数据源和 Repository val remoteDataSource = com.narutohuo.xindazhou.common.version.datasource.remote.VersionRemoteDataSourceImpl() val versionRepository = VersionRepository(remoteDataSource) // 检查版本(如果没有版本,返回 null,不影响启动) val versionResponse = versionRepository.checkVersion(platform, currentVersionCode) // 如果有新版本,显示更新对话框 if (versionResponse != null && versionRepository.hasUpdate(versionResponse)) { val dialog = UpdateDialogFragment.create( versionResponse = versionResponse, onDismiss = { // 对话框关闭后的回调 if (versionRepository.isForceUpdate(versionResponse)) { // 强制更新时,如果用户关闭对话框,执行回调或退出应用 if (onForceUpdateDismiss != null) { onForceUpdateDismiss() } else { activity.finish() } } } ) dialog.show(activity.supportFragmentManager, "UpdateDialogFragment") } } catch (e: Exception) { // 版本检查失败不影响应用启动 // 可以记录日志,但不显示错误提示 LogHelper.e("VersionUpdateManager", "版本检查失败", e) } } } /** * 检查版本更新(使用 LifecycleOwner,适用于 Fragment) * * @param lifecycleOwner LifecycleOwner(Activity 或 Fragment) * @param activity Activity 实例(用于显示对话框和获取版本号) * @param platform 平台类型(默认 1-安卓) * @param onForceUpdateDismiss 强制更新时,用户关闭对话框的回调(可选,默认退出应用) */ fun checkUpdate( lifecycleOwner: LifecycleOwner, activity: FragmentActivity, platform: Int = PLATFORM_ANDROID, onForceUpdateDismiss: (() -> Unit)? = null ) { val currentVersionCode = getCurrentVersionCode(activity) lifecycleOwner.lifecycleScope.launch { try { // 创建数据源和 Repository val remoteDataSource = VersionRemoteDataSourceImpl() val versionRepository = VersionRepository(remoteDataSource) // 检查版本(如果没有版本,返回 null,不影响启动) val versionResponse = versionRepository.checkVersion(platform, currentVersionCode) // 如果有新版本,显示更新对话框 if (versionResponse != null && versionRepository.hasUpdate(versionResponse)) { val dialog = UpdateDialogFragment.create( versionResponse = versionResponse, onDismiss = { // 对话框关闭后的回调 if (versionRepository.isForceUpdate(versionResponse)) { // 强制更新时,如果用户关闭对话框,执行回调或退出应用 if (onForceUpdateDismiss != null) { onForceUpdateDismiss() } else { activity.finish() } } } ) dialog.show(activity.supportFragmentManager, "UpdateDialogFragment") } } catch (e: Exception) { // 版本检查失败不影响应用启动 // 可以记录日志,但不显示错误提示 LogHelper.e("VersionUpdateManager", "版本检查失败", e) } } } /** * 获取当前应用的版本号 * * @param context 上下文 * @return 版本号,如果获取失败返回 1 */ fun getCurrentVersionCode(context: Context): Int { return try { val packageManager = context.packageManager val packageInfo = packageManager.getPackageInfo(context.packageName, 0) // 使用 PackageInfoCompat 统一处理,兼容所有版本 PackageInfoCompat.getLongVersionCode(packageInfo).toInt() } catch (e: PackageManager.NameNotFoundException) { // 记录异常 LogHelper.e("VersionUpdateManager", "无法获取版本号", e) 1 // 默认版本号 } } }