import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_intro/flutter_intro.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'core/utils/app_lifecycle_manager.dart'; import 'routes/app_pages.dart'; import 'routes/app_routes.dart'; import 'core/translations/app_translations.dart'; import 'core/theme/app_theme.dart'; import 'core/theme/theme_service.dart'; import 'core/bindings/initial_binding.dart'; import 'core/utils/logger.dart'; import 'data/models/device_images.dart'; import 'core/services/native_localization_sync.dart'; import 'core/services/ai_orb_controller.dart'; import 'data/services/login_service.dart'; import 'modules/meeting/controllers/meeting_home_controller.dart'; import 'modules/splash/controllers/splash_controller.dart'; bool _deepLinkHandlerInitialized = false; void main() async { WidgetsFlutterBinding.ensureInitialized(); // App 不做横屏适配,锁死竖屏(原生侧 AndroidManifest/Info.plist 也各锁了一道, // 这里是 Flutter 侧兜底,避免个别机型仅靠原生配置锁不住) await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); // 初始化存储 await GetStorage.init(); // 加载环境变量 await dotenv.load(fileName: ".env"); Logger.i("Main", "环境变量加载成功"); // 初始化文件日志 await Logger.initFileLog(); // 读一次产品图清单。必须在 runApp 之前 await:设备页第一帧就要取图, // 清单没载入的话首屏会闪一下默认图再跳回产品图。 await DeviceImages.load(); // 初始化登录服务 Get.put(LoginService()); // 延迟初始化深链接处理器,确保Flutter完全准备好 WidgetsBinding.instance.addPostFrameCallback((_) { Future.delayed(const Duration(milliseconds: 1500), () { _initDeepLinkHandler(); }); }); runApp(MainApp()); } // 初始化深链接处理器 void _initDeepLinkHandler() { if (_deepLinkHandlerInitialized) return; _deepLinkHandlerInitialized = true; Logger.d("DeepLink", "初始化深链接处理器"); const platform = MethodChannel('com.yimai.eaimar/deeplink'); platform.setMethodCallHandler((call) async { Logger.d("DeepLink", "Flutter 收到深链接调用: ${call.method}"); if (call.method == 'handleDeepLink') { final arguments = call.arguments as Map; Logger.d("DeepLink", "深链接参数: $arguments"); final url = arguments['url'] as String?; if (url != null) { Logger.d("DeepLink", "处理深链接 URL: $url"); await _handleDeepLinkNavigation(url); } return; } if (call.method == 'handleSharedFile') { final arguments = call.arguments as Map; final filePath = arguments['filePath'] as String?; if (filePath == null || filePath.isEmpty) return; await _handleSharedAudioFile(filePath); return; } }); Logger.i("DeepLink", "深链接处理器初始化完成"); } // 处理深链接导航 Future _handleDeepLinkNavigation(String url) async { Logger.d("DeepLink", "开始处理深链接导航: $url"); try { final uri = Uri.parse(url); Logger.d("DeepLink", "解析URI: scheme=${uri.scheme}, host=${uri.host}, path=${uri.path}"); if (uri.scheme == 'deepvoice' && uri.host == 'qqmusic') { Logger.i("DeepLink", "检测到QQ音乐登录回调"); // 等待SplashController注册 int retryCount = 0; const maxRetries = 10; while (retryCount < maxRetries) { try { if (Get.isRegistered()) { Logger.i("DeepLink", "找到SplashController,处理QQ音乐登录"); final controller = Get.find(); controller.handleQQMusicLogin(); return; } } catch (e) { Logger.e("DeepLink", "获取SplashController失败", e); } retryCount++; Logger.d("DeepLink", "等待SplashController注册 ($retryCount/$maxRetries)"); await Future.delayed(const Duration(milliseconds: 500)); } Logger.w("DeepLink", "超时等待SplashController注册"); } } catch (e) { Logger.e("DeepLink", "处理深链接时出错", e); } } Future _handleSharedAudioFile(String filePath) async { try { if (!File(filePath).existsSync()) { Logger.w("DeepLink", "分享文件不存在: $filePath"); return; } int retryCount = 0; const maxRetries = 10; while (retryCount < maxRetries) { try { if (Get.isRegistered()) { final controller = Get.find(); controller.addAudio(filePath); return; } Get.toNamed( Routes.meeting, arguments: { 'filePath': filePath, }, ); return; } catch (e) { retryCount++; await Future.delayed(const Duration(milliseconds: 300)); } } } catch (e) { Logger.e("DeepLink", "处理分享文件失败", e); } } class MainApp extends StatelessWidget { const MainApp({super.key}); @override Widget build(BuildContext context) { // 在应用构建时立即初始化深链接处理 _initDeepLinkHandler(); WidgetsBinding.instance.addPostFrameCallback((_) { unawaited(NativeLocalizationSync.syncToNative()); }); // 获取保存的主题设置 final themeMode = ThemeService().getThemeMode(); return ScreenUtilInit( designSize: const Size(375, 812), minTextAdapt: true, splitScreenMode: true, builder: (_, child) { return GetMaterialApp( title: 'EAIMAR', theme: AppTheme.lightTheme, darkTheme: AppTheme.darkTheme, themeMode: themeMode, // 使用提前获取的主题模式 initialBinding: InitialBinding(), initialRoute: Routes.splash, getPages: AppPages.pages, routingCallback: (routing) { if (Get.isRegistered()) { Get.find().onRouteChanged(routing?.current); } if (!Get.isRegistered()) return; unawaited( Get.find().refreshBleWakeupPolicy( route: routing?.current, ), ); }, debugShowCheckedModeBanner: false, translations: AppTranslations(), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], locale: AppTranslations.deviceLocale(), fallbackLocale: AppTranslations.fallbackLocale, supportedLocales: AppTranslations.supportedLocales, builder: EasyLoading.init( builder: (BuildContext context, Widget? widget) { EasyLoading.instance.userInteractions = false; return MediaQuery( data: MediaQuery.of(context).copyWith( textScaler: TextScaler.noScaling, ), child: Intro( padding: EdgeInsets.zero, // AI 球已改为只在 AI tab 内渲染(见 ai_tab.dart), // 不再作为全局悬浮层叠加在所有页面之上 child: widget!, ), ); }, ), ); }); // // 使用 ScreenUtilInit 包装整个应用 // return ScreenUtilInit( // designSize: const Size(375, 812), // 设计稿尺寸,根据你的设计稿调整 // minTextAdapt: true, // splitScreenMode: true, // builder: (context, child) { // return GetMaterialApp( // title: 'Eaimar', // theme: AppTheme.lightTheme, // darkTheme: AppTheme.darkTheme, // themeMode: ThemeService().getThemeMode(), // initialRoute: Routes.splash, // getPages: AppPages.pages, // initialBinding: InitialBinding(), // translations: AppTranslations(), // locale: Get.deviceLocale, // fallbackLocale: const Locale('en', 'US'), // debugShowCheckedModeBanner: false, // ); // }, // ); } }