From 9423df2cd132f415f117974d052c306aa4327680 Mon Sep 17 00:00:00 2001 From: Sai Naw Wun Date: Sun, 6 Sep 2020 02:36:57 +0630 Subject: [PATCH] add messaging --- lib/app.dart | 159 ++++++++++++------ .../common/data/providers/messaging_fcm.dart | 66 ++++++++ lib/fcs/common/pages/signin/code_page.dart | 2 +- lib/fcs/common/pages/signin/signin_page.dart | 2 +- lib/fcs/common/pages/welcome_page.dart | 4 +- .../common/pages/widgets/action_button.dart | 4 +- lib/fcs/common/services/messaging_imp.dart | 25 +++ .../common/services/messaging_service.dart | 7 + lib/fcs/common/services/services.dart | 5 + lib/main-dev.dart | 1 + lib/main-local.dart | 5 +- lib/main-prod.dart | 1 + pubspec.yaml | 1 + 13 files changed, 224 insertions(+), 58 deletions(-) create mode 100644 lib/fcs/common/data/providers/messaging_fcm.dart create mode 100644 lib/fcs/common/services/messaging_imp.dart create mode 100644 lib/fcs/common/services/messaging_service.dart diff --git a/lib/app.dart b/lib/app.dart index d769bd3..9f597ac 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,6 +1,9 @@ +import 'dart:io'; + import 'package:fcs/fcs/common/localization/app_translations_delegate.dart'; import 'package:fcs/fcs/common/localization/transalation.dart'; import 'package:fcs/fcs/common/pages/model/language_model.dart'; +import 'package:fcs/fcs/common/services/services.dart'; import 'package:fcs/model/buyer_model.dart'; import 'package:fcs/model/delivery_model.dart'; import 'package:fcs/model/discount_model.dart'; @@ -17,6 +20,7 @@ import 'package:fcs/model_fcs/package_model.dart'; import 'package:fcs/pages/email_page.dart'; import 'package:fcs/pages/login_page.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:provider/provider.dart'; import 'package:fcs/fcs/common/pages/model/main_model.dart' as fcs; @@ -82,6 +86,8 @@ class _AppState extends State { final DiscountModel discountModel = new DiscountModel(); AppTranslationsDelegate _newLocaleDelegate; + static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); @override void initState() { @@ -121,6 +127,64 @@ class _AppState extends State { ..addModel(customerModel) ..addModel(discountModel); this.mainModel.init(); + + _initLocalNotifications(); + Services.instance.messagingService.init((message) { + print("Message from FCM:$message"); + _showNotification(message); + }); + } + + _initLocalNotifications() { + var initializationSettingsAndroid = + new AndroidInitializationSettings('@mipmap/ic_launcher'); + var initializationSettingsIOS = new IOSInitializationSettings(); + var initializationSettings = new InitializationSettings( + initializationSettingsAndroid, initializationSettingsIOS); + _flutterLocalNotificationsPlugin.initialize(initializationSettings); + } + + static Future _showNotification(Map message) async { + var pushTitle; + var pushText; + var action; + + if (Platform.isAndroid) { + var nodeData = message['notification']; + pushTitle = nodeData['title']; + pushText = nodeData['body']; + action = nodeData['action']; + } else { + pushTitle = message['title']; + pushText = message['body']; + action = message['action']; + } + print("AppPushs params pushTitle : $pushTitle"); + print("AppPushs params pushText : $pushText"); + print("AppPushs params pushAction : $action"); + + // @formatter:off + var platformChannelSpecificsAndroid = new AndroidNotificationDetails( + 'your channel id', 'your channel name', 'your channel description', + playSound: true, + enableVibration: true, + importance: Importance.Max, + priority: Priority.High); + // @formatter:on + var platformChannelSpecificsIos = + new IOSNotificationDetails(presentSound: true); + var platformChannelSpecifics = new NotificationDetails( + platformChannelSpecificsAndroid, platformChannelSpecificsIos); + + new Future.delayed(Duration.zero, () { + _flutterLocalNotificationsPlugin.show( + 0, + pushTitle, + pushText, + platformChannelSpecifics, + payload: 'No_Sound', + ); + }); } void onLocaleChange(Locale locale) { @@ -146,55 +210,50 @@ class _AppState extends State { @override Widget build(BuildContext context) { return MultiProvider( - providers: [ - ChangeNotifierProvider.value(value: mainModel), - ChangeNotifierProvider.value(value: userModel), - ChangeNotifierProvider.value(value: productModel), - ChangeNotifierProvider.value(value: employeeModel), - ChangeNotifierProvider.value(value: poSubmissionModel), - ChangeNotifierProvider.value(value: doModel), - ChangeNotifierProvider.value(value: storageModel), - ChangeNotifierProvider.value(value: pdModel), - ChangeNotifierProvider.value(value: lanuguageModel), - ChangeNotifierProvider.value(value: regModel), - ChangeNotifierProvider.value(value: buyerModel), - ChangeNotifierProvider.value(value: notificationModel), - ChangeNotifierProvider.value(value: chartModel), - ChangeNotifierProvider.value(value: deliveryModel), - ChangeNotifierProvider.value(value: logModel), - ChangeNotifierProvider.value(value: phoneDeviceModel), - ChangeNotifierProvider.value(value: reportModel), - ChangeNotifierProvider.value(value: announcementModel), - ChangeNotifierProvider.value(value: reportUserModel), - ChangeNotifierProvider.value(value: pickUpModel), - ChangeNotifierProvider.value(value: shipmentRateModel), - ChangeNotifierProvider.value(value: shipmentModel), - ChangeNotifierProvider.value(value: packageModel), - ChangeNotifierProvider.value(value: boxModel), - ChangeNotifierProvider.value(value: messageModel), - ChangeNotifierProvider.value(value: invoiceModel), - ChangeNotifierProvider.value(value: customerModel), - ChangeNotifierProvider.value(value: discountModel), - ChangeNotifierProvider.value(value: testModel), - ChangeNotifierProvider.value(value: mainModel2), - ], - child: Consumer( - builder: (BuildContext context, LanguageModel value, Widget child) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: 'Ok Energy', - routes: route(context), - theme: ThemeData(accentColor: Colors.black), - localizationsDelegates: [ - _newLocaleDelegate, - //provides localised strings - GlobalMaterialLocalizations.delegate, - //provides RTL support - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: Translation().supportedLocales()); - }, - ), - ); + providers: [ + ChangeNotifierProvider.value(value: mainModel), + ChangeNotifierProvider.value(value: userModel), + ChangeNotifierProvider.value(value: productModel), + ChangeNotifierProvider.value(value: employeeModel), + ChangeNotifierProvider.value(value: poSubmissionModel), + ChangeNotifierProvider.value(value: doModel), + ChangeNotifierProvider.value(value: storageModel), + ChangeNotifierProvider.value(value: pdModel), + ChangeNotifierProvider.value(value: lanuguageModel), + ChangeNotifierProvider.value(value: regModel), + ChangeNotifierProvider.value(value: buyerModel), + ChangeNotifierProvider.value(value: notificationModel), + ChangeNotifierProvider.value(value: chartModel), + ChangeNotifierProvider.value(value: deliveryModel), + ChangeNotifierProvider.value(value: logModel), + ChangeNotifierProvider.value(value: phoneDeviceModel), + ChangeNotifierProvider.value(value: reportModel), + ChangeNotifierProvider.value(value: announcementModel), + ChangeNotifierProvider.value(value: reportUserModel), + ChangeNotifierProvider.value(value: pickUpModel), + ChangeNotifierProvider.value(value: shipmentRateModel), + ChangeNotifierProvider.value(value: shipmentModel), + ChangeNotifierProvider.value(value: packageModel), + ChangeNotifierProvider.value(value: boxModel), + ChangeNotifierProvider.value(value: messageModel), + ChangeNotifierProvider.value(value: invoiceModel), + ChangeNotifierProvider.value(value: customerModel), + ChangeNotifierProvider.value(value: discountModel), + ChangeNotifierProvider.value(value: testModel), + ChangeNotifierProvider.value(value: mainModel2), + ], + child: MaterialApp( + debugShowCheckedModeBanner: false, + title: 'FCS', + routes: route(context), + theme: ThemeData(accentColor: Colors.black), + localizationsDelegates: [ + _newLocaleDelegate, + //provides localised strings + GlobalMaterialLocalizations.delegate, + //provides RTL support + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: Translation().supportedLocales())); } } diff --git a/lib/fcs/common/data/providers/messaging_fcm.dart b/lib/fcs/common/data/providers/messaging_fcm.dart new file mode 100644 index 0000000..2b31272 --- /dev/null +++ b/lib/fcs/common/data/providers/messaging_fcm.dart @@ -0,0 +1,66 @@ +import 'package:fcs/fcs/common/services/messaging_service.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:logging/logging.dart'; + +final msgLog = Logger('backgroundMessageHandler'); + +Future backgroundMessageHandler(Map message) async { + if (message.containsKey('data')) { + // Handle data message + final dynamic data = message['data']; + msgLog.info("background onMessage: $message"); + } + + if (message.containsKey('notification')) { + // Handle notification message + final dynamic notification = message['notification']; + } +} + +class MessagingFCM { + final log = Logger('MessagingFCM'); + + FirebaseMessaging _firebaseMessaging; + + MessagingFCM(OnNotify onMessage, {OnNotify onLaunch, OnNotify onResume}) { + _firebaseMessaging = FirebaseMessaging(); + _firebaseMessaging.configure( + onMessage: (Map message) async { + log.info("onMessage: $message"); + if (onMessage != null) _onNotify(message, onMessage); + }, + onBackgroundMessage: backgroundMessageHandler, + onLaunch: (Map message) async { + log.info("onLaunch: $message"); + if (onLaunch != null) _onNotify(message, onLaunch); + }, + onResume: (Map message) async { + log.info("onResume: $message"); + if (onResume != null) _onNotify(message, onResume); + }, + ); + _firebaseMessaging.requestNotificationPermissions( + const IosNotificationSettings( + sound: true, badge: true, alert: true, provisional: true)); + _firebaseMessaging.onIosSettingsRegistered + .listen((IosNotificationSettings settings) { + log.info("Settings registered: $settings"); + }); + _firebaseMessaging.getToken().then((String token) { + log.info("Messaging Token:$token"); + }); + } + + Future subscribeToTopic(String topic) { + return _firebaseMessaging.subscribeToTopic(topic); + } + + _onNotify(Map message, OnNotify onNotify) { + var data = message['data'] ?? message; + onNotify(Map.from(message)); + } + + Future unsubscribeToTopic(String topic) { + return _firebaseMessaging.unsubscribeFromTopic(topic); + } +} diff --git a/lib/fcs/common/pages/signin/code_page.dart b/lib/fcs/common/pages/signin/code_page.dart index e681af0..f534eea 100644 --- a/lib/fcs/common/pages/signin/code_page.dart +++ b/lib/fcs/common/pages/signin/code_page.dart @@ -5,6 +5,7 @@ import 'package:fcs/fcs/common/domain/entities/auth_status.dart'; import 'package:fcs/fcs/common/domain/entities/user.dart'; import 'package:fcs/fcs/common/pages/model/main_model.dart'; import 'package:fcs/fcs/common/pages/util.dart'; +import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; import 'package:fcs/widget/bottom_up_page_route.dart'; import 'package:flutter/material.dart'; import 'package:pin_input_text_field/pin_input_text_field.dart'; @@ -12,7 +13,6 @@ import 'package:provider/provider.dart'; import 'signup_page.dart'; import '../../helpers/theme.dart'; -import '../../../../widget/local_text.dart'; import '../../../../widget/progress.dart'; const resend_count_sec = 5; diff --git a/lib/fcs/common/pages/signin/signin_page.dart b/lib/fcs/common/pages/signin/signin_page.dart index a869786..ba1d2b0 100644 --- a/lib/fcs/common/pages/signin/signin_page.dart +++ b/lib/fcs/common/pages/signin/signin_page.dart @@ -2,6 +2,7 @@ import 'package:country_code_picker/country_code_picker.dart'; import 'package:fcs/fcs/common/domain/entities/auth_result.dart'; import 'package:fcs/fcs/common/domain/entities/auth_status.dart'; import 'package:fcs/fcs/common/pages/model/main_model.dart'; +import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; import 'package:fcs/widget/bottom_up_page_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -9,7 +10,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import '../../helpers/theme.dart'; -import '../../../../widget/local_text.dart'; import '../../../../widget/progress.dart'; import 'code_page.dart'; import '../util.dart'; diff --git a/lib/fcs/common/pages/welcome_page.dart b/lib/fcs/common/pages/welcome_page.dart index d7a9077..f5bc2b6 100644 --- a/lib/fcs/common/pages/welcome_page.dart +++ b/lib/fcs/common/pages/welcome_page.dart @@ -1,6 +1,6 @@ +import 'package:fcs/fcs/common/pages/model/language_model.dart'; import 'package:fcs/fcs/common/pages/model/main_model.dart'; import 'package:fcs/fcs/common/pages/widgets/bottom_widgets.dart'; -import 'package:fcs/model/language_model.dart'; import 'package:fcs/widget/banner.dart'; import 'package:fcs/widget/bottom_up_page_route.dart'; import 'package:fcs/widget/localization/transalation.dart'; @@ -194,7 +194,7 @@ class _WelcomePageState extends State { } _langChange(index) { - var languageModel = Provider.of(context); + var languageModel = Provider.of(context, listen: false); languageModel.saveLanguage(Translation().supportedLanguages[index]); setState(() { isSelected.asMap().forEach((i, e) { diff --git a/lib/fcs/common/pages/widgets/action_button.dart b/lib/fcs/common/pages/widgets/action_button.dart index 66fcc0d..44ed0d5 100644 --- a/lib/fcs/common/pages/widgets/action_button.dart +++ b/lib/fcs/common/pages/widgets/action_button.dart @@ -23,8 +23,8 @@ class ActionButton extends StatelessWidget { onTap: btnCallback != null ? btnCallback : () => {}, child: Container( width: 120, - height: 150, - padding: EdgeInsets.only(top:15.0), + height: 130, + padding: EdgeInsets.only(top: 10.0, left: 5, right: 5), decoration: new BoxDecoration( color: Colors.transparent, borderRadius: new BorderRadius.only( diff --git a/lib/fcs/common/services/messaging_imp.dart b/lib/fcs/common/services/messaging_imp.dart new file mode 100644 index 0000000..2d9940b --- /dev/null +++ b/lib/fcs/common/services/messaging_imp.dart @@ -0,0 +1,25 @@ +import 'package:fcs/fcs/common/data/providers/messaging_fcm.dart'; + +import 'messaging_service.dart'; + +class MessagingServiceImp implements MessagingService { + MessagingServiceImp(); + + static MessagingFCM messagingFCM; + + @override + void init(onMessage, {OnNotify onLaunch, OnNotify onResume}) { + messagingFCM = + MessagingFCM(onMessage, onLaunch: onLaunch, onResume: onResume); + } + + @override + Future subscribe(String topic) { + return messagingFCM.unsubscribeToTopic(topic); + } + + @override + Future unsubscribe(String topic) { + return messagingFCM.unsubscribeToTopic(topic); + } +} diff --git a/lib/fcs/common/services/messaging_service.dart b/lib/fcs/common/services/messaging_service.dart new file mode 100644 index 0000000..f22ecd4 --- /dev/null +++ b/lib/fcs/common/services/messaging_service.dart @@ -0,0 +1,7 @@ +typedef OnNotify(Map message); + +abstract class MessagingService { + void init(OnNotify onMessage, {OnNotify onLaunch, OnNotify onResume}); + Future subscribe(String topic); + Future unsubscribe(String topic); +} diff --git a/lib/fcs/common/services/services.dart b/lib/fcs/common/services/services.dart index 912d376..560525d 100644 --- a/lib/fcs/common/services/services.dart +++ b/lib/fcs/common/services/services.dart @@ -1,5 +1,7 @@ import 'package:fcs/fcs/common/data/providers/auth_fb.dart'; import 'package:fcs/fcs/common/services/auth_imp.dart'; +import 'package:fcs/fcs/common/services/messaging_imp.dart'; +import 'package:fcs/fcs/common/services/messaging_service.dart'; import 'auth_service.dart'; @@ -7,13 +9,16 @@ class Services { static final Services instance = Services._(); AuthService _authService; + MessagingService _messagingService; Services._() { _authService = AuthServiceImp( authFb: AuthFb.instance, connectivity: null, userFBDataProvider: null, userLocalDataProvider: null); + _messagingService = MessagingServiceImp(); } AuthService get authService => _authService; + MessagingService get messagingService => _messagingService; } diff --git a/lib/main-dev.dart b/lib/main-dev.dart index 9ebdbaf..cd69cbe 100644 --- a/lib/main-dev.dart +++ b/lib/main-dev.dart @@ -5,6 +5,7 @@ import 'package:logging/logging.dart'; import 'app.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); Config( flavor: Flavor.DEV, color: Colors.blue, diff --git a/lib/main-local.dart b/lib/main-local.dart index eb80cc2..5d60521 100644 --- a/lib/main-local.dart +++ b/lib/main-local.dart @@ -1,14 +1,15 @@ +import 'package:fcs/config.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; -import 'package:fcs/config.dart'; import 'app.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); Config( flavor: Flavor.DEV, color: Colors.blue, - apiURL: "http://192.168.1.155:7777", + apiURL: "http://192.168.100.11:7777", level: Level.ALL); runApp(App()); } diff --git a/lib/main-prod.dart b/lib/main-prod.dart index 7314fac..34ef854 100644 --- a/lib/main-prod.dart +++ b/lib/main-prod.dart @@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'app.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); Config( flavor: Flavor.PRODUCTION, color: Colors.blue, diff --git a/pubspec.yaml b/pubspec.yaml index 1ce2236..c377aaf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -73,6 +73,7 @@ dependencies: timeline_list: ^0.0.5 barcode_scan: ^3.0.1 flutter_pdfview: ^1.0.3 + flutter_local_notifications: ^1.4.4+4