Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: 8.12.0 #288

Merged
merged 3 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 8.12.0

* [**FEAT**] Add `setOnlyAlertOnce` option to AndroidNotificationOptions [pr-#287](https://github.com/Dev-hwang/flutter_foreground_task/pull/287)
* [**CHANGE**] Change notification channel importance from `DEFAULT` to `LOW`

## 8.11.0

* [**FEAT**] Allow sending Set collection using `FlutterForegroundTask.sendDataToMain`
Expand Down
56 changes: 12 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To use this plugin, add `flutter_foreground_task` as a [dependency in your pubsp

```yaml
dependencies:
flutter_foreground_task: ^8.11.0
flutter_foreground_task: ^8.12.0
```

After adding the plugin to your flutter project, we need to declare the platform-specific permissions ans service to use for this plugin to work properly.
Expand Down Expand Up @@ -113,10 +113,10 @@ Open the `ios/Runner/AppDelegate.swift` file and add the commented code.
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"

// here
// this
#import <flutter_foreground_task/FlutterForegroundTaskPlugin.h>

// here
// this
void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
[GeneratedPluginRegistrant registerWithRegistry:registry];
}
Expand All @@ -127,7 +127,7 @@ void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];

// here
// this
[FlutterForegroundTaskPlugin setPluginRegistrantCallback:registerPlugins];
if (@available(iOS 10.0, *)) {
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
Expand All @@ -153,15 +153,15 @@ Open the `ios/Runner/AppDelegate.swift` file and add the commented code.
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)

// here
// this
SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback { registry in
GeneratedPluginRegistrant.register(with: registry)
}
Expand Down Expand Up @@ -234,25 +234,6 @@ class MyTaskHandler extends TaskHandler {
void onNotificationButtonPressed(String id) {
print('onNotificationButtonPressed: $id');
}

// Called when the notification itself is pressed.
//
// AOS: "android.permission.SYSTEM_ALERT_WINDOW" permission must be granted
// for this function to be called.
@override
void onNotificationPressed() {
FlutterForegroundTask.launchApp('/');
print('onNotificationPressed');
}

// Called when the notification itself is dismissed.
//
// AOS: only work Android 14+
// iOS: only work iOS 10+
@override
void onNotificationDismissed() {
print('onNotificationDismissed');
}
}
```

Expand Down Expand Up @@ -299,19 +280,6 @@ Future<void> _requestPermissions() async {
}

if (Platform.isAndroid) {
// "android.permission.SYSTEM_ALERT_WINDOW" permission must be granted for
// onNotificationPressed function to be called.
//
// When the notification is pressed while permission is denied,
// the onNotificationPressed function is not called and the app opens.
//
// If you do not use the onNotificationPressed or launchApp function,
// you do not need to write this code.
if (!await FlutterForegroundTask.canDrawOverlays) {
// This function requires `android.permission.SYSTEM_ALERT_WINDOW` permission.
await FlutterForegroundTask.openSystemAlertWindowSettings();
}

// Android 12+, there are restrictions on starting a foreground service.
//
// To restart the service on device reboot or unexpected problem, you need to allow below permission.
Expand Down Expand Up @@ -340,8 +308,7 @@ void _initService() {
channelName: 'Foreground Service Notification',
channelDescription:
'This notification appears when the foreground service is running.',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
onlyAlertOnce: true,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
Expand All @@ -363,9 +330,9 @@ void initState() {
// Add a callback to receive data sent from the TaskHandler.
FlutterForegroundTask.addTaskDataCallback(_onReceiveTaskData);

WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
// Request permissions and initialize the service.
_requestPermissions();
await _requestPermissions();
_initService();
});
}
Expand Down Expand Up @@ -434,7 +401,7 @@ class FirstTaskHandler extends TaskHandler {
);
} else {
FlutterForegroundTask.updateService(
notificationTitle: 'FirstTask',
notificationTitle: 'Hello FirstTaskHandler :)',
notificationText: timestamp.toString(),
);

Expand Down Expand Up @@ -466,7 +433,7 @@ class SecondTaskHandler extends TaskHandler {
@override
void onRepeatEvent(DateTime timestamp) {
FlutterForegroundTask.updateService(
notificationTitle: 'SecondTask',
notificationTitle: 'Hello SecondTaskHandler :)',
notificationText: timestamp.toString(),
);

Expand Down Expand Up @@ -585,6 +552,7 @@ class MyTaskHandler extends TaskHandler {
* [`internal_plugin_service`](https://github.com/Dev-hwang/flutter_foreground_task_example/tree/main/internal_plugin_service) (Recommend)
* [`location_service`](https://github.com/Dev-hwang/flutter_foreground_task_example/tree/main/location_service)
* [`record_service`](https://github.com/Dev-hwang/flutter_foreground_task_example/tree/main/record_service)
* [`geofencing_service`](https://github.com/Dev-hwang/flutter_foreground_task_example/tree/main/geofencing_service)

## More Documentation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ data class NotificationOptions(
val channelId = prefs.getString(PrefsKey.NOTIFICATION_CHANNEL_ID, null) ?: "foreground_service"
val channelName = prefs.getString(PrefsKey.NOTIFICATION_CHANNEL_NAME, null) ?: "Foreground Service"
val channelDesc = prefs.getString(PrefsKey.NOTIFICATION_CHANNEL_DESC, null)
val channelImportance = prefs.getInt(PrefsKey.NOTIFICATION_CHANNEL_IMPORTANCE, 3)
val priority = prefs.getInt(PrefsKey.NOTIFICATION_PRIORITY, 0)
val channelImportance = prefs.getInt(PrefsKey.NOTIFICATION_CHANNEL_IMPORTANCE, 2)
val priority = prefs.getInt(PrefsKey.NOTIFICATION_PRIORITY, -1)
val enableVibration = prefs.getBoolean(PrefsKey.ENABLE_VIBRATION, false)
val playSound = prefs.getBoolean(PrefsKey.PLAY_SOUND, false)
val showWhen = prefs.getBoolean(PrefsKey.SHOW_WHEN, false)
Expand Down Expand Up @@ -61,8 +61,8 @@ data class NotificationOptions(
val channelId = map?.get(PrefsKey.NOTIFICATION_CHANNEL_ID) as? String
val channelName = map?.get(PrefsKey.NOTIFICATION_CHANNEL_NAME) as? String
val channelDesc = map?.get(PrefsKey.NOTIFICATION_CHANNEL_DESC) as? String
val channelImportance = map?.get(PrefsKey.NOTIFICATION_CHANNEL_IMPORTANCE) as? Int ?: 3
val priority = map?.get(PrefsKey.NOTIFICATION_PRIORITY) as? Int ?: 0
val channelImportance = map?.get(PrefsKey.NOTIFICATION_CHANNEL_IMPORTANCE) as? Int ?: 2
val priority = map?.get(PrefsKey.NOTIFICATION_PRIORITY) as? Int ?: -1
val enableVibration = map?.get(PrefsKey.ENABLE_VIBRATION) as? Boolean ?: false
val playSound = map?.get(PrefsKey.PLAY_SOUND) as? Boolean ?: false
val showWhen = map?.get(PrefsKey.SHOW_WHEN) as? Boolean ?: false
Expand Down
25 changes: 13 additions & 12 deletions documentation/models_documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

Notification options for Android platform.

| Property | Description |
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `channelId` | Unique ID of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelName` | The name of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelDescription` | The description of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelImportance` | The importance of the notification channel. The default is `NotificationChannelImportance.DEFAULT`. It is set only once for the first time on Android 8.0+. |
| `priority` | Priority of notifications for Android 7.1 and lower. The default is `NotificationPriority.DEFAULT`. |
| `enableVibration` | Whether to enable vibration when creating notifications. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `playSound` | Whether to play sound when creating notifications. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `showWhen` | Whether to show the timestamp when the notification was created in the content view. The default is `false`. |
| `showBadge` | Whether to show the badge near the app icon when service is started. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `visibility` | Control the level of detail displayed in notifications on the lock screen. The default is `NotificationVisibility.VISIBILITY_PUBLIC`. |
| Property | Description |
|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| `channelId` | Unique ID of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelName` | The name of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelDescription` | The description of the notification channel. It is set only once for the first time on Android 8.0+. |
| `channelImportance` | The importance of the notification channel. The default is `NotificationChannelImportance.LOW`. It is set only once for the first time on Android 8.0+. |
| `priority` | Priority of notifications for Android 7.1 and lower. The default is `NotificationPriority.LOW`. |
| `enableVibration` | Whether to enable vibration when creating notifications. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `playSound` | Whether to play sound when creating notifications. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `showWhen` | Whether to show the timestamp when the notification was created in the content view. The default is `false`. |
| `showBadge` | Whether to show the badge near the app icon when service is started. The default is `false`. It is set only once for the first time on Android 8.0+. |
| `onlyAlertOnce` | Whether to only alert once when the notification is created. The default is `false`. |
| `visibility` | Control the level of detail displayed in notifications on the lock screen. The default is `NotificationVisibility.VISIBILITY_PUBLIC`. |

### :chicken: IOSNotificationOptions

Expand Down
10 changes: 4 additions & 6 deletions example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)

SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback(registerPlugins)
SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback { registry in
GeneratedPluginRegistrant.register(with: registry)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

func registerPlugins(registry: FlutterPluginRegistry) {
GeneratedPluginRegistrant.register(with: registry)
}
43 changes: 24 additions & 19 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class ExamplePage extends StatefulWidget {
}

class _ExamplePageState extends State<ExamplePage> {
final ValueNotifier<Object?> _receivedTaskData = ValueNotifier(null);
final ValueNotifier<Object?> _taskDataListenable = ValueNotifier(null);

Future<void> _requestPermissions() async {
// Android 13+, you need to allow notification permission to display foreground service notification.
Expand Down Expand Up @@ -167,8 +167,7 @@ class _ExamplePageState extends State<ExamplePage> {
channelName: 'Foreground Service Notification',
channelDescription:
'This notification appears when the foreground service is running.',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
onlyAlertOnce: true,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
Expand Down Expand Up @@ -207,7 +206,7 @@ class _ExamplePageState extends State<ExamplePage> {

void _onReceiveTaskData(Object data) {
print('onReceiveTaskData: $data');
_receivedTaskData.value = data;
_taskDataListenable.value = data;
}

void _incrementCount() {
Expand All @@ -220,9 +219,9 @@ class _ExamplePageState extends State<ExamplePage> {
// Add a callback to receive data sent from the TaskHandler.
FlutterForegroundTask.addTaskDataCallback(_onReceiveTaskData);

WidgetsBinding.instance.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
// Request permissions and initialize the service.
_requestPermissions();
await _requestPermissions();
_initService();
});
}
Expand All @@ -231,7 +230,7 @@ class _ExamplePageState extends State<ExamplePage> {
void dispose() {
// Remove a callback to receive data sent from the TaskHandler.
FlutterForegroundTask.removeTaskDataCallback(_onReceiveTaskData);
_receivedTaskData.dispose();
_taskDataListenable.dispose();
super.dispose();
}

Expand All @@ -244,27 +243,33 @@ class _ExamplePageState extends State<ExamplePage> {
// This widget must be declared above the [Scaffold] widget.
return WithForegroundTask(
child: Scaffold(
appBar: AppBar(
title: const Text('Flutter Foreground Task'),
centerTitle: true,
),
body: _buildContentView(),
appBar: _buildAppBar(),
body: _buildContent(),
),
);
}

Widget _buildContentView() {
return Column(
children: [
Expanded(child: _buildCommunicationText()),
_buildServiceControlButtons(),
],
AppBar _buildAppBar() {
return AppBar(
title: const Text('Flutter Foreground Task'),
centerTitle: true,
);
}

Widget _buildContent() {
return SafeArea(
child: Column(
children: [
Expanded(child: _buildCommunicationText()),
_buildServiceControlButtons(),
],
),
);
}

Widget _buildCommunicationText() {
return ValueListenableBuilder(
valueListenable: _receivedTaskData,
valueListenable: _taskDataListenable,
builder: (context, data, _) {
return Center(
child: Column(
Expand Down
8 changes: 4 additions & 4 deletions lib/models/notification_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class AndroidNotificationOptions {
required this.channelId,
required this.channelName,
this.channelDescription,
this.channelImportance = NotificationChannelImportance.DEFAULT,
this.priority = NotificationPriority.DEFAULT,
this.channelImportance = NotificationChannelImportance.LOW,
this.priority = NotificationPriority.LOW,
this.enableVibration = false,
this.playSound = false,
this.showWhen = false,
Expand Down Expand Up @@ -40,13 +40,13 @@ class AndroidNotificationOptions {
final String? channelDescription;

/// The importance of the notification channel.
/// The default is `NotificationChannelImportance.DEFAULT`.
/// The default is `NotificationChannelImportance.LOW`.
///
/// It is set only once for the first time on Android 8.0+.
final NotificationChannelImportance channelImportance;

/// Priority of notifications for Android 7.1 and lower.
/// The default is `NotificationPriority.DEFAULT`.
/// The default is `NotificationPriority.LOW`.
final NotificationPriority priority;

/// Whether to enable vibration when creating notifications.
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_foreground_task
description: This plugin is used to implement a foreground service on the Android platform.
version: 8.11.0
version: 8.12.0
homepage: https://github.com/Dev-hwang/flutter_foreground_task

environment:
Expand Down
6 changes: 3 additions & 3 deletions test/dummy/service_dummy_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class ServiceDummyData {
channelId: 'test_channel',
channelName: 'Test Channel',
channelDescription: 'Test Channel Description',
channelImportance: NotificationChannelImportance.DEFAULT,
priority: NotificationPriority.DEFAULT,
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
enableVibration: false,
playSound: false,
showWhen: false,
Expand All @@ -25,7 +25,7 @@ class ServiceDummyData {

final IOSNotificationOptions iosNotificationOptions =
const IOSNotificationOptions(
showNotification: true,
showNotification: false,
playSound: false,
);

Expand Down