From 48c91d2c9c4ced92b261141a3c42a3fb0d3ae54c Mon Sep 17 00:00:00 2001 From: lowrt Date: Wed, 16 Jul 2025 21:57:17 +0800 Subject: [PATCH 1/7] refactor(service): migrate background service to awesome_notifications --- lib/core/service.dart | 83 ++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/lib/core/service.dart b/lib/core/service.dart index ac14809ec..272553d32 100644 --- a/lib/core/service.dart +++ b/lib/core/service.dart @@ -2,24 +2,21 @@ import 'dart:async'; import 'dart:io'; import 'dart:ui'; -import 'package:dpip/utils/extensions/latlng.dart'; -import 'package:flutter/cupertino.dart'; - -import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:intl/intl.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:permission_handler/permission_handler.dart'; - import 'package:dpip/api/exptech.dart'; -import 'package:dpip/app_old/page/home/home.dart'; import 'package:dpip/app_old/page/map/radar/radar.dart'; import 'package:dpip/core/location.dart'; import 'package:dpip/core/preference.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/global.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/location_to_code.dart'; import 'package:dpip/utils/log.dart'; +import 'package:awesome_notifications/awesome_notifications.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:intl/intl.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:permission_handler/permission_handler.dart'; Timer? _locationUpdateTimer; final _backgroundService = FlutterBackgroundService(); @@ -87,7 +84,6 @@ void _setupPositionListener() { GlobalProviders.location.setCode(location?.code.toString()); GlobalProviders.location.setLatLng(latitude: latitude, longitude: longitude); - HomePage.updatePosition(); RadarMap.updatePosition(); }); @@ -101,26 +97,24 @@ void _setupPositionListener() { Future _initializeAndroidForegroundService() async { _isAndroidServiceInitialized = true; - const notificationChannel = AndroidNotificationChannel( - 'my_foreground', - '前景自動定位', - description: '前景自動定位', - importance: Importance.low, - ); - - final notifications = FlutterLocalNotificationsPlugin(); - await notifications.initialize( - const InitializationSettings( - iOS: DarwinInitializationSettings(), - android: AndroidInitializationSettings('@mipmap/ic_launcher'), - ), + await AwesomeNotifications().initialize( + null, // 使用預設 launcher icon + [ + NotificationChannel( + channelKey: 'my_foreground', + channelName: '前景自動定位', + channelDescription: '背景定位服務通知', + importance: NotificationImportance.Low, + defaultColor: const Color(0xFF2196f3), + ledColor: Colors.white, + locked: true, + playSound: false, + onlyAlertOnce: true, + ) + ], ); - await notifications - .resolvePlatformSpecificImplementation() - ?.createNotificationChannel(notificationChannel); - await _backgroundService.configure( androidConfiguration: AndroidConfiguration( onStart: _onServiceStart, @@ -150,7 +144,6 @@ Future _onServiceStart(ServiceInstance service) async { GlobalProviders.init(); final locationService = LocationService(); - final notifications = FlutterLocalNotificationsPlugin(); // Setup service event listeners service.on(ServiceEvent.stopService.name).listen((event) { @@ -166,12 +159,16 @@ Future _onServiceStart(ServiceInstance service) async { if (service is AndroidServiceInstance) { // Initialize foreground service and notification await service.setAsForegroundService(); - await notifications.show( - 888, - 'DPIP', - '前景服務啟動中...', - const NotificationDetails( - android: AndroidNotificationDetails('my_foreground', '前景自動定位', icon: '@drawable/ic_stat_name', ongoing: true), + await AwesomeNotifications().createNotification( + content: NotificationContent( + id: 888, + channelKey: 'my_foreground', + title: 'DPIP', + body: '前景服務啟動中...', + notificationLayout: NotificationLayout.Default, + locked: true, + autoDismissible: false, + icon: 'resource://drawable/ic_stat_name', ), ); @@ -187,6 +184,7 @@ Future _onServiceStart(ServiceInstance service) async { // Define the periodic location update task Future updateLocation() async { + _locationUpdateTimer?.cancel(); if (!await service.isForegroundService()) return; // Get current position and location info @@ -213,12 +211,15 @@ Future _onServiceStart(ServiceInstance service) async { final notificationBody = '$timestamp\n$latitude,$longitude $locationName'; service.invoke(ServiceEvent.sendDebug.name, {'notifyBody': notificationBody}); - await notifications.show( - 888, - notificationTitle, - notificationBody, - const NotificationDetails( - android: AndroidNotificationDetails('my_foreground', '前景自動定位', icon: 'ic_stat_name', ongoing: true), + await AwesomeNotifications().createNotification( + content: NotificationContent( + id: 888, + channelKey: 'my_foreground', + title: notificationTitle, + body: notificationBody, + notificationLayout: NotificationLayout.Default, + locked: true, + autoDismissible: false, ), ); service.setForegroundNotificationInfo(title: notificationTitle, content: notificationBody); From c7993d5906844829287d4ecc40622a333cae6244 Mon Sep 17 00:00:00 2001 From: lowrt Date: Wed, 16 Jul 2025 22:01:01 +0800 Subject: [PATCH 2/7] chore(pubspec): remove flutter_local_notifications --- pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d892a9598..38f3d8a62 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,7 +31,6 @@ dependencies: url: https://github.com/ExpTechTW/flutter_background_service.git path: packages/flutter_background_service ref: master - flutter_local_notifications: ^19.1.0 flutter_localizations: sdk: flutter flutter_markdown: ^0.7.7 From cbf8dd7fc84a593d3b17a87f117b5c3a44433055 Mon Sep 17 00:00:00 2001 From: lowrt Date: Thu, 17 Jul 2025 20:12:24 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix(core/notify)=EF=BB=BF:=EF=BB=BF=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/notify.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/notify.dart b/lib/core/notify.dart index 5939ae72a..52dbbcb6f 100644 --- a/lib/core/notify.dart +++ b/lib/core/notify.dart @@ -240,7 +240,7 @@ Future notifyInit() async { channelGroupKey: 'group_evacuation', channelKey: 'evacuation_minor-general-v2', channelName: '避難資訊(一般)', - channelDescription: '所在地(鄉鎮)發布防空、土石流、淹水或堰塞湖避難警訊時', + channelDescription: '所在地(鄉鎮)發布防空、土石流、淹水或堰塞湖避難資訊時', importance: NotificationImportance.High, defaultPrivacy: NotificationPrivacy.Public, playSound: true, @@ -285,7 +285,7 @@ Future notifyInit() async { channelGroupKey: 'group_tsunami', channelKey: 'tsunami-silent-v2', channelName: '太平洋海嘯消息 (無聲通知)', - channelDescription: '地震報告所在地震度 3 以下的地區', + channelDescription: '太平洋海嘯消息發布時', groupAlertBehavior: GroupAlertBehavior.Children, importance: NotificationImportance.Min, defaultPrivacy: NotificationPrivacy.Public, From b029ec72a42018258407b3f6a9af2651f2a71ec1 Mon Sep 17 00:00:00 2001 From: lowrt Date: Thu, 17 Jul 2025 20:12:39 +0800 Subject: [PATCH 4/7] fix --- ios/Runner/AppDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index ec02dba7d..c8167ccd7 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -49,7 +49,7 @@ class AppDelegate: FlutterAppDelegate, CLLocationManagerDelegate { } // MARK: - Setup Methods - + private func setupFlutterChannels() { guard let controller = window?.rootViewController as? FlutterViewController else { return } From 3af623beb48a242b715ef0210e7d411747c6dbdb Mon Sep 17 00:00:00 2001 From: lowrt Date: Thu, 17 Jul 2025 20:14:13 +0800 Subject: [PATCH 5/7] build: 3.0.014 --- android/app/build.gradle | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index c70369baf..f9a625f92 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -49,7 +49,7 @@ android { applicationId "com.exptech.dpip" minSdkVersion 26 targetSdkVersion 35 - versionCode 300001305 + versionCode 300001400 versionName flutterVersionName multiDexEnabled true } diff --git a/pubspec.yaml b/pubspec.yaml index 7fefe9a98..b9302abd2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: dpip description: "Disaster Prevention Information Platform" publish_to: 'none' -version: 3.0.013 +version: 3.0.014 environment: sdk: '>=3.7.0 <4.0.0' From 9d1c9382e9b7dea2578c662e24beb9ec2b49c5ca Mon Sep 17 00:00:00 2001 From: lowrt Date: Thu, 17 Jul 2025 21:46:46 +0800 Subject: [PATCH 6/7] fix: AndroidManifest --- android/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 554cafb63..76ae559c1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,7 +30,7 @@ Date: Fri, 18 Jul 2025 19:25:47 +0800 Subject: [PATCH 7/7] fix: Preferences --- android/app/build.gradle | 1 + android/app/src/main/AndroidManifest.xml | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f9a625f92..1461aeda4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -90,6 +90,7 @@ flutter { } dependencies { + implementation 'org.maplibre.gl:android-sdk:11.5.2' implementation 'androidx.core:core-splashscreen:1.0.1' implementation 'com.google.android.material:material:1.12.0' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4' diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 76ae559c1..ee4ac1737 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -26,11 +26,12 @@ android:name="${applicationName}" android:icon="@mipmap/ic_launcher" android:theme="@style/LaunchTheme" - android:enableOnBackInvokedCallback="true"> + android:enableOnBackInvokedCallback="true" + android:allowBackup="false" + tools:replace="android:allowBackup">