Hibok
您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 
 
 
 

497 行
17 KiB

  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'package:amap_location/amap_location.dart';
  5. import 'package:apple_sign_in/apple_sign_in.dart';
  6. import 'package:chat/data/WebData.dart';
  7. import 'package:chat/data/chat_data_mgr.dart';
  8. import 'package:chat/data/constants.dart';
  9. import 'package:chat/data/group_data_mgr.dart';
  10. import 'package:chat/home/homeMain.dart';
  11. import 'package:chat/home/splash_page.dart';
  12. import 'package:chat/models/gift_select_provider.dart';
  13. import 'package:chat/models/money_change.dart';
  14. import 'package:chat/models/ref_name_provider.dart';
  15. import 'package:chat/utils/MessageMgr.dart';
  16. import 'package:chat/utils/NetUtil.dart';
  17. import 'package:chat/utils/OtherLogin.dart';
  18. import 'package:chat/utils/file_cache_mgr.dart';
  19. import 'package:chat/utils/flutter_windowmanager.dart';
  20. import 'package:chat/utils/local_notification_util.dart';
  21. import 'package:chat/utils/msgHandler.dart';
  22. import 'package:chat/utils/receive_share_file.dart';
  23. import 'package:chat/utils/screen.dart';
  24. import 'package:chat/utils/screen_shot.dart';
  25. import 'package:chat/utils/sound_util.dart';
  26. import 'package:chat/utils/sp_utils.dart';
  27. import 'package:chat/utils/sql_util.dart';
  28. import 'package:easy_contact_picker/easy_contact_picker.dart';
  29. import 'package:flutter/cupertino.dart';
  30. import 'package:flutter/material.dart';
  31. import 'package:flutter/services.dart';
  32. import 'package:flutter_bugly/flutter_bugly.dart';
  33. import 'package:flutter_screenutil/flutter_screenutil.dart';
  34. //import 'package:flutter_bugly/flutter_bugly.dart';
  35. import 'package:location_permissions/location_permissions.dart' as lp;
  36. import 'package:package_info/package_info.dart';
  37. import 'package:permission_handler/permission_handler.dart';
  38. import 'package:oktoast/oktoast.dart';
  39. import 'package:provider/provider.dart';
  40. import 'package:shared_preferences/shared_preferences.dart';
  41. import 'home/IndexPage.dart';
  42. import 'generated/i18n.dart';
  43. import 'package:flutter_localizations/flutter_localizations.dart';
  44. import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx;
  45. import 'package:chat/data/UserData.dart' show UserData;
  46. import 'package:auto_orientation/auto_orientation.dart';
  47. import 'models/voucher_change.dart';
  48. //读取本地数据
  49. initLocalData() async {
  50. SharedPreferences prefs = await SharedPreferences.getInstance();
  51. var localUserId = prefs.getInt(Constants.LocalUserId);
  52. if (localUserId != null) {
  53. print('用户不为空');
  54. //设置用户基本信息
  55. UserData().basicInfo.userId = localUserId;
  56. String localUserData = await SPUtils.get(Constants.LocalUsrInfo);
  57. if (localUserData != null) {
  58. UserData().fromLocalJson(json.decode(localUserData));
  59. }
  60. //读取好友信息
  61. //读取聊天信息
  62. await ChatDataMgr().initMsg();
  63. //读取群信息
  64. await GroupInfoMgr().initLocalGroupList();
  65. }
  66. }
  67. void main() async {
  68. WidgetsFlutterBinding.ensureInitialized();
  69. LocalNotificationUtil.instance.initJPush();
  70. LocalNotificationUtil.instance.initLocalPush();
  71. await FileCacheMgr.initPathKey();
  72. await SqlUtil.init();
  73. await initLocalData();
  74. AutoOrientation.portraitUpMode();
  75. AMapLocationClient.setApiKey("3f4c9fca5f513ac0be361e92d8586ff3");
  76. AMapLocationClient.startup(new AMapLocationOption(
  77. desiredAccuracy: CLLocationAccuracy.kCLLocationAccuracyHundredMeters));
  78. setStatusBar();
  79. FlutterBugly.init(androidAppId: "d2a8d2c6a0", iOSAppId: "f0ad7340d0");
  80. FlutterBugly.postCatchedException(() {
  81. runApp(MyApp());
  82. }, debugUpload: true);
  83. // runApp(RestartWidget(
  84. // child: MyApp(),
  85. // ));
  86. }
  87. void setCustomErrorPage(BuildContext context) {
  88. ErrorWidget.builder = (FlutterErrorDetails flutterErrorDetails) {
  89. print(flutterErrorDetails.toString());
  90. return Scaffold(
  91. body: Center(
  92. child: Column(
  93. children: <Widget>[
  94. Container(
  95. margin: EdgeInsets.only(
  96. top: ScreenUtil.instance.setHeight(180),
  97. bottom: ScreenUtil.instance.setHeight(49)),
  98. child: Image.asset(
  99. 'assets/images/net_error.png',
  100. width: ScreenUtil.instance.setWidth(150),
  101. ),
  102. ),
  103. Container(
  104. margin: EdgeInsets.only(top: ScreenUtil().setHeight(50)),
  105. child: Text(
  106. I18n.of(Constants.getCurrentContext()).server_error_tips,
  107. textScaleFactor: 1.0,
  108. style: TextStyle(color: Color(0xFF8F8E8E), fontSize: 18),
  109. ),
  110. ),
  111. ],
  112. )),
  113. );
  114. };
  115. }
  116. Map<String, int> language = {
  117. 'en_US': LanguageType.English,
  118. 'en_CN': LanguageType.English,
  119. 'vi_VN': LanguageType.Vietnamese,
  120. 'vi_CN': LanguageType.Vietnamese,
  121. 'vi_US': LanguageType.Vietnamese,
  122. 'zh_Hant_CN': LanguageType.TraditionalChinese,
  123. 'zh_TW': LanguageType.TraditionalChinese,
  124. 'zh_HK': LanguageType.TraditionalChinese,
  125. 'zh_Hant': LanguageType.TraditionalChinese,
  126. 'zh_Hant_MO': LanguageType.TraditionalChinese,
  127. 'zh_Hant_TW': LanguageType.TraditionalChinese,
  128. 'zh_Hant_HK': LanguageType.TraditionalChinese,
  129. 'zh_Hant_US': LanguageType.TraditionalChinese,
  130. 'zh_Hans': LanguageType.SimplifiedChinese,
  131. 'zh_Hans_CN': LanguageType.SimplifiedChinese,
  132. 'zh_Hans_US': LanguageType.SimplifiedChinese,
  133. 'zh_Hans_MO': LanguageType.SimplifiedChinese,
  134. 'zh_Hans_SG': LanguageType.SimplifiedChinese,
  135. 'zh_Hans_VN': LanguageType.SimplifiedChinese,
  136. 'zh_CN': LanguageType.SimplifiedChinese,
  137. 'ko_KR': LanguageType.Korean,
  138. 'ko_KP': LanguageType.Korean,
  139. 'ko_Kore_CN': LanguageType.Korean,
  140. 'ko_Kore_US': LanguageType.Korean,
  141. 'ko_CN': LanguageType.Korean,
  142. 'ja_JP': LanguageType.Japanese,
  143. 'ja_US': LanguageType.Japanese,
  144. 'ja_CN': LanguageType.Japanese,
  145. };
  146. //全局去掉水波纹
  147. class NoSplashFactory extends InteractiveInkFeatureFactory {
  148. const NoSplashFactory();
  149. InteractiveInkFeature create({
  150. @required MaterialInkController controller,
  151. @required RenderBox referenceBox,
  152. @required Offset position,
  153. @required Color color,
  154. TextDirection textDirection,
  155. bool containedInkWell: false,
  156. RectCallback rectCallback,
  157. BorderRadius borderRadius,
  158. ShapeBorder customBorder,
  159. double radius,
  160. VoidCallback onRemoved,
  161. }) {
  162. return new NoSplash(
  163. controller: controller,
  164. referenceBox: referenceBox,
  165. color: color,
  166. onRemoved: onRemoved,
  167. );
  168. }
  169. }
  170. class NoSplash extends InteractiveInkFeature {
  171. NoSplash({
  172. @required MaterialInkController controller,
  173. @required RenderBox referenceBox,
  174. Color color,
  175. VoidCallback onRemoved,
  176. }) : assert(controller != null),
  177. assert(referenceBox != null),
  178. super(
  179. controller: controller,
  180. referenceBox: referenceBox,
  181. onRemoved: onRemoved) {
  182. controller.addInkFeature(this);
  183. }
  184. @override
  185. void paintFeature(Canvas canvas, Matrix4 transform) {}
  186. }
  187. class FallbackCupertinoLocalisationsDelegate
  188. extends LocalizationsDelegate<CupertinoLocalizations> {
  189. const FallbackCupertinoLocalisationsDelegate();
  190. @override
  191. bool isSupported(Locale locale) => true;
  192. @override
  193. Future<CupertinoLocalizations> load(Locale locale) =>
  194. DefaultCupertinoLocalizations.load(locale);
  195. @override
  196. bool shouldReload(FallbackCupertinoLocalisationsDelegate old) => false;
  197. }
  198. class MyApp extends StatefulWidget {
  199. MyApp({Key key}) : super(key: key);
  200. _MyAppState createState() => _MyAppState();
  201. }
  202. class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  203. final i18n = I18n.delegate;
  204. RefNameProvider _refNameProvider;
  205. bool isOpen = true;
  206. @override
  207. void initState() {
  208. super.initState();
  209. setCustomErrorPage(context);
  210. isAvailableAppleSignIn();
  211. Screen.initFactor();
  212. initVersionName();
  213. askLocationPermission();
  214. I18n.onLocaleChanged = onLocaleChange;
  215. WidgetsBinding.instance.addObserver(this);
  216. ReceiveShareFile.init();
  217. ScreenShot.getFileStream();
  218. }
  219. isAvailableAppleSignIn() async {
  220. isOpen = (await SPUtils.getBool(Constants.Splash_OPENED)) ?? false;
  221. OtherLogin.isAvailableForAppleSignIn = await AppleSignIn.isAvailable();
  222. }
  223. @override
  224. void didChangeDependencies() {
  225. super.didChangeDependencies();
  226. if (_refNameProvider == null) {
  227. _refNameProvider = RefNameProvider();
  228. }
  229. }
  230. initVersionName() async {
  231. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  232. Constants.versionName = packageInfo.version;
  233. Constants.packageName = packageInfo.packageName;
  234. }
  235. @override
  236. void dispose() {
  237. //positionStream?.cancel();
  238. WidgetsBinding.instance.removeObserver(this);
  239. // LocalNotificationUtil.instance.dispose();
  240. super.dispose();
  241. }
  242. @override
  243. void didChangeAppLifecycleState(AppLifecycleState state) async {
  244. print("--" + state.toString());
  245. switch (state) {
  246. case AppLifecycleState.inactive: // 处于这种状态的应用程序应该假设它们可能在任何时候暂停。
  247. break;
  248. case AppLifecycleState.resumed: // 应用程序可见,前台
  249. setStatusBar();
  250. print('切换到前台');
  251. //检测用户是否开启定位权限
  252. MessageMgr().emit('test_Permission');
  253. NetWork().checkConnect();
  254. MessageMgr().emit(MessageMgr.REFRESH_PUSH_PERMISSION);
  255. LocalNotificationUtil.isBackground = false;
  256. LocalNotificationUtil.instance.cleanAllNotifications();
  257. if (UserData().isBannerStatus) {
  258. UserData().isBannerStatus = false;
  259. MessageMgr().emit('refresh_money');
  260. }
  261. if (MsgHandler.audioChatRequestFriendId > 0) {
  262. MessageMgr().emit(
  263. 'Receive AudioChat Request', MsgHandler.audioChatRequestFriendId);
  264. }
  265. // await FlutterStatusbarcolor.setStatusBarColor(Colors.white);
  266. break;
  267. case AppLifecycleState.paused: // 应用程序不可见,后台
  268. print('切换到后台');
  269. LocalNotificationUtil.isBackground = true;
  270. SoundUtils.instance.pause();
  271. if (Platform.isIOS) NetWork().reallyClose();
  272. ///iOS切后台关闭socket不然会闪退
  273. break;
  274. // case AppLifecycleState.suspending: // 申请将暂时暂停
  275. // print('程序挂起');
  276. // break;
  277. case AppLifecycleState.detached: // 申请将暂时暂停
  278. // print('程序挂起');
  279. break;
  280. }
  281. }
  282. void onLocaleChange(Locale locale) {
  283. final String lang = locale != null ? locale.toString() : "";
  284. print('#### onLocaleChange $lang');
  285. setState(() {
  286. I18n.locale = locale;
  287. });
  288. }
  289. setDisableScreenshots() async {
  290. print('Platform.isAndroid ${Platform.isAndroid}');
  291. if (Platform.isAndroid) {
  292. await FlutterWindowManager.addFlags(FlutterWindowManager.FLAG_SECURE);
  293. }
  294. }
  295. @override
  296. Widget build(BuildContext context) {
  297. fluwx.registerWxApi(
  298. appId: Constants.AppId,
  299. universalLink: "https://www.xxx.com/iosuniversallink/");
  300. return OKToast(
  301. child: MultiProvider(
  302. providers: [
  303. ChangeNotifierProvider(create: (_) => GiftSelectProvider()),
  304. ChangeNotifierProvider(create: (_) => MoneyChangeProvider()),
  305. ChangeNotifierProvider(create: (_) => _refNameProvider),
  306. ChangeNotifierProvider(create: (_) => VoucherChangeProvider()),
  307. ],
  308. child: MaterialApp(
  309. theme: ThemeData(
  310. platform: TargetPlatform.iOS,
  311. highlightColor: Colors.transparent,
  312. splashFactory: const NoSplashFactory(),
  313. toggleableActiveColor: Constants.BlueTextColor,
  314. scaffoldBackgroundColor: Constants.GreyBackgroundColor,
  315. accentColor: Constants.BlueTextColor,
  316. indicatorColor: Constants.BlueTextColor,
  317. tabBarTheme: TabBarTheme(
  318. indicatorSize: TabBarIndicatorSize.label,
  319. labelColor: Constants.BlueTextColor,
  320. unselectedLabelColor: Constants.GreyTextColor,
  321. labelPadding: EdgeInsets.only(bottom: 5, left: 15, right: 15),
  322. labelStyle:
  323. TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
  324. unselectedLabelStyle:
  325. TextStyle(fontWeight: FontWeight.w500, fontSize: 15),
  326. ),
  327. appBarTheme: AppBarTheme(
  328. elevation: 0,
  329. brightness: Brightness.light,
  330. color: Colors.white,
  331. iconTheme: IconThemeData(color: Colors.black),
  332. actionsIconTheme: IconThemeData(color: Colors.black),
  333. textTheme: TextTheme(
  334. title: TextStyle(
  335. color: Constants.BlackTextColor, fontSize: 20))),
  336. primaryColor: Constants.BlueTextColor,
  337. inputDecorationTheme: InputDecorationTheme(
  338. labelStyle: TextStyle(
  339. fontSize: 13, color: Constants.BlackTextColor),
  340. border: InputBorder.none,
  341. contentPadding: EdgeInsets.all(10),
  342. hintStyle: TextStyle(
  343. fontSize: 11,
  344. color: Color.fromARGB(255, 192, 191, 191))),
  345. ),
  346. localizationsDelegates: [
  347. i18n,
  348. GlobalMaterialLocalizations.delegate,
  349. GlobalWidgetsLocalizations.delegate,
  350. GlobalCupertinoLocalizations.delegate, // <-- needed for iOS
  351. const FallbackCupertinoLocalisationsDelegate()
  352. ],
  353. //locale: Locale("en", "US"),
  354. supportedLocales: i18n.supportedLocales,
  355. title: 'Chat',
  356. onGenerateTitle: (context) {
  357. // 此处
  358. return 'Hibok';
  359. },
  360. navigatorKey: Constants.navigatorKey,
  361. routes: <String, WidgetBuilder>{
  362. '/main': (BuildContext context) => HomeMain(),
  363. },
  364. home: Builder(builder: (context) {
  365. return goIndex();
  366. }),
  367. //home: IndexPage(),
  368. localeResolutionCallback: (deviceLocale, supportedLocales) {
  369. if (deviceLocale != null) {
  370. final String lang =
  371. deviceLocale != null ? deviceLocale.toString() : "";
  372. print('#### fl: $lang');
  373. UserData().deviceLanguageCode = deviceLocale.toString();
  374. //设置设备语言
  375. if (language.containsKey(deviceLocale.toString()))
  376. UserData().deviceLanguage =
  377. language[deviceLocale.toString()];
  378. getPosition(deviceLocale);
  379. }
  380. return deviceLocale;
  381. },
  382. )));
  383. }
  384. goIndex() {
  385. if (!isOpen) {
  386. return SplashPage();
  387. } else {
  388. return IndexPage();
  389. }
  390. }
  391. askLocationPermission() async {
  392. lp.PermissionStatus status =
  393. await lp.LocationPermissions().checkPermissionStatus();
  394. print('定位权限 $status');
  395. final PermissionStatus addStatus = await PermissionHandler()
  396. .checkPermissionStatus(PermissionGroup.contacts);
  397. print('通讯录权限 $addStatus');
  398. List<PermissionGroup> permissionList = [];
  399. if (status == lp.PermissionStatus.granted) {
  400. UserData().hasLocationPermission = true;
  401. } else {
  402. permissionList.add(PermissionGroup.locationWhenInUse);
  403. }
  404. if (addStatus == PermissionStatus.granted) {
  405. setContact();
  406. } else {
  407. if (Platform.isAndroid) {
  408. // ///ios隐藏
  409. permissionList.add(PermissionGroup.contacts);
  410. }
  411. }
  412. print(permissionList);
  413. if (permissionList.length != 0) {
  414. Map<PermissionGroup, PermissionStatus> permissionRequestResult =
  415. await PermissionHandler().requestPermissions(permissionList);
  416. var status = permissionRequestResult[PermissionGroup.locationWhenInUse];
  417. var addStatus = permissionRequestResult[PermissionGroup.contacts];
  418. if (status == PermissionStatus.granted) {
  419. UserData().hasLocationPermission = true;
  420. }
  421. if (addStatus == PermissionStatus.granted) {
  422. setContact();
  423. }
  424. }
  425. MessageMgr().emit('test_Permission');
  426. }
  427. setContact() async {
  428. final EasyContactPicker _contactPicker = new EasyContactPicker();
  429. List<Contact> _list = await _contactPicker.selectContacts();
  430. UserData().contactList.clear();
  431. _list.forEach((contack) {
  432. UserData()
  433. .contactList
  434. .add({'PhoneNumber': contack.phoneNumber, 'Name': contack.fullName});
  435. });
  436. MessageMgr().emit('PostContact');
  437. }
  438. void getPosition(deviceLocale) async {
  439. SharedPreferences prefs = await SharedPreferences.getInstance();
  440. var localLanguage = prefs.getInt(Constants.Language);
  441. print('localLanguage$localLanguage');
  442. if (localLanguage == null) {
  443. if (language.containsKey(deviceLocale.toString()))
  444. UserData().language = language[deviceLocale.toString()];
  445. } else {
  446. UserData().language = localLanguage;
  447. }
  448. WebData().getAllData();
  449. UserData().getCurrentPosition();
  450. }
  451. }