main.dart
9.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
import 'dart:io';
import 'package:Parlando/account/view_models/account_view_model.dart';
import 'package:Parlando/membership/view_models/membership_view_model.dart';
import 'package:dio/dio.dart';
import 'package:flustars/flustars.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:oktoast/oktoast.dart';
import 'package:provider/provider.dart';
import 'package:quick_actions/quick_actions.dart';
import 'package:url_strategy/url_strategy.dart';
import 'package:flutter_gen/gen_l10n/Parlando_localizations.dart';
import 'home/splash_page.dart';
import 'net/dio_utils.dart';
import 'net/intercept.dart';
import 'provider/locale_provider.dart';
import 'provider/theme_provider.dart';
import 'res/constant.dart';
import 'routers/not_found_page.dart';
import 'routers/routers.dart';
import 'util/device_utils.dart';
import 'util/handle_error_utils.dart';
import 'util/log_utils.dart';
import 'util/theme_utils.dart';
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'
show BMFMapSDK, BMF_COORD_TYPE;
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
///
/// 配置本地化的方法
/// 1. 安裝Flutter intl插件
/// 2. 執行 intl插件的初始化(tools->Flutter Intl->initialize for the Project)
/// 3. 創建i18n文件
/// 4. 执行:flutter gen-l10n --template-arb-file intl_en.arb --output-class ParlandoLocalizations letLocalizations --output-localization-file Parlando_localizations.dart
///
/// json to model
/// 安装
/// dependencies:
/// json_annotation: ^4.4.0x
/// dev_dependencies:
/// json_serializable: ^6.1.3
/// build_runner: ^2.1.7
/// 执行:flutter packages pub run build_runner build --delete-conflicting-outputs
Future<void> main() async {
// debugProfileBuildsEnabled = true;
// debugPaintLayerBordersEnabled = true;
// debugProfilePaintsEnabled = true;
// debugRepaintRainbowEnabled = true;
/// 确保初始化完成
WidgetsFlutterBinding.ensureInitialized();
/// 去除URL中的“#”(hash),仅针对Web。默认为setHashUrlStrategy
/// 注意本地部署和远程部署时`web/index.html`中的base标签,https://github.com/flutter/flutter/issues/69760
setPathUrlStrategy();
/// sp初始化
await SpUtil.getInstance();
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
/// 1.22 预览功能: 在输入频率与显示刷新率不匹配情况下提供平滑的滚动效果
// GestureBinding.instance?.resamplingEnabled = true;
/// 异常处理
handleError(() => runApp(MyApp()));
/// 隐藏状态栏。为启动页、引导页设置。完成后修改回显示状态栏。
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: [SystemUiOverlay.bottom]);
// TODO(weilu): 启动体验不佳。状态栏、导航栏在冷启动开始的一瞬间为黑色,且无法通过隐藏、修改颜色等方式进行处理。。。
// 相关问题跟踪:https://github.com/flutter/flutter/issues/73351
if (Platform.isAndroid) {
//设置Android头部的导航栏透明
SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(
statusBarColor: Colors.transparent, //全局设置透明
statusBarIconBrightness: Brightness.light
//light:黑色图标 dark:白色图标
//在此处设置statusBarIconBrightness为全局设置
);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
/// 动态申请定位权限
requestPermission();
LocationFlutterPlugin myLocPlugin = LocationFlutterPlugin();
/// 设置用户是否同意SDK隐私协议
/// since 3.1.0 开发者必须设置
BMFMapSDK.setAgreePrivacy(true);
myLocPlugin.setAgreePrivacy(true);
// 百度地图sdk初始化鉴权
if (Platform.isIOS) {
myLocPlugin.authAK('rMsgMvYERM9zHDDdaipk34oBx7yoaGQh');
BMFMapSDK.setApiKeyAndCoordType(
'rMsgMvYERM9zHDDdaipk34oBx7yoaGQh', BMF_COORD_TYPE.BD09LL);
} else if (Platform.isAndroid) {
// Android 目前不支持接口设置Apikey,
// 请在主工程的Manifest文件里设置,详细配置方法请参考官网(https://lbsyun.baidu.com/)demo
BMFMapSDK.setCoordType(BMF_COORD_TYPE.BD09LL);
}
}
class MyApp extends StatelessWidget {
MyApp({Key? key, this.home, this.theme}) : super(key: key) {
Log.init();
initDio();
Routes.initRoutes();
initQuickActions();
}
final Widget? home;
final ThemeData? theme;
static GlobalKey<NavigatorState> navigatorKey = GlobalKey();
void initDio() {
final List<Interceptor> interceptors = <Interceptor>[];
/// 统一添加身份验证请求头
interceptors.add(AuthInterceptor());
/// 打印Log(生产模式去除)
if (!Constant.inProduction) {
interceptors.add(LoggingInterceptor());
}
interceptors.add(AdapterInterceptor());
configDio(
baseUrl: 'https://api.parlando.ink/api/v1/',
interceptors: interceptors,
);
}
void initQuickActions() {
if (Device.isMobile) {
const QuickActions quickActions = QuickActions();
if (Device.isIOS) {
// Android每次是重新启动activity,所以放在了splash_page处理。
// 总体来说使用不方便,这种动态的方式在安卓中局限性高。这里仅做练习使用。
quickActions.initialize((String shortcutType) async {
// if (shortcutType == 'demo') {
// navigatorKey.currentState?.push<dynamic>(MaterialPageRoute<dynamic>(
// builder: (BuildContext context) => const DemoPage(),
// ));
// }
});
}
quickActions.setShortcutItems(<ShortcutItem>[
const ShortcutItem(
type: 'demo', localizedTitle: '发一言', icon: 'flutter_dash_black'),
]);
}
}
@override
Widget build(BuildContext context) {
final Widget app = MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ThemeProvider()),
ChangeNotifierProvider(create: (_) => LocaleProvider()),
ChangeNotifierProvider(create: (_) => AccountViewProvider()),
ChangeNotifierProvider(create: (_) => MembershipViewProvider())
],
child: Consumer2<ThemeProvider, LocaleProvider>(
builder:
(_, ThemeProvider provider, LocaleProvider localeProvider, __) {
return _buildMaterialApp(provider, localeProvider);
},
),
);
/// Toast 配置
return OKToast(
backgroundColor: Colors.black54,
textPadding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
radius: 20.0,
position: ToastPosition.bottom,
child: app);
}
Widget _buildMaterialApp(
ThemeProvider provider, LocaleProvider localeProvider) {
return MaterialApp(
title: '一言',
// showPerformanceOverlay: true, //显示性能标签
// debugShowCheckedModeBanner: false, // 去除右上角debug的标签
// checkerboardRasterCacheImages: true,
// showSemanticsDebugger: true, // 显示语义视图
// checkerboardOffscreenLayers: true, // 检查离屏渲染
theme: theme ?? provider.getTheme(),
darkTheme: provider.getTheme(isDarkMode: true),
themeMode: provider.getThemeMode(),
home: home ?? const SplashPage(),
onGenerateRoute: Routes.router.generator,
localizationsDelegates: ParlandoLocalizations.localizationsDelegates,
supportedLocales: ParlandoLocalizations.supportedLocales,
locale: localeProvider.locale,
navigatorKey: navigatorKey,
builder: (BuildContext context, Widget? child) {
/// 仅针对安卓
if (Device.isAndroid) {
/// 切换深色模式会触发此方法,这里设置导航栏颜色
ThemeUtils.setSystemNavigationBar(provider.getThemeMode());
}
/// 保证文字大小不受手机系统设置影响 https://www.kikt.top/posts/flutter/layout/dynamic-text/
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: child!,
);
},
/// 因为使用了fluro,这里设置主要针对Web
onUnknownRoute: (_) {
return MaterialPageRoute<void>(
builder: (BuildContext context) => const NotFoundPage(),
);
},
restorationScopeId: 'app',
);
}
}
// 动态申请定位权限
void requestPermission() async {
// 申请权限
bool hasLocationPermission = await requestLocationPermission();
if (hasLocationPermission) {
// 权限申请通过
} else {}
}
/// 申请定位权限
/// 授予定位权限返回true, 否则返回false
Future<bool> requestLocationPermission() async {
//获取当前的权限
var status = await Permission.location.status;
if (status == PermissionStatus.granted) {
//已经授权
return true;
} else {
//未授权则发起一次申请
status = await Permission.location.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}