♿ Optimize notification background service
This commit is contained in:
parent
a487924300
commit
306ce9e2b4
109
lib/background.dart
Normal file
109
lib/background.dart
Normal file
@ -0,0 +1,109 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:solian/models/notification.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/providers/websocket.dart';
|
||||
|
||||
FlutterBackgroundService? bgNotificationService;
|
||||
|
||||
void autoConfigureBackgroundNotificationService() async {
|
||||
if (bgNotificationService != null) return;
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getBool('service_background_notification') != true) return;
|
||||
|
||||
bgNotificationService = FlutterBackgroundService();
|
||||
|
||||
await bgNotificationService!.configure(
|
||||
androidConfiguration: AndroidConfiguration(
|
||||
onStart: onBackgroundNotificationServiceStart,
|
||||
autoStart: true,
|
||||
autoStartOnBoot: true,
|
||||
isForegroundMode: false,
|
||||
),
|
||||
// This feature won't be able to use on iOS
|
||||
// We got APNs support covered
|
||||
iosConfiguration: IosConfiguration(
|
||||
autoStart: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void autoStartBackgroundNotificationService() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getBool('service_background_notification') != true) return;
|
||||
if (bgNotificationService == null) return;
|
||||
bgNotificationService!.startService();
|
||||
}
|
||||
|
||||
void autoStopBackgroundNotificationService() async {
|
||||
if (bgNotificationService == null) return;
|
||||
if (await bgNotificationService!.isRunning()) {
|
||||
bgNotificationService?.invoke('stopService');
|
||||
}
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void onBackgroundNotificationServiceStart(ServiceInstance service) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
DartPluginRegistrant.ensureInitialized();
|
||||
|
||||
Get.put(AuthProvider());
|
||||
Get.put(WebSocketProvider());
|
||||
|
||||
service.on('stopService').listen((event) {
|
||||
service.stopSelf();
|
||||
});
|
||||
|
||||
final auth = Get.find<AuthProvider>();
|
||||
await auth.refreshAuthorizeStatus();
|
||||
await auth.ensureCredentials();
|
||||
if (!auth.isAuthorized.value) {
|
||||
debugPrint(
|
||||
'Background notification do nothing due to user didn\'t sign in.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const notificationChannelId = 'solian_notification_service';
|
||||
|
||||
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
final ws = Get.find<WebSocketProvider>();
|
||||
await ws.connect();
|
||||
debugPrint('Background notification has been started');
|
||||
ws.stream.stream.listen(
|
||||
(event) {
|
||||
debugPrint(
|
||||
'Background notification service incoming message: ${event.method} ${event.message}',
|
||||
);
|
||||
|
||||
if (event.method == 'notifications.new' && event.payload != null) {
|
||||
final data = Notification.fromJson(event.payload!);
|
||||
debugPrint(
|
||||
'Background notification service got a notification id=${data.id}',
|
||||
);
|
||||
flutterLocalNotificationsPlugin.show(
|
||||
data.id,
|
||||
data.title,
|
||||
[data.subtitle, data.body].where((x) => x != null).join('\n'),
|
||||
const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
notificationChannelId,
|
||||
'Solian Notification Service',
|
||||
channelDescription: 'Notifications that sent via Solar Network',
|
||||
importance: Importance.high,
|
||||
icon: 'mipmap/ic_launcher',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
@ -4,16 +4,13 @@ import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/material.dart' hide Notification;
|
||||
import 'package:flutter_acrylic/flutter_acrylic.dart';
|
||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:protocol_handler/protocol_handler.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:solian/background.dart';
|
||||
import 'package:solian/bootstrapper.dart';
|
||||
import 'package:solian/firebase_options.dart';
|
||||
import 'package:solian/models/notification.dart';
|
||||
import 'package:solian/platform.dart';
|
||||
import 'package:solian/providers/attachment_uploader.dart';
|
||||
import 'package:solian/providers/daily_sign.dart';
|
||||
@ -70,82 +67,7 @@ Future<void> _initializeFirebase() async {
|
||||
}
|
||||
|
||||
Future<void> _initializeBackgroundNotificationService() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getBool('service_background_notification') != true) return;
|
||||
|
||||
final service = FlutterBackgroundService();
|
||||
|
||||
await service.configure(
|
||||
androidConfiguration: AndroidConfiguration(
|
||||
onStart: onBackgroundNotificationServiceStart,
|
||||
autoStart: true,
|
||||
autoStartOnBoot: true,
|
||||
isForegroundMode: false,
|
||||
),
|
||||
// This feature won't be able to use on iOS
|
||||
// We got APNs support covered
|
||||
iosConfiguration: IosConfiguration(
|
||||
autoStart: false,
|
||||
),
|
||||
);
|
||||
|
||||
await service.startService();
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void onBackgroundNotificationServiceStart(ServiceInstance service) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
DartPluginRegistrant.ensureInitialized();
|
||||
|
||||
Get.put(AuthProvider());
|
||||
Get.put(WebSocketProvider());
|
||||
|
||||
final auth = Get.find<AuthProvider>();
|
||||
await auth.refreshAuthorizeStatus();
|
||||
await auth.ensureCredentials();
|
||||
if (!auth.isAuthorized.value) {
|
||||
debugPrint(
|
||||
'Background notification do nothing due to user didn\'t sign in.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const notificationChannelId = 'solian_notification_service';
|
||||
|
||||
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
final ws = Get.find<WebSocketProvider>();
|
||||
await ws.connect();
|
||||
debugPrint('Background notification has been started');
|
||||
ws.stream.stream.listen(
|
||||
(event) {
|
||||
debugPrint(
|
||||
'Background notification service incoming message: ${event.method} ${event.message}',
|
||||
);
|
||||
|
||||
if (event.method == 'notifications.new' && event.payload != null) {
|
||||
final data = Notification.fromJson(event.payload!);
|
||||
debugPrint(
|
||||
'Background notification service got a notification id=${data.id}',
|
||||
);
|
||||
flutterLocalNotificationsPlugin.show(
|
||||
data.id,
|
||||
data.title,
|
||||
[data.subtitle, data.body].where((x) => x != null).join('\n'),
|
||||
const NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
notificationChannelId,
|
||||
'Solian Notification Service',
|
||||
channelDescription: 'Notifications that sent via Solar Network',
|
||||
importance: Importance.high,
|
||||
icon: 'mipmap/ic_launcher',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
autoConfigureBackgroundNotificationService();
|
||||
}
|
||||
|
||||
Future<void> _initializePlatformComponents() async {
|
||||
|
@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_connect/http/src/request/request.dart';
|
||||
import 'package:solian/background.dart';
|
||||
import 'package:solian/exceptions/request.dart';
|
||||
import 'package:solian/exceptions/unauthorized.dart';
|
||||
import 'package:solian/providers/database/database.dart';
|
||||
@ -200,6 +201,7 @@ class AuthProvider extends GetConnect {
|
||||
Get.find<WebSocketProvider>().notificationUnread.value = 0;
|
||||
|
||||
AppDatabase.removeDatabase();
|
||||
autoStopBackgroundNotificationService();
|
||||
|
||||
storage.deleteAll();
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:protocol_handler/protocol_handler.dart';
|
||||
import 'package:solian/background.dart';
|
||||
import 'package:solian/exts.dart';
|
||||
import 'package:solian/providers/websocket.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
@ -22,7 +23,7 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
final _usernameController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
|
||||
void requestResetPassword() async {
|
||||
void _requestResetPassword() async {
|
||||
final username = _usernameController.value.text;
|
||||
if (username.isEmpty) {
|
||||
context.showErrorDialog('signinResetPasswordHint'.tr);
|
||||
@ -52,7 +53,7 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
context.showModalDialog('done'.tr, 'signinResetPasswordSent'.tr);
|
||||
}
|
||||
|
||||
void performAction() async {
|
||||
void _performAction() async {
|
||||
final AuthProvider auth = Get.find();
|
||||
|
||||
final username = _usernameController.value.text;
|
||||
@ -100,6 +101,8 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
}
|
||||
|
||||
Get.find<WebSocketProvider>().registerPushNotifications();
|
||||
autoConfigureBackgroundNotificationService();
|
||||
autoStartBackgroundNotificationService();
|
||||
|
||||
Navigator.pop(context, true);
|
||||
}
|
||||
@ -121,7 +124,7 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
final uri = url.replaceFirst('solink://', '');
|
||||
if (uri == 'auth?status=done') {
|
||||
closeInAppWebView();
|
||||
performAction();
|
||||
_performAction();
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,19 +178,19 @@ class _SignInPopupState extends State<SignInPopup> with ProtocolListener {
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
onSubmitted: (_) => performAction(),
|
||||
onSubmitted: (_) => _performAction(),
|
||||
),
|
||||
const Gap(12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: _isBusy ? null : () => requestResetPassword(),
|
||||
onPressed: _isBusy ? null : () => _requestResetPassword(),
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.grey),
|
||||
child: Text('forgotPassword'.tr),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _isBusy ? null : () => performAction(),
|
||||
onPressed: _isBusy ? null : () => _performAction(),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
Loading…
Reference in New Issue
Block a user