Files
QingTianJiZhang/lib/main.dart

247 lines
7.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

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: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<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
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<void> _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),
),
),
),
),
],
),
);
}
}