hi-client/lib/app/modules/kr_splash/controllers/kr_splash_controller.dart
Rust dee7f0a591 优化部分安卓机型可能存在连接超时等问题新增日志排查
(cherry picked from commit e0fcc27f28f27321a49115df86507e3ac55e8ef8)
2025-11-02 02:46:36 -08:00

762 lines
34 KiB
Dart
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:get/get.dart';
import 'dart:convert';
import 'dart:io' show Platform, SocketException;
import 'dart:math';
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:kaer_with_panels/app/utils/kr_network_check.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/app/utils/kr_secure_storage.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart';
import 'package:kaer_with_panels/app/common/app_config.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import 'package:kaer_with_panels/app/services/kr_device_info_service.dart';
import 'package:kaer_with_panels/app/services/api_service/kr_auth_api.dart';
import 'package:kaer_with_panels/app/model/enum/kr_request_type.dart';
import 'package:kaer_with_panels/app/utils/kr_secure_storage.dart';
import 'package:kaer_with_panels/app/services/kr_subscribe_service.dart';
import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:flutter/material.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/modules/kr_home/controllers/kr_home_controller.dart';
import 'package:kaer_with_panels/app/modules/kr_home/models/kr_home_views_status.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:kaer_with_panels/app/utils/kr_init_log_collector.dart';
class KRSplashController extends GetxController {
// 🔧 新增:初始化日志收集器
final _initLog = KRInitLogCollector();
// 加载状态
final RxBool kr_isLoading = true.obs;
// 错误状态
final RxBool kr_hasError = false.obs;
// 错误信息
final RxString kr_errorMessage = ''.obs;
/// 订阅服务
final KRSubscribeService kr_subscribeService = KRSubscribeService();
// 倒计时
// final count = 0.obs;
// 是否正在加载
final isLoading = true.obs;
// // 是否初始化成功
// final isInitialized = false.obs;
// 启动开始时间(用于计算总耗时)
late final DateTime _startTime;
late DateTime _stepStartTime;
@override
void onInit() {
super.onInit();
// 记录启动开始时间
_startTime = DateTime.now();
_stepStartTime = _startTime;
// 使用 print 确保日志一定会输出
print('[SPLASH_TIMING] ═══════════════════════════════════════');
print('[SPLASH_TIMING] 🎬 KRSplashController onInit 被调用了!');
print('[SPLASH_TIMING] ⏰ 启动开始时间: ${_startTime.toIso8601String()}');
print('[SPLASH_TIMING] ═══════════════════════════════════════');
KRLogUtil.kr_i('[SPLASH_TIMING] ═══════════════════════════════════════', tag: 'SplashController');
KRLogUtil.kr_i('[SPLASH_TIMING] 🎬 启动页控制器 onInit', tag: 'SplashController');
KRLogUtil.kr_i('[SPLASH_TIMING] ═══════════════════════════════════════', tag: 'SplashController');
// 🔧 修复1.0:新增 - DEBUG模式下清理旧数据
// ⚠️ 仅在DEBUG模式下执行防止误删生产环境用户数据
if (kDebugMode) {
KRLogUtil.kr_i('🧹 DEBUG模式准备清理旧本地存储数据', tag: 'SplashController');
_kr_clearOldLocalData();
}
// 🔧 修复1应用启动时清理域名检测静态状态
print('🧹 清理域名检测状态...');
KRDomain.kr_resetDomainState();
// 🔧 P2优化网站配置和设备登录在后台执行不阻塞主流程
print('🌐 启动后台任务:网站配置加载...');
KRLogUtil.kr_i('🌐 后台任务:网站配置和设备登录', tag: 'SplashController');
_kr_initSiteConfig(); // 不等待完成,在后台执行
// 🔧 关键修复:先初始化日志收集器,再开始主流程
if (kDebugMode) {
print('🔧 初始化日志收集器...');
}
_initializeAndStart();
}
/// 🔧 新增:初始化日志收集器并启动主流程
Future<void> _initializeAndStart() async {
try {
// 等待日志收集器初始化完成
await _initLog.initialize();
_initLog.logPhaseStart('应用启动');
_initLog.log('KRSplashController.onInit 被调用', tag: 'Splash');
if (kDebugMode) {
print('✅ 日志收集器初始化完成');
print('🔧 立即开始主初始化流程...');
}
// 开始主初始化流程
_kr_initialize();
} catch (e) {
if (kDebugMode) {
print('❌ 日志收集器初始化失败: $e,继续执行主流程');
}
// 即使日志收集器失败,也要继续主流程
_kr_initialize();
}
}
// 记录步骤耗时的辅助方法
void _logStepTiming(String stepName) {
final now = DateTime.now();
final stepDuration = now.difference(_stepStartTime);
final totalDuration = now.difference(_startTime);
final stepMs = stepDuration.inMilliseconds;
final totalMs = totalDuration.inMilliseconds;
print('[SPLASH_TIMING] ⏱️ $stepName 耗时: ${stepMs}ms | 累计: ${totalMs}ms');
KRLogUtil.kr_i('[SPLASH_TIMING] ⏱️ $stepName 耗时: ${stepMs}ms | 累计: ${totalMs}ms', tag: 'SplashController');
_stepStartTime = now; // 更新步骤开始时间
}
/// 初始化网站配置(后台执行,不阻塞主流程)
Future<void> _kr_initSiteConfig() async {
print('[SPLASH_TIMING] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
print('[SPLASH_TIMING] 🌐 开始初始化网站配置...');
print('[SPLASH_TIMING] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
KRLogUtil.kr_i('[SPLASH_TIMING] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
KRLogUtil.kr_i('[SPLASH_TIMING] 🌐 初始化网站配置...', tag: 'SplashController');
KRLogUtil.kr_i('[SPLASH_TIMING] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
try {
// 🔧 Android 15 优化延长超时保护到25秒匹配网络请求超时20秒 + 5秒缓冲
await Future.any([
_executeSiteConfigInit(),
Future.delayed(const Duration(seconds: 25), () {
throw TimeoutException('网站配置加载超时25秒');
}),
]);
} on TimeoutException catch (e) {
print('⏱️ 网站配置加载超时,应用将使用默认配置: $e');
KRLogUtil.kr_w('⏱️ 网站配置加载超时: $e', tag: 'SplashController');
} catch (e) {
print('❌ 网站配置初始化异常: $e');
KRLogUtil.kr_e('❌ 网站配置初始化异常: $e', tag: 'SplashController');
}
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
}
/// 执行网站配置初始化
Future<void> _executeSiteConfigInit() async {
print('📞 准备调用 KRSiteConfigService().initialize()...');
final success = await KRSiteConfigService().initialize();
final crispId = await KRSiteConfigService().getCrispId();
print('📞 KRSiteConfigService().initialize() 返回: $success');
if (success) {
final config = AppConfig.getInstance();
config.kr_website_id = crispId;
print('📞 KRSiteConfigService().initialize() 返回: $crispId');
print('AppConfig website_id 已更新为: ${config.kr_website_id}');
// print('[SPLASH_TIMING] ✅ 网站配置初始化成功');
// await _kr_checkAndPerformDeviceLogin();
} else {
print('⚠️ 网站配置初始化失败,将使用默认配置');
KRLogUtil.kr_w('⚠️ 网站配置初始化失败,将使用默认配置', tag: 'SplashController');
}
}
/// 检查并执行设备登录(后台执行,有超时保护)
Future<void> _kr_checkAndPerformDeviceLogin() async {
try {
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
print('🔍 检查是否支持设备登录...');
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
final siteConfigService = KRSiteConfigService();
// 检查是否启用设备登录
final isDeviceLoginEnabled = siteConfigService.isDeviceLoginEnabled();
print('📱 设备登录状态: ${isDeviceLoginEnabled ? "已启用" : "未启用"}');
KRLogUtil.kr_i('📱 设备登录状态: $isDeviceLoginEnabled', tag: 'SplashController');
if (!isDeviceLoginEnabled) {
print('⚠️ 设备登录未启用,跳过自动登录');
KRLogUtil.kr_w('⚠️ 设备登录未启用', tag: 'SplashController');
return;
}
print('✅ 设备登录已启用,开始初始化设备信息...');
// 🔧 Android 15 优化延长设备登录超时到15秒匹配网络请求超时
await Future.any([
_executeDeviceLogin(),
Future.delayed(const Duration(seconds: 15), () {
throw TimeoutException('设备登录超时15秒');
}),
]);
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
} on TimeoutException catch (e) {
print('⏱️ 设备登录超时,应用将继续启动: $e');
KRLogUtil.kr_w('⏱️ 设备登录超时: $e', tag: 'SplashController');
} catch (e, stackTrace) {
print('❌ 设备登录检查异常: $e');
print('📚 堆栈跟踪: $stackTrace');
KRLogUtil.kr_e('❌ 设备登录检查异常: $e', tag: 'SplashController');
}
}
/// 执行设备登录
Future<void> _executeDeviceLogin() async {
// 初始化设备信息服务
await KRDeviceInfoService().initialize();
print('🔐 开始执行设备登录...');
KRLogUtil.kr_i('🔐 开始执行设备登录', tag: 'SplashController');
// 执行设备登录
final authApi = KRAuthApi();
final result = await authApi.kr_deviceLogin();
result.fold(
(error) {
print('❌ 设备登录失败: ${error.msg}');
KRLogUtil.kr_e('❌ 设备登录失败: ${error.msg}', tag: 'SplashController');
},
(token) async {
print('✅ 设备登录成功!');
print('🎫 Token: ${token.substring(0, min(20, token.length))}...');
KRLogUtil.kr_i('✅ 设备登录成功', tag: 'SplashController');
// 使用 saveUserInfo 保存完整的用户信息
// 设备登录使用特殊的账号标识,登录类型设为邮箱(后续可以绑定真实账号)
final deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
await KRAppRunData.getInstance().kr_saveUserInfo(
token,
'device_$deviceId', // 使用设备ID作为临时账号
KRLoginType.kr_email, // 默认登录类型
null, // 设备登录无需区号
);
print('💾 用户信息已保存包括Token');
print('✅ 已标记为登录状态');
KRLogUtil.kr_i('✅ 设备登录流程完成', tag: 'SplashController');
},
);
}
Future<void> _kr_initialize() async {
try {
_initLog.logPhaseStart('主初始化流程');
_initLog.log('开始执行 _kr_initialize', tag: 'Splash');
KRLogUtil.kr_i('🔧 开始执行 _kr_initialize', tag: 'SplashController');
// 🔧 Android 15 优化添加总体超时保护15秒更快响应
await Future.any([
_executeInitialization(),
Future.delayed(const Duration(seconds: 15), () {
throw TimeoutException('初始化超时15秒内未完成');
}),
]);
_initLog.logPhaseEnd('主初始化流程', success: true);
} on TimeoutException catch (e) {
// 🔧 P2优化超时错误提供更友好的提示
KRLogUtil.kr_e('⏱️ 初始化超时: $e', tag: 'SplashController');
print('⏱️ 初始化超时,直接跳转到主页');
// 超时后直接跳转到主页,让用户可以手动重试
// Get.offAllNamed(Routes.KR_MAIN);
HIDialog.show(
message: '初始化超时,请检查网络或重试',
confirmText: '重试',
preventBackDismiss: true,
onConfirm: () async {
await _kr_initialize(); // 递归重试
},
);
return;
} on SocketException catch (e) {
// 🔧 P2优化网络连接错误
KRLogUtil.kr_e('❌ 网络连接错误: $e', tag: 'SplashController');
_handleError('网络连接失败', '请检查您的网络连接是否正常,然后重试。');
} on DioException catch (e) {
// 🔧 P2优化HTTP请求错误
KRLogUtil.kr_e('❌ HTTP请求错误: ${e.type} - ${e.message}', tag: 'SplashController');
final errorMsg = _getDioErrorMessage(e);
_handleError('服务请求失败', errorMsg);
} catch (e) {
// 🔧 P2优化其他未知错误
KRLogUtil.kr_e('❌ 未知初始化异常: $e', tag: 'SplashController');
_handleError('初始化失败', '应用启动时发生错误,请尝试重启应用或清除缓存。');
}
}
/// 🔧 Android 15 新增:最小化初始化(降级策略)
/// 确保即使网络失败,应用也能启动到可用状态
Future<void> _executeMinimalInitialization() async {
try {
_initLog.logPhaseStart('降级初始化Minimal Initialization');
_initLog.logWarning('网络初始化失败,执行降级策略', tag: 'Splash');
KRLogUtil.kr_i('🛡️ 执行最小化初始化(降级模式)', tag: 'SplashController');
if (kDebugMode) {
print('🛡️ 执行最小化初始化(降级模式)');
}
// 1. 设置默认域名(确保应用有可用域名)
try {
_initLog.log('步骤1: 设置默认域名', tag: 'Minimal');
if (KRDomain.kr_currentDomain.isEmpty && KRDomain.kr_baseDomains.isNotEmpty) {
KRDomain.kr_currentDomain = KRDomain.kr_baseDomains[0];
_initLog.logSuccess('设置默认域名: ${KRDomain.kr_currentDomain}', tag: 'Minimal');
KRLogUtil.kr_i('✅ 设置默认域名: ${KRDomain.kr_currentDomain}', tag: 'SplashController');
if (kDebugMode) {
print('✅ 设置默认域名: ${KRDomain.kr_currentDomain}');
}
} else {
_initLog.log('当前域名: ${KRDomain.kr_currentDomain}', tag: 'Minimal');
}
} catch (e) {
_initLog.logError('设置默认域名失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ 设置默认域名失败: $e', tag: 'SplashController');
}
// 2. 初始化 SingBox核心功能不依赖网络
try {
_initLog.log('步骤2: 初始化 SingBox', tag: 'Minimal');
await KRSingBoxImp.instance.init().timeout(
const Duration(seconds: 3),
onTimeout: () {
_initLog.logWarning('SingBox 初始化超时(3秒)', tag: 'Minimal');
KRLogUtil.kr_w('SingBox 初始化超时', tag: 'SplashController');
if (kDebugMode) {
print('⏱️ SingBox 初始化超时');
}
},
);
_initLog.logSuccess('SingBox 初始化完成', tag: 'Minimal');
KRLogUtil.kr_i('✅ SingBox 初始化完成', tag: 'SplashController');
if (kDebugMode) {
print('✅ SingBox 初始化完成');
}
} catch (e) {
_initLog.logError('SingBox 初始化失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ SingBox 初始化失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('⚠️ SingBox 初始化失败: $e');
}
}
// 3. 尝试加载本地用户信息(不依赖网络)
try {
_initLog.log('步骤3: 加载本地用户信息', tag: 'Minimal');
await KRAppRunData.getInstance().kr_initializeUserInfo().timeout(
const Duration(seconds: 2),
onTimeout: () {
_initLog.logWarning('用户信息加载超时(2秒)', tag: 'Minimal');
KRLogUtil.kr_w('用户信息加载超时', tag: 'SplashController');
if (kDebugMode) {
print('⏱️ 用户信息加载超时');
}
},
);
_initLog.logSuccess('本地用户信息加载完成', tag: 'Minimal');
KRLogUtil.kr_i('✅ 本地用户信息加载完成', tag: 'SplashController');
if (kDebugMode) {
print('✅ 本地用户信息加载完成');
}
} catch (e) {
_initLog.logError('用户信息加载失败', tag: 'Minimal', error: e);
KRLogUtil.kr_w('⚠️ 用户信息加载失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('⚠️ 用户信息加载失败: $e');
}
}
_initLog.logPhaseEnd('降级初始化Minimal Initialization', success: true);
_initLog.log('应用将以降级模式启动用户将看到基本UI', tag: 'Minimal');
_initLog.log('预期显示:订阅卡片 + 连接选项', tag: 'Minimal');
KRLogUtil.kr_i('✅ 最小化初始化完成,应用将以降级模式启动', tag: 'SplashController');
if (kDebugMode) {
print('✅ 最小化初始化完成,应用将以降级模式启动');
}
if (kDebugMode) {
print('📱 用户将看到基本UI订阅卡片 + 连接选项)');
}
// 🔧 最小化初始化也不关闭日志
// await _initLog.finalize(); // ❌ 注释掉
if (kDebugMode && _initLog.getLogFilePath() != null) {
print('📁 初始化日志文件(保持打开): ${_initLog.getLogFilePath()}');
}
} catch (e) {
_initLog.logError('最小化初始化也失败', tag: 'Minimal', error: e);
KRLogUtil.kr_e('❌ 最小化初始化也失败: $e', tag: 'SplashController');
if (kDebugMode) {
print('❌ 最小化初始化也失败: $e');
}
// 即使降级初始化失败也不关闭日志
// await _initLog.finalize(); // ❌ 注释掉
}
}
/// 处理错误并显示
void _handleError(String title, String message) {
kr_hasError.value = true;
kr_errorMessage.value = '$title\n\n$message';
}
/// 获取Dio错误的友好提示
String _getDioErrorMessage(DioException e) {
switch (e.type) {
case DioExceptionType.connectionTimeout:
case DioExceptionType.sendTimeout:
case DioExceptionType.receiveTimeout:
return '请求超时,请检查网络连接后重试。';
case DioExceptionType.badResponse:
final statusCode = e.response?.statusCode;
if (statusCode == 404) {
return '服务地址未找到404请联系管理员。';
} else if (statusCode == 500) {
return '服务器内部错误500请稍后重试。';
} else if (statusCode == 401 || statusCode == 403) {
return '访问被拒绝($statusCode),请检查配置。';
}
return '服务器返回错误($statusCode),请稍后重试。';
case DioExceptionType.cancel:
return '请求已取消';
case DioExceptionType.connectionError:
return '无法连接到服务器,请检查网络设置。';
default:
return '网络请求失败,请检查网络后重试。';
}
}
// 🔧 P0修复将原来的初始化逻辑提取到单独方法
Future<void> _executeInitialization() async {
_initLog.log('🔍 开始执行核心初始化流程', tag: 'Init');
// 只在手机端检查网络权限
if (Platform.isIOS || Platform.isAndroid) {
_initLog.log('📱 检测到移动平台,检查网络权限', tag: 'Init');
KRLogUtil.kr_i('📱 移动平台,检查网络权限...', tag: 'SplashController');
try {
_initLog.log('开始网络权限检查超时8秒', tag: 'Init');
// 🔧 Android 15 优化:网络权限检查添加 8 秒超时
final bool hasNetworkPermission = await KRNetworkCheck.kr_initialize(
Get.context!,
onPermissionGranted: () async {
_initLog.logSuccess('网络权限已授予', tag: 'Init');
await _kr_continueInitialization();
},
).timeout(
const Duration(seconds: 8),
onTimeout: () {
_initLog.logWarning('网络权限检查超时8秒', tag: 'Init');
KRLogUtil.kr_w('⏱️ 网络权限检查超时,执行降级初始化', tag: 'SplashController');
return false;
},
);
if (!hasNetworkPermission) {
// 🔧 Android 15 优化:权限检查失败时执行降级策略而非显示错误
_initLog.logWarning('网络权限检查失败或超时,执行降级初始化', tag: 'Init');
KRLogUtil.kr_w('⚠️ 网络权限检查失败或超时,执行降级初始化', tag: 'SplashController');
await _executeMinimalInitialization();
Get.offAllNamed(Routes.KR_MAIN);
return;
}
_initLog.logSuccess('网络权限检查通过', tag: 'Init');
} catch (e) {
_initLog.logError('网络权限检查异常,执行降级初始化', tag: 'Init', error: e);
KRLogUtil.kr_w('⚠️ 网络权限检查异常: $e,执行降级初始化', tag: 'SplashController');
await _executeMinimalInitialization();
Get.offAllNamed(Routes.KR_MAIN);
return;
}
} else {
// 非手机端直接继续初始化
_initLog.log('💻 检测到桌面平台,直接执行初始化', tag: 'Init');
KRLogUtil.kr_i('💻 桌面平台,直接执行初始化', tag: 'SplashController');
await _kr_continueInitialization();
}
}
Future<void> _kr_continueInitialization() async {
try {
_initLog.logSeparator();
_initLog.log('🚀 启动页主流程开始', tag: 'Continue');
_initLog.logSeparator();
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
KRLogUtil.kr_i('🚀 启动页主流程开始...', tag: 'SplashController');
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
// 🔧 Android 15 优化:网络连接检查改为非阻塞
if (Platform.isIOS || Platform.isAndroid) {
_initLog.log('📱 检查网络连接状态超时5秒', tag: 'Continue');
KRLogUtil.kr_i('📱 检查网络连接...', tag: 'SplashController');
try {
// 添加5秒超时保护
final bool isConnected = await KRNetworkCheck.kr_checkNetworkConnection().timeout(
const Duration(seconds: 5),
onTimeout: () {
_initLog.logWarning('网络连接检查超时5秒继续初始化', tag: 'Continue');
KRLogUtil.kr_w('⏱️ 网络连接检查超时,继续初始化', tag: 'SplashController');
return true; // 超时时允许继续
},
);
if (isConnected) {
_initLog.logSuccess('网络连接正常', tag: 'Continue');
KRLogUtil.kr_i('✅ 网络连接正常', tag: 'SplashController');
} else {
// 🔧 Android 15 优化:网络未连接也允许继续,改为警告而非错误
_initLog.logWarning('网络未连接,应用将以离线模式启动', tag: 'Continue');
KRLogUtil.kr_w('⚠️ 网络未连接,应用将以离线模式启动', tag: 'SplashController');
}
} catch (e) {
// 🔧 Android 15 优化:网络检查异常不阻塞启动
_initLog.logError('网络检查异常,继续初始化', tag: 'Continue', error: e);
KRLogUtil.kr_w('⚠️ 网络检查异常: $e,继续初始化', tag: 'SplashController');
}
} else {
_initLog.log('💻 桌面平台,跳过网络连接检查', tag: 'Continue');
KRLogUtil.kr_i('💻 桌面平台,跳过网络连接检查', tag: 'SplashController');
}
// 网络检查完成后执行设备登录(始终支持)
_logStepTiming('开始设备登录检查');
// 5⃣ 执行设备登录
final success = await KRAppRunData.getInstance().kr_checkAndPerformDeviceLogin();
if (!success) {
// 设备登录失败 → 提示用户重试
HIDialog.show(
message: '设备登录失败,请检查网络或重试',
confirmText: '重试',
preventBackDismiss: true,
onConfirm: () async {
await _kr_initialize(); // 递归重试
},
);
return;
}
_logStepTiming('设备登录检查完成');
// 初始化配置
_initLog.log('⚙️ 开始初始化应用配置(域名加载等)', tag: 'Continue');
KRLogUtil.kr_i('⚙️ 开始初始化应用配置...', tag: 'SplashController');
await AppConfig().initConfig(
onSuccess: () async {
// 配置初始化成功,继续后续步骤
_initLog.logSuccess('应用配置初始化成功', tag: 'Continue');
KRLogUtil.kr_i('✅ 应用配置初始化成功,继续后续步骤', tag: 'SplashController');
await _kr_continueAfterConfig();
},
);
} catch (e) {
// 🔧 Android 15 优化:配置初始化失败时执行降级策略
_initLog.logError('启动页初始化异常,执行降级策略', tag: 'Continue', error: e);
KRLogUtil.kr_w('⚠️ 启动页初始化异常,执行降级策略: $e', tag: 'SplashController');
await _executeMinimalInitialization();
Get.offAllNamed(Routes.KR_MAIN);
}
}
// 配置初始化成功后的后续步骤
Future<void> _kr_continueAfterConfig() async {
try {
// 用户信息初始化完成后,立即初始化订阅服务
print('[SPLASH_TIMING] 🔄 开始初始化订阅服务...');
KRLogUtil.kr_i('[SPLASH_TIMING] 🔄 开始初始化订阅服务', tag: 'SplashController');
_kr_ensureSubscribeServiceInitialized();
// 初始化SingBox
_logStepTiming('开始SingBox初始化');
await KRSingBoxImp.instance.init();
_logStepTiming('SingBox初始化完成');
// 验证登录状态是否已正确设置
final loginStatus = KRAppRunData.getInstance().kr_isLogin.value;
final token = KRAppRunData.getInstance().kr_token;
final hasToken = token != null && token.isNotEmpty;
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
print('🎯 准备进入主页');
print('📊 最终登录状态: $loginStatus');
print('🎫 Token存在: $hasToken');
if (hasToken) {
print('🎫 Token前缀: ${token.substring(0, min(20, token.length))}...');
}
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
KRLogUtil.kr_i('🎯 准备进入主页', tag: 'SplashController');
KRLogUtil.kr_i('📊 最终登录状态: $loginStatus', tag: 'SplashController');
KRLogUtil.kr_i('🎫 Token存在: $hasToken', tag: 'SplashController');
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
// 🔧 记录最终状态到日志
_initLog.logSeparator();
_initLog.log('准备进入主页', tag: 'Splash');
_initLog.log('最终登录状态: $loginStatus', tag: 'Splash');
_initLog.log('Token存在: $hasToken', tag: 'Splash');
_initLog.logSuccess('正常初始化流程完成', tag: 'Splash');
// 🔧 关键修复:不要在这里关闭日志文件!
// 日志文件需要保持打开状态,让 HomeController 也能写入日志
// 日志文件将在 HomeController 初始化完成后关闭
// await _initLog.finalize(); // ❌ 注释掉
if (kDebugMode && _initLog.getLogFilePath() != null) {
print('📁 初始化日志文件(保持打开): ${_initLog.getLogFilePath()}');
}
// 直接导航到主页(无论是否登录,主页会根据登录状态显示不同内容)
_logStepTiming('开始页面导航');
if(loginStatus) {
// 直接导航到主页
Get.offAllNamed(Routes.KR_HOME);
}else {
kr_hasError.value = true;
kr_errorMessage.value = '登录:${AppTranslations.kr_splash.kr_initializationFailed}';
}
_logStepTiming('页面导航完成');
} catch (e) {
// 计算错误时的总耗时
final endTime = DateTime.now();
final totalDuration = endTime.difference(_startTime);
final totalMs = totalDuration.inMilliseconds;
print('❌ 启动失败时间: ${endTime.toIso8601String()}');
print('🕐 启动失败总耗时: ${totalMs}ms (${totalDuration.inSeconds}.${(totalMs % 1000).toString().padLeft(3, '0')}s)');
// 后续步骤失败,显示错误信息
_initLog.logError('启动初始化失败', tag: 'Splash', error: e);
KRLogUtil.kr_e('启动初始化失败: $e', tag: 'SplashController');
KRLogUtil.kr_e('⏰ 启动失败总耗时: ${totalMs}ms', tag: 'SplashController');
kr_hasError.value = true;
kr_errorMessage.value = '${AppTranslations.kr_splash.kr_initializationFailed}$e';
// 🔧 错误情况下也不关闭日志,让后续的错误处理也能写入
// await _initLog.finalize(); // ❌ 注释掉
}
}
/// 确保订阅服务初始化
Future<void> _kr_ensureSubscribeServiceInitialized() async {
try {
// 检查订阅服务状态
final currentStatus = kr_subscribeService.kr_currentStatus.value;
KRLogUtil.kr_i('订阅服务当前状态: $currentStatus', tag: 'SplashController');
if (currentStatus == KRSubscribeServiceStatus.kr_none ||
currentStatus == KRSubscribeServiceStatus.kr_error) {
KRLogUtil.kr_i(
'订阅服务未初始化或错误,开始初始化', tag: 'SplashController');
// 初始化订阅服务并等待完成
// 设置加载状态
KRHomeController().kr_currentListStatus.value = KRHomeViewsListStatus.kr_loading;
try {
await kr_subscribeService.kr_refreshAll();
KRLogUtil.kr_i('订阅服务初始化完成', tag: 'SplashController');
} catch (error) {
KRLogUtil.kr_e('订阅服务初始化失败: $error', tag: 'SplashController');
// 重新抛出异常,让调用方知道初始化失败
KRHomeController().kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
rethrow;
}
} else if (currentStatus == KRSubscribeServiceStatus.kr_loading) {
KRLogUtil.kr_i('订阅服务正在初始化中', tag: 'SplashController');
// 如果正在加载中,等待加载完成
while (kr_subscribeService.kr_currentStatus.value == KRSubscribeServiceStatus.kr_loading) {
await Future.delayed(Duration(milliseconds: 100));
}
KRLogUtil.kr_i('订阅服务加载完成,最终状态: ${kr_subscribeService.kr_currentStatus.value}', tag: 'SplashController');
KRHomeController().kr_currentListStatus.value = KRHomeViewsListStatus.kr_loading;
} else if (currentStatus == KRSubscribeServiceStatus.kr_success) {
KRHomeController().kr_currentListStatus.value = KRHomeViewsListStatus.kr_none;
KRLogUtil.kr_i('订阅服务已成功初始化', tag: 'SplashController');
}
} catch (e) {
KRLogUtil.kr_e('确保订阅服务初始化失败: $e', tag: 'SplashController');
KRHomeController().kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
rethrow;
}
}
// 重试按钮点击事件
void kr_retry() {
kr_hasError.value = false;
kr_errorMessage.value = '';
_kr_initialize();
}
// 🔧 P3优化跳过初始化直接进入主页
void kr_skipInitialization() {
KRLogUtil.kr_i('⏭️ 用户选择跳过初始化', tag: 'SplashController');
print('⏭️ 用户跳过初始化,直接进入主页');
// 重置状态
kr_hasError.value = false;
kr_errorMessage.value = '';
kr_isLoading.value = false;
// 直接跳转到主页
Get.offAllNamed(Routes.KR_MAIN);
}
/// 🔧 修复1.1清理旧的本地存储数据DEBUG模式专用
/// 防止旧的测试账号在新安装时被恢复
Future<void> _kr_clearOldLocalData() async {
try {
KRLogUtil.kr_i('🧹 开始清理旧本地存储数据...', tag: 'SplashController');
// 清理用户信息存储
await KRSecureStorage().kr_deleteData(key: 'USER_INFO');
KRLogUtil.kr_i('✅ 已清理USER_INFO', tag: 'SplashController');
// 清理设备登录状态
await KRSecureStorage().kr_deleteData(key: 'DEVICE_INFO');
KRLogUtil.kr_i('✅ 已清理DEVICE_INFO', tag: 'SplashController');
KRLogUtil.kr_i('✅ 旧本地存储数据已全部清理', tag: 'SplashController');
} catch (e) {
KRLogUtil.kr_w('⚠️ 清理旧数据过程中出错: $e', tag: 'SplashController');
// 继续执行,不阻塞初始化流程
}
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {
super.onClose();
}
}