新增编译模式下对日志进行输出,并且更新了hive缓存取出后进行连通性判断
Some checks failed
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
Some checks failed
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled
(cherry picked from commit 40f95d0c463c31428c5f25118f59b0c3a60e73ba)
This commit is contained in:
parent
4c5763647d
commit
2b80fcba0d
@ -1081,21 +1081,141 @@ class KRDomain {
|
||||
);
|
||||
}
|
||||
|
||||
/// 从本地加载域名
|
||||
/// 从本地加载域名(方案1:加载后验证可用性)
|
||||
static Future<void> kr_loadBaseDomain() async {
|
||||
KRLogUtil.kr_i('📂 开始从 Hive 加载域名配置', tag: 'KRDomain');
|
||||
final startTime = DateTime.now();
|
||||
|
||||
try {
|
||||
// 🔧 Android 15 关键修复:添加总体超时保护(15秒)
|
||||
await Future.any([
|
||||
_executeLoadAndVerify(),
|
||||
Future.delayed(const Duration(seconds: 15), () {
|
||||
throw TimeoutException('域名加载和验证总超时(15秒)');
|
||||
}),
|
||||
]);
|
||||
} on TimeoutException catch (e) {
|
||||
final duration = DateTime.now().difference(startTime).inSeconds;
|
||||
KRLogUtil.kr_e('⏱️ 域名加载验证超时($duration 秒): $e', tag: 'KRDomain');
|
||||
// 超时时使用默认域名
|
||||
if (kr_baseDomains.isNotEmpty) {
|
||||
kr_currentDomain = kr_baseDomains[0];
|
||||
KRLogUtil.kr_w('⚠️ 超时后使用默认域名: $kr_currentDomain', tag: 'KRDomain');
|
||||
}
|
||||
} catch (e) {
|
||||
final duration = DateTime.now().difference(startTime).inSeconds;
|
||||
KRLogUtil.kr_e('❌ 域名加载异常($duration 秒): $e', tag: 'KRDomain');
|
||||
// 异常时使用默认域名
|
||||
if (kr_baseDomains.isNotEmpty) {
|
||||
kr_currentDomain = kr_baseDomains[0];
|
||||
}
|
||||
}
|
||||
|
||||
final totalDuration = DateTime.now().difference(startTime).inMilliseconds;
|
||||
KRLogUtil.kr_i('✅ 域名加载完成,耗时: ${totalDuration}ms,当前域名: $kr_currentDomain', tag: 'KRDomain');
|
||||
}
|
||||
|
||||
/// 执行域名加载和验证
|
||||
static Future<void> _executeLoadAndVerify() async {
|
||||
// 加载域名列表
|
||||
String? savedDomains = await _storage.kr_readData(key: kr_domainsKey);
|
||||
if (savedDomains != null) {
|
||||
kr_baseDomains = savedDomains.split(',');
|
||||
if (savedDomains != null && savedDomains.isNotEmpty) {
|
||||
kr_baseDomains = savedDomains.split(',').where((d) => d.isNotEmpty).toList();
|
||||
KRLogUtil.kr_i('📋 从 Hive 加载的域名列表: $kr_baseDomains', tag: 'KRDomain');
|
||||
} else {
|
||||
KRLogUtil.kr_w('⚠️ Hive 中没有保存的域名列表,使用默认配置', tag: 'KRDomain');
|
||||
}
|
||||
|
||||
// 加载当前域名
|
||||
String? savedDomain = await _storage.kr_readData(key: kr_domainKey);
|
||||
if (savedDomain != null && kr_baseDomains.contains(savedDomain)) {
|
||||
kr_currentDomain = savedDomain;
|
||||
KRLogUtil.kr_i('📌 从 Hive 加载的当前域名: $savedDomain', tag: 'KRDomain');
|
||||
|
||||
if (savedDomain != null && savedDomain.isNotEmpty && kr_baseDomains.contains(savedDomain)) {
|
||||
// 🔧 Android 15 关键修复:验证 Hive 缓存的域名是否仍然可用
|
||||
KRLogUtil.kr_i('🔍 验证 Hive 缓存域名的可用性: $savedDomain', tag: 'KRDomain');
|
||||
|
||||
try {
|
||||
// 快速验证(3 秒超时)
|
||||
bool isAvailable = await kr_fastCheckDomainAvailability(savedDomain).timeout(
|
||||
const Duration(seconds: 3),
|
||||
onTimeout: () {
|
||||
KRLogUtil.kr_w('⏱️ 域名验证超时(3秒),视为不可用', tag: 'KRDomain');
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
||||
if (isAvailable) {
|
||||
kr_currentDomain = savedDomain;
|
||||
KRLogUtil.kr_i('✅ Hive 缓存域名验证通过,继续使用: $kr_currentDomain', tag: 'KRDomain');
|
||||
return;
|
||||
} else {
|
||||
KRLogUtil.kr_w('❌ Hive 缓存域名不可用: $savedDomain,需要切换', tag: 'KRDomain');
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('❌ 域名验证异常: $e,需要切换', tag: 'KRDomain');
|
||||
}
|
||||
} else {
|
||||
if (savedDomain == null || savedDomain.isEmpty) {
|
||||
KRLogUtil.kr_w('⚠️ Hive 中没有保存的当前域名', tag: 'KRDomain');
|
||||
} else {
|
||||
KRLogUtil.kr_w('⚠️ Hive 缓存的域名 $savedDomain 不在域名列表中', tag: 'KRDomain');
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 Android 15 增强:Hive 域名验证失败,自动选择可用域名
|
||||
KRLogUtil.kr_i('🔄 Hive 域名不可用,开始选择可用域名...', tag: 'KRDomain');
|
||||
|
||||
// 尝试从域名列表中找到可用的域名(每个最多 3 秒)
|
||||
for (String domain in kr_baseDomains) {
|
||||
try {
|
||||
KRLogUtil.kr_i('🧪 测试域名: $domain', tag: 'KRDomain');
|
||||
bool isAvailable = await kr_fastCheckDomainAvailability(domain).timeout(
|
||||
const Duration(seconds: 3),
|
||||
onTimeout: () {
|
||||
KRLogUtil.kr_w('⏱️ 域名 $domain 验证超时(3秒)', tag: 'KRDomain');
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
||||
if (isAvailable) {
|
||||
kr_currentDomain = domain;
|
||||
await kr_saveCurrentDomain();
|
||||
KRLogUtil.kr_i('✅ 找到可用域名: $kr_currentDomain,已保存到 Hive', tag: 'KRDomain');
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ 域名 $domain 验证异常: $e', tag: 'KRDomain');
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有主域名都不可用,快速尝试备用域名(5秒总超时)
|
||||
KRLogUtil.kr_w('⚠️ 所有主域名都不可用,尝试备用域名...', tag: 'KRDomain');
|
||||
try {
|
||||
String? backupDomain = await kr_tryLocalBackupDomains().timeout(
|
||||
const Duration(seconds: 5),
|
||||
onTimeout: () {
|
||||
KRLogUtil.kr_w('⏱️ 备用域名获取超时', tag: 'KRDomain');
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
if (backupDomain != null) {
|
||||
kr_currentDomain = backupDomain;
|
||||
await kr_saveCurrentDomain();
|
||||
KRLogUtil.kr_i('✅ 使用备用域名: $kr_currentDomain', tag: 'KRDomain');
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_w('⚠️ 备用域名获取异常: $e', tag: 'KRDomain');
|
||||
}
|
||||
|
||||
// 最后的兜底:使用列表中的第一个域名(即使不可用)
|
||||
if (kr_baseDomains.isNotEmpty) {
|
||||
kr_currentDomain = kr_baseDomains[0];
|
||||
await kr_saveCurrentDomain();
|
||||
KRLogUtil.kr_w('⚠️ 无法验证任何域名,使用默认域名: $kr_currentDomain', tag: 'KRDomain');
|
||||
} else {
|
||||
KRLogUtil.kr_e('❌ 没有可用的域名配置!', tag: 'KRDomain');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1123,6 +1243,19 @@ class KRDomain {
|
||||
}
|
||||
|
||||
class AppConfig {
|
||||
/// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
/// 初始化日志收集开关
|
||||
/// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
/// 🔧 全局开关:是否启用初始化日志收集
|
||||
/// true:将所有初始化日志写入文件,方便问题诊断
|
||||
/// false:关闭日志收集,减少 I/O 操作
|
||||
///
|
||||
/// 建议:
|
||||
/// - 测试版本、Beta 版本:设置为 true
|
||||
/// - 正式生产版本:根据需要设置为 false(或在遇到问题时临时开启)
|
||||
static const bool enableInitLogCollection = true;
|
||||
|
||||
/// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
/// 加密密钥配置
|
||||
/// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
@ -265,6 +265,14 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
kr_forceSyncConnectionStatus();
|
||||
_checkQuickConnectAutoStart();
|
||||
});
|
||||
|
||||
// 🔧 Android 15 新增:5秒后再次强制更新高度,兜底保护
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (kr_bottomPanelHeight.value < 100) {
|
||||
KRLogUtil.kr_w('检测到底部面板高度异常(${kr_bottomPanelHeight.value}),强制修正', tag: 'HomeController');
|
||||
kr_updateBottomPanelHeight();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -272,11 +280,22 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
void _kr_initLoginStatus() {
|
||||
KRLogUtil.kr_i('初始化登录状态', tag: 'HomeController');
|
||||
|
||||
// 设置超时处理
|
||||
Timer(const Duration(seconds: 10), () {
|
||||
// 🔧 Android 15 紧急修复:8秒超时,更快响应移动网络慢的情况
|
||||
Timer(const Duration(seconds: 8), () {
|
||||
if (kr_currentListStatus.value == KRHomeViewsListStatus.kr_loading) {
|
||||
KRLogUtil.kr_w('订阅服务初始化超时,设置为错误状态', tag: 'HomeController');
|
||||
kr_currentListStatus.value = KRHomeViewsListStatus.kr_error;
|
||||
KRLogUtil.kr_w('⏱️ 订阅服务初始化超时(8秒),强制设置为无数据状态', tag: 'HomeController');
|
||||
// 🔧 Android 15 优化:超时设置为 none 而非 error,避免底部面板显示错误界面
|
||||
kr_currentListStatus.value = KRHomeViewsListStatus.kr_none;
|
||||
// 强制更新底部面板高度,确保显示正常
|
||||
kr_updateBottomPanelHeight();
|
||||
KRLogUtil.kr_i('✅ 已强制切换到默认视图', tag: 'HomeController');
|
||||
}
|
||||
});
|
||||
|
||||
// 🔧 Android 15 新增:3秒警告,帮助诊断
|
||||
Timer(const Duration(seconds: 3), () {
|
||||
if (kr_currentListStatus.value == KRHomeViewsListStatus.kr_loading) {
|
||||
KRLogUtil.kr_w('⚠️ 订阅服务初始化已耗时3秒,可能网络较慢', tag: 'HomeController');
|
||||
}
|
||||
});
|
||||
|
||||
@ -1414,8 +1433,10 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
||||
|
||||
// 更新底部面板高度
|
||||
void kr_updateBottomPanelHeight() {
|
||||
// 🔧 Android 15 优化:加载状态时也允许更新高度,显示加载指示器
|
||||
if (kr_subscribeService.kr_currentStatus ==
|
||||
KRHomeViewsListStatus.kr_loading) {
|
||||
KRHomeViewsListStatus.kr_loading &&
|
||||
kr_currentListStatus.value != KRHomeViewsListStatus.kr_loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -50,81 +50,76 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
|
||||
}
|
||||
|
||||
Widget _kr_buildDefaultView(BuildContext context) {
|
||||
// 使用 GetX 的 .obs 变量来避免重复访问
|
||||
final hasValidSubscription =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value != null;
|
||||
final isTrial = controller.kr_subscribeService.kr_isTrial;
|
||||
final isLastDay = controller.kr_subscribeService.kr_isLastDayOfSubscription;
|
||||
// 🔧 Android 15 增强:增加防御性检查,避免空指针
|
||||
bool hasValidSubscription = false;
|
||||
bool isTrial = false;
|
||||
bool isLastDay = false;
|
||||
|
||||
try {
|
||||
hasValidSubscription = controller.kr_subscribeService.kr_currentSubscribe.value != null;
|
||||
isTrial = controller.kr_subscribeService.kr_isTrial.value;
|
||||
isLastDay = controller.kr_subscribeService.kr_isLastDayOfSubscription.value;
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('获取订阅数据异常: $e', tag: 'HomeBottomPanel');
|
||||
}
|
||||
|
||||
final isNotLoggedIn = controller.kr_currentViewStatus.value ==
|
||||
KRHomeViewsStatus.kr_notLoggedIn;
|
||||
|
||||
KRLogUtil.kr_i('构建默认视图', tag: 'HomeBottomPanel');
|
||||
KRLogUtil.kr_i('是否未登录: $isNotLoggedIn', tag: 'HomeBottomPanel');
|
||||
KRLogUtil.kr_i('是否有有效订阅: $hasValidSubscription', tag: 'HomeBottomPanel');
|
||||
KRLogUtil.kr_i('是否试用: ${isTrial.value}', tag: 'HomeBottomPanel');
|
||||
KRLogUtil.kr_i('是否试用: $isTrial', tag: 'HomeBottomPanel');
|
||||
KRLogUtil.kr_i('当前高度: ${controller.kr_bottomPanelHeight.value}',
|
||||
tag: 'HomeBottomPanel');
|
||||
|
||||
// 🔧 关键修复:统一布局逻辑,确保无论登录状态如何都显示完整UI
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 主要内容区域
|
||||
if (isNotLoggedIn)
|
||||
// 未登录状态下,使用 SingleChildScrollView 让内容自然撑开
|
||||
SingleChildScrollView(
|
||||
// 主要内容区域 - 始终使用 Expanded + ScrollView 确保内容可见
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 🔧 核心修复:无论登录状态,都显示核心卡片(订阅或连接信息)
|
||||
if (hasValidSubscription)
|
||||
// 已订阅:显示连接信息卡片
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeConnectionInfoView(),
|
||||
)
|
||||
else
|
||||
// 未订阅(包括未登录):始终显示订阅卡片
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h, left: 12.w, right: 12.w),
|
||||
child: const KRSubscriptionCard(),
|
||||
),
|
||||
|
||||
// 2. 如果已订阅且是试用,展示试用卡片
|
||||
if (hasValidSubscription && isTrial)
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeTrialCard(),
|
||||
),
|
||||
|
||||
// 3. 如果已订阅且是最后一天,展示最后一天卡片
|
||||
if (hasValidSubscription && isLastDay && !isTrial)
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeLastDayCard(),
|
||||
),
|
||||
|
||||
// 4. 连接选项(分组和国家入口)- 始终显示
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
|
||||
child: const KRHomeConnectionOptionsView(),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
// 已登录状态下,使用固定高度
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 1. 如果已订阅,展示当前连接卡片
|
||||
if (hasValidSubscription)
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeConnectionInfoView())
|
||||
else
|
||||
Container(
|
||||
margin:
|
||||
EdgeInsets.only(top: 12.h, left: 12.w, right: 12.w),
|
||||
child: const KRSubscriptionCard()),
|
||||
|
||||
// 2. 如果已订阅且是试用,展示试用卡片
|
||||
if (hasValidSubscription && isTrial.value)
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeTrialCard(),
|
||||
),
|
||||
|
||||
// 3. 如果已订阅且是最后一天,展示最后一天卡片
|
||||
if (hasValidSubscription && isLastDay.value && !isTrial.value)
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 12.h),
|
||||
child: const KRHomeLastDayCard(),
|
||||
),
|
||||
|
||||
// 4. 连接选项(分组和国家入口)
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
|
||||
child: const KRHomeConnectionOptionsView(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -134,11 +129,50 @@ class KRHomeBottomPanel extends GetView<KRHomeController> {
|
||||
KRLogUtil.kr_i('当前高度: ${controller.kr_bottomPanelHeight.value}',
|
||||
tag: 'HomeBottomPanel');
|
||||
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.green,
|
||||
strokeWidth: 2.0,
|
||||
),
|
||||
// 🔧 Android 15 紧急修复:加载时显示完整的默认内容 + 加载指示器
|
||||
// 而不是只显示一个转圈圈,避免用户看到空白面板
|
||||
return Stack(
|
||||
children: [
|
||||
// 底层:显示默认内容(半透明)
|
||||
Opacity(
|
||||
opacity: 0.5,
|
||||
child: _kr_buildDefaultView(Get.context!),
|
||||
),
|
||||
// 顶层:加载指示器
|
||||
Center(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(16.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Get.context!.theme.cardColor,
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircularProgressIndicator(
|
||||
color: Colors.green,
|
||||
strokeWidth: 3.0,
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
Text(
|
||||
'正在加载...',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Get.context!.theme.textTheme.bodyMedium?.color,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -27,8 +27,12 @@ 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;
|
||||
|
||||
@ -86,9 +90,35 @@ class KRSplashController extends GetxController {
|
||||
KRLogUtil.kr_i('🌐 后台任务:网站配置和设备登录', tag: 'SplashController');
|
||||
_kr_initSiteConfig(); // 不等待完成,在后台执行
|
||||
|
||||
// 立即开始主初始化流程
|
||||
print('🔧 立即开始主初始化流程...');
|
||||
_kr_initialize();
|
||||
// 🔧 关键修复:先初始化日志收集器,再开始主流程
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 记录步骤耗时的辅助方法
|
||||
@ -116,11 +146,11 @@ class KRSplashController extends GetxController {
|
||||
KRLogUtil.kr_i('[SPLASH_TIMING] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'SplashController');
|
||||
|
||||
try {
|
||||
// 🔧 P2优化:为后台任务添加10秒超时保护
|
||||
// 🔧 Android 15 优化:延长超时保护到25秒,匹配网络请求超时(20秒 + 5秒缓冲)
|
||||
await Future.any([
|
||||
_executeSiteConfigInit(),
|
||||
Future.delayed(const Duration(seconds: 10), () {
|
||||
throw TimeoutException('网站配置加载超时(10秒)');
|
||||
Future.delayed(const Duration(seconds: 25), () {
|
||||
throw TimeoutException('网站配置加载超时(25秒)');
|
||||
}),
|
||||
]);
|
||||
} on TimeoutException catch (e) {
|
||||
@ -178,11 +208,11 @@ class KRSplashController extends GetxController {
|
||||
|
||||
print('✅ 设备登录已启用,开始初始化设备信息...');
|
||||
|
||||
// 🔧 P2优化:为设备登录添加8秒超时保护
|
||||
// 🔧 Android 15 优化:延长设备登录超时到15秒,匹配网络请求超时
|
||||
await Future.any([
|
||||
_executeDeviceLogin(),
|
||||
Future.delayed(const Duration(seconds: 8), () {
|
||||
throw TimeoutException('设备登录超时(8秒)');
|
||||
Future.delayed(const Duration(seconds: 15), () {
|
||||
throw TimeoutException('设备登录超时(15秒)');
|
||||
}),
|
||||
]);
|
||||
|
||||
@ -237,15 +267,19 @@ class KRSplashController extends GetxController {
|
||||
|
||||
Future<void> _kr_initialize() async {
|
||||
try {
|
||||
_initLog.logPhaseStart('主初始化流程');
|
||||
_initLog.log('开始执行 _kr_initialize', tag: 'Splash');
|
||||
KRLogUtil.kr_i('🔧 开始执行 _kr_initialize', tag: 'SplashController');
|
||||
|
||||
// 🔧 P0修复:添加总体超时保护(30秒)
|
||||
// 🔧 Android 15 优化:添加总体超时保护(15秒),更快响应
|
||||
await Future.any([
|
||||
_executeInitialization(),
|
||||
Future.delayed(const Duration(seconds: 30), () {
|
||||
throw TimeoutException('初始化超时:30秒内未完成');
|
||||
Future.delayed(const Duration(seconds: 15), () {
|
||||
throw TimeoutException('初始化超时:15秒内未完成');
|
||||
}),
|
||||
]);
|
||||
|
||||
_initLog.logPhaseEnd('主初始化流程', success: true);
|
||||
} on TimeoutException catch (e) {
|
||||
// 🔧 P2优化:超时错误提供更友好的提示
|
||||
KRLogUtil.kr_e('⏱️ 初始化超时: $e', tag: 'SplashController');
|
||||
@ -311,24 +345,51 @@ class KRSplashController extends GetxController {
|
||||
|
||||
// 🔧 P0修复:将原来的初始化逻辑提取到单独方法
|
||||
Future<void> _executeInitialization() async {
|
||||
_initLog.log('🔍 开始执行核心初始化流程', tag: 'Init');
|
||||
|
||||
// 只在手机端检查网络权限
|
||||
if (Platform.isIOS || Platform.isAndroid) {
|
||||
_initLog.log('📱 检测到移动平台,检查网络权限', tag: 'Init');
|
||||
KRLogUtil.kr_i('📱 移动平台,检查网络权限...', tag: 'SplashController');
|
||||
final bool hasNetworkPermission = await KRNetworkCheck.kr_initialize(
|
||||
Get.context!,
|
||||
onPermissionGranted: () async {
|
||||
await _kr_continueInitialization();
|
||||
},
|
||||
);
|
||||
|
||||
if (!hasNetworkPermission) {
|
||||
kr_hasError.value = true;
|
||||
kr_errorMessage.value = AppTranslations.kr_splash.kr_networkPermissionFailed;
|
||||
KRLogUtil.kr_e('❌ 网络权限检查失败', 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();
|
||||
}
|
||||
@ -336,22 +397,44 @@ class KRSplashController extends GetxController {
|
||||
|
||||
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');
|
||||
final bool isConnected = await KRNetworkCheck.kr_checkNetworkConnection();
|
||||
if (!isConnected) {
|
||||
kr_hasError.value = true;
|
||||
kr_errorMessage.value = AppTranslations.kr_splash.kr_networkConnectionFailed;
|
||||
KRLogUtil.kr_e('❌ 网络连接失败', tag: 'SplashController');
|
||||
return;
|
||||
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');
|
||||
}
|
||||
KRLogUtil.kr_i('✅ 网络连接正常', tag: 'SplashController');
|
||||
} else {
|
||||
_initLog.log('💻 桌面平台,跳过网络连接检查', tag: 'Continue');
|
||||
KRLogUtil.kr_i('💻 桌面平台,跳过网络连接检查', tag: 'SplashController');
|
||||
}
|
||||
|
||||
@ -375,19 +458,22 @@ class KRSplashController extends GetxController {
|
||||
_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) {
|
||||
// 配置初始化失败,显示错误信息
|
||||
KRLogUtil.kr_e('❌ 启动页初始化异常: $e', tag: 'SplashController');
|
||||
kr_hasError.value = true;
|
||||
kr_errorMessage.value = '${AppTranslations.kr_splash.kr_initializationFailed}$e';
|
||||
// 🔧 Android 15 优化:配置初始化失败时执行降级策略
|
||||
_initLog.logError('启动页初始化异常,执行降级策略', tag: 'Continue', error: e);
|
||||
KRLogUtil.kr_w('⚠️ 启动页初始化异常,执行降级策略: $e', tag: 'SplashController');
|
||||
await _executeMinimalInitialization();
|
||||
Get.offAllNamed(Routes.KR_MAIN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,6 +510,19 @@ class KRSplashController extends GetxController {
|
||||
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');
|
||||
|
||||
// 完成日志收集
|
||||
await _initLog.finalize();
|
||||
if (kDebugMode && _initLog.getLogFilePath() != null) {
|
||||
print('📁 初始化日志文件: ${_initLog.getLogFilePath()}');
|
||||
}
|
||||
|
||||
// 直接导航到主页(无论是否登录,主页会根据登录状态显示不同内容)
|
||||
_logStepTiming('开始页面导航');
|
||||
if(loginStatus) {
|
||||
@ -444,10 +543,14 @@ class KRSplashController extends GetxController {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,10 +12,10 @@ class KRSiteConfigService extends ChangeNotifier {
|
||||
static final KRSiteConfigService _instance = KRSiteConfigService._internal();
|
||||
factory KRSiteConfigService() => _instance;
|
||||
KRSiteConfigService._internal() {
|
||||
// 🔧 P1修复:减少超时时间 10秒 → 5秒
|
||||
_dio.options.connectTimeout = const Duration(seconds: 5);
|
||||
_dio.options.sendTimeout = const Duration(seconds: 5);
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 5);
|
||||
// 🔧 Android 15 优化:增加超时时间以适应移动网络(5秒 → 20秒)
|
||||
_dio.options.connectTimeout = const Duration(seconds: 20);
|
||||
_dio.options.sendTimeout = const Duration(seconds: 20);
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 20);
|
||||
|
||||
// 🔧 配置HttpClientAdapter使用sing-box的mixed代理
|
||||
_dio.httpClientAdapter = IOHttpClientAdapter(
|
||||
@ -67,7 +67,8 @@ class KRSiteConfigService extends ChangeNotifier {
|
||||
print('📤 准备发送 GET 请求到: $url');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('⏱️ 超时配置: connectTimeout=10s, sendTimeout=10s, receiveTimeout=10s');
|
||||
// 🔧 修正日志,显示真实的超时配置
|
||||
print('⏱️ 超时配置: connectTimeout=${_dio.options.connectTimeout}, sendTimeout=${_dio.options.sendTimeout}, receiveTimeout=${_dio.options.receiveTimeout}');
|
||||
}
|
||||
|
||||
if (kDebugMode) {
|
||||
|
||||
@ -84,7 +84,7 @@ class KRNetworkCheck {
|
||||
if (connectivityResult == ConnectivityResult.none) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 尝试进行实际的网络请求测试
|
||||
try {
|
||||
final result = await InternetAddress.lookup('www.apple.com');
|
||||
@ -93,13 +93,51 @@ class KRNetworkCheck {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Android 平台保持原有逻辑
|
||||
final connectivityResult = await Connectivity().checkConnectivity();
|
||||
return connectivityResult != ConnectivityResult.none;
|
||||
// 🔧 Android 15 增强:多重验证网络可用性
|
||||
// 1. 检查连接状态(基础检查)
|
||||
final connectivityResult = await Connectivity().checkConnectivity().timeout(
|
||||
const Duration(seconds: 3),
|
||||
onTimeout: () {
|
||||
debugPrint('⚠️ 连接性检查超时');
|
||||
return ConnectivityResult.none;
|
||||
},
|
||||
);
|
||||
|
||||
if (connectivityResult == ConnectivityResult.none) {
|
||||
debugPrint('❌ 网络未连接');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 🔧 Android 15 新增:尝试实际 DNS 解析验证网络可用性
|
||||
// 这在 Android 15 上很重要,因为系统可能报告网络已连接但实际无法访问
|
||||
try {
|
||||
final result = await InternetAddress.lookup('www.google.com').timeout(
|
||||
const Duration(seconds: 5),
|
||||
onTimeout: () {
|
||||
debugPrint('⚠️ DNS 解析超时,网络可能不稳定');
|
||||
return <InternetAddress>[];
|
||||
},
|
||||
);
|
||||
|
||||
if (result.isEmpty) {
|
||||
debugPrint('⚠️ DNS 解析失败,但允许继续(可能是网络延迟)');
|
||||
// 即使 DNS 解析失败,也允许继续,因为可能只是网络延迟
|
||||
return true;
|
||||
}
|
||||
|
||||
debugPrint('✅ 网络权限检查通过(连接性 + DNS 解析)');
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint('⚠️ DNS 解析异常: $e,但允许继续');
|
||||
// DNS 解析异常也允许继续,避免误判
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('网络权限检查错误: $e');
|
||||
return false;
|
||||
debugPrint('❌ 网络权限检查错误: $e');
|
||||
// 🔧 Android 15 优化:出错时返回 true,避免阻塞应用启动
|
||||
// 实际网络问题会在后续步骤中处理
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +150,7 @@ class KRNetworkCheck {
|
||||
if (connectivityResult == ConnectivityResult.none) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
final result = await InternetAddress.lookup('www.apple.com');
|
||||
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
|
||||
@ -120,12 +158,29 @@ class KRNetworkCheck {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
final connectivityResult = await Connectivity().checkConnectivity();
|
||||
return connectivityResult != ConnectivityResult.none;
|
||||
// 🔧 Android 15 增强:添加超时保护
|
||||
final connectivityResult = await Connectivity().checkConnectivity().timeout(
|
||||
const Duration(seconds: 3),
|
||||
onTimeout: () {
|
||||
debugPrint('⚠️ 网络连接检查超时');
|
||||
return ConnectivityResult.none;
|
||||
},
|
||||
);
|
||||
|
||||
if (connectivityResult == ConnectivityResult.none) {
|
||||
debugPrint('❌ 网络未连接');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 🔧 Android 15 优化:对于已连接的网络,快速返回 true
|
||||
// 避免不必要的 DNS 查询延迟应用启动
|
||||
debugPrint('✅ 网络连接检查通过(${connectivityResult.name})');
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('网络连接检查错误: $e');
|
||||
return false;
|
||||
debugPrint('❌ 网络连接检查错误: $e');
|
||||
// 🔧 Android 15 优化:出错时返回 true,避免误判
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user