import 'package:flutter/material.dart'; import 'dart:async'; import 'package:provider/provider.dart'; import 'providers/expense_provider.dart'; import 'screens/home_screen.dart'; import 'package:flutter_unionad/flutter_unionad.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => ExpenseProvider()..loadData()), ], child: MaterialApp( title: 'Expense Tracker', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const SplashPage(), ), ); } } class SplashPage extends StatefulWidget { const SplashPage({super.key}); @override State createState() => _SplashPageState(); } class _SplashPageState extends State { bool _showAd = true; Timer? _adWatchdog; bool? _initSuccess; // null=loading, true=success, false=failure @override void initState() { super.initState(); // 延后到首帧绘制后再初始化广告 SDK,避免在 Activity/Context 未就绪时调用导致 NPE WidgetsBinding.instance.addPostFrameCallback((_) { _initUnionAd(); }); // 如果广告或 SDK 未在合理时间内返回,使用回退跳转避免白屏 _adWatchdog = Timer(const Duration(seconds: 6), () { if (mounted) _goToHome(); }); } Future _initUnionAd() async { // 注册并初始化 FlutterUnionad SDK try { await FlutterUnionad.register( // 穿山甲广告 Android appid 必填 androidAppId: "5779303", // 穿山甲广告 ios appid 必填 iosAppId: "5779303", // appname 必填 appName: "晴天记账", // 使用聚合功能(true 使用 GroMore 下的广告位) useMediation: false, // 是否为计费用户 paid: false, // 用户画像关键词 keywords: "", // 是否允许 SDK 展示通知栏提示 allowShowNotify: true, // 是否显示 debug 日志 debug: true, // 是否支持多进程 supportMultiProcess: false, // 允许直接下载的网络状态集合 directDownloadNetworkType: [ FlutterUnionadNetCode.NETWORK_STATE_2G, FlutterUnionadNetCode.NETWORK_STATE_3G, FlutterUnionadNetCode.NETWORK_STATE_4G, FlutterUnionadNetCode.NETWORK_STATE_WIFI, ], androidPrivacy: AndroidPrivacy( isCanUseLocation: false, lat: 0.0, lon: 0.0, isCanUsePhoneState: false, imei: "", isCanUseWifiState: false, macAddress: "", isCanUseWriteExternal: false, oaid: "b69cd3cf68900323", alist: false, isCanUseAndroidId: false, androidId: "", isCanUsePermissionRecordAudio: false, isLimitPersonalAds: false, isProgrammaticRecommend: false, userPrivacyConfig: {"mcod": "0"}, ), iosPrivacy: IOSPrivacy( limitPersonalAds: false, limitProgrammaticAds: false, forbiddenCAID: false, ), // userInfo: UnionadUserInfo( // userId: "unionad_123", // age: 19, // gender: 2, // channel: "flutter", // subChannel: "flutter_unionad", // userValueGroup: "QQ", // customInfos: {"QQ": "123", "WeChat": "456"}, // ), // localConfig: "site_config_5098580", ); debugPrint('FlutterUnionad.register: success'); if (mounted) setState(() => _initSuccess = true); } catch (e) { debugPrint('FlutterUnionad.register error: $e'); if (mounted) setState(() => _initSuccess = false); } try { final sdkVersion = await FlutterUnionad.getSDKVersion(); debugPrint('FlutterUnionad SDK Version: $sdkVersion'); } catch (e) { debugPrint('getSDKVersion error: $e'); } FlutterUnionad.requestPermissionIfNecessary( callBack: FlutterUnionadPermissionCallBack( notDetermined: () { debugPrint('权限未确定'); }, restricted: () { debugPrint('权限限制'); }, denied: () { debugPrint('权限拒绝'); }, authorized: () { debugPrint('权限同意'); }, ), ); // 如果注册/初始化在合理时间内仍未完成,标记为失败以便调试 Future.delayed(const Duration(seconds: 4), () { if (!mounted) return; if (_initSuccess == null) { debugPrint('FlutterUnionad: init did not finish within 4s, marking as failed'); setState(() => _initSuccess = false); } }); } void _goToHome() { if (!mounted) return; _adWatchdog?.cancel(); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const HomeScreen()), ); } @override void dispose() { _adWatchdog?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ // 后端主页面作为备用 const Offstage(offstage: true, child: HomeScreen()), // 开屏广告视图 Positioned.fill( child: _showAd ? FlutterUnionadSplashAdView( androidCodeId: "102729400", iosCodeId: "102729400", supportDeepLink: true, width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, hideSkip: false, timeout: 3000, callBack: FlutterUnionadSplashCallBack( onShow: () { debugPrint('开屏广告显示'); setState(() => _showAd = true); }, onClick: () { debugPrint('开屏广告点击'); }, onFail: (error) { debugPrint('开屏广告失败 $error'); _goToHome(); }, onFinish: () { debugPrint('开屏广告倒计时结束'); _goToHome(); }, onSkip: () { debugPrint('开屏广告跳过'); _goToHome(); }, onTimeOut: () { debugPrint('开屏广告超时'); _goToHome(); }, ), ) : const SizedBox.shrink(), ), // Debug: init 状态可视化,方便在真机上观察 Positioned( left: 12, right: 12, bottom: 24, child: Align( alignment: Alignment.bottomCenter, child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Colors.black.withOpacity(0.6), borderRadius: BorderRadius.circular(8), ), child: Text( _initSuccess == null ? 'SDK init: loading...' : (_initSuccess == true ? 'SDK init: success' : 'SDK init: failed'), style: const TextStyle(color: Colors.white), ), ), ), ), ], ), ); } }