From 26580201786272b1228ca65c5e34aae412e7b138 Mon Sep 17 00:00:00 2001 From: Hwang WooJin <47127353+Dev-hwang@users.noreply.github.com> Date: Mon, 9 Sep 2024 20:27:17 +0900 Subject: [PATCH] docs: Update example and readme --- README.md | 34 +++++++---------- example/lib/main.dart | 86 +++++++++++++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 81003570..aec7409d 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ After adding the `flutter_foreground_task` plugin to the flutter project, we nee ### :baby_chick: Android -Open the `AndroidManifest.xml` file and specify the service inside the `` tag as follows. If you want the foreground service to run only when the app is running, add `android:stopWithTask` option. +Open the `AndroidManifest.xml` file and specify the service inside the `` tag as follows. + +If you want the foreground service to run only when the app is running, add `android:stopWithTask="true"` option. As it is mentioned in the Android Guidelines, in Android 14, to start a FG service, you need to specify `android:foregroundServiceType`. @@ -47,7 +49,6 @@ Change the type with your type (all types are listed in the link above). - _requestPermissions() async { // Android 13+, you need to allow notification permission to display foreground service notification. // // iOS: If you need notification, ask for permission. - final NotificationPermission notificationPermissionStatus = + final NotificationPermission notificationPermission = await FlutterForegroundTask.checkNotificationPermission(); - if (notificationPermissionStatus != NotificationPermission.granted) { + if (notificationPermission != NotificationPermission.granted) { await FlutterForegroundTask.requestNotificationPermission(); } @@ -308,7 +309,7 @@ Future _requestPermissions() async { } } -Future _initService() async { +void _initService() { FlutterForegroundTask.init( androidNotificationOptions: AndroidNotificationOptions( channelId: 'foreground_service', @@ -319,7 +320,7 @@ Future _initService() async { priority: NotificationPriority.LOW, ), iosNotificationOptions: const IOSNotificationOptions( - showNotification: true, + showNotification: false, playSound: false, ), foregroundTaskOptions: ForegroundTaskOptions( @@ -398,6 +399,8 @@ class FirstTaskHandler extends TaskHandler { @override void onRepeatEvent(DateTime timestamp) { + _count++; + if (_count == 10) { FlutterForegroundTask.updateService( foregroundTaskOptions: ForegroundTaskOptions( @@ -417,8 +420,6 @@ class FirstTaskHandler extends TaskHandler { }; FlutterForegroundTask.sendDataToMain(data); } - - _count++; } @override @@ -481,33 +482,26 @@ JSON and serialization >> https://docs.flutter.dev/data-and-backend/serializatio // TaskHandler @override void onStart(DateTime timestamp) { - // TaskHandler -> UI + // TaskHandler -> Main(UI) FlutterForegroundTask.sendDataToMain(Object); } -// Main(UI)::onReceiveTaskData +// Main(UI) void _onReceiveTaskData(Object data) { - if (data is Map) { - final dynamic timestampMillis = data["timestampMillis"]; - if (timestampMillis != null) { - final DateTime timestamp = - DateTime.fromMillisecondsSinceEpoch(timestampMillis, isUtc: true); - print('timestamp: ${timestamp.toString()}'); - } - } + print('onReceiveTaskData: $data'); } ``` ```dart // Main(UI) void _sendDataToTask() { - // UI -> TaskHandler + // Main(UI) -> TaskHandler // // The Map collection can only be sent in json format, such as Map. FlutterForegroundTask.sendDataToTask(Object); } -// TaskHandler::onReceiveData +// TaskHandler @override void onReceiveData(Object data) { print('onReceiveData: $data'); diff --git a/example/lib/main.dart b/example/lib/main.dart index 5f7d983c..1433b8ec 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:io'; -import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; @@ -19,12 +18,28 @@ void startCallback() { } class MyTaskHandler extends TaskHandler { + static const String incrementCountCommand = 'incrementCount'; + int _count = 0; + void _incrementCount() { + _count++; + + // Update notification content. + FlutterForegroundTask.updateService( + notificationTitle: 'Hello MyTaskHandler :)', + notificationText: 'count: $_count', + ); + + // Send data to main isolate. + FlutterForegroundTask.sendDataToMain(_count); + } + // Called when the task is started. @override void onStart(DateTime timestamp) { print('onStart'); + _incrementCount(); } // Called by eventAction in [ForegroundTaskOptions]. @@ -33,12 +48,7 @@ class MyTaskHandler extends TaskHandler { // - repeat(interval) : Call onRepeatEvent at milliseconds interval. @override void onRepeatEvent(DateTime timestamp) { - FlutterForegroundTask.updateService(notificationText: 'count: $_count'); - - // Send data to main isolate. - FlutterForegroundTask.sendDataToMain(_count); - - _count++; + _incrementCount(); } // Called when the task is destroyed. @@ -51,6 +61,9 @@ class MyTaskHandler extends TaskHandler { @override void onReceiveData(Object data) { print('onReceiveData: $data'); + if (data == incrementCountCommand) { + _incrementCount(); + } } // Called when the notification button is pressed. @@ -80,7 +93,7 @@ class MyTaskHandler extends TaskHandler { } class ExampleApp extends StatelessWidget { - const ExampleApp({Key? key}) : super(key: key); + const ExampleApp({super.key}); @override Widget build(BuildContext context) { @@ -94,20 +107,22 @@ class ExampleApp extends StatelessWidget { } class ExamplePage extends StatefulWidget { - const ExamplePage({Key? key}) : super(key: key); + const ExamplePage({super.key}); @override State createState() => _ExamplePageState(); } class _ExamplePageState extends State { + final ValueNotifier _receivedTaskData = ValueNotifier(null); + Future _requestPermissions() async { // Android 13+, you need to allow notification permission to display foreground service notification. // // iOS: If you need notification, ask for permission. - final NotificationPermission notificationPermissionStatus = + final NotificationPermission notificationPermission = await FlutterForegroundTask.checkNotificationPermission(); - if (notificationPermissionStatus != NotificationPermission.granted) { + if (notificationPermission != NotificationPermission.granted) { await FlutterForegroundTask.requestNotificationPermission(); } @@ -146,7 +161,7 @@ class _ExamplePageState extends State { } } - Future _initService() async { + void _initService() { FlutterForegroundTask.init( androidNotificationOptions: AndroidNotificationOptions( channelId: 'foreground_service', @@ -157,7 +172,7 @@ class _ExamplePageState extends State { priority: NotificationPriority.LOW, ), iosNotificationOptions: const IOSNotificationOptions( - showNotification: true, + showNotification: false, playSound: false, ), foregroundTaskOptions: ForegroundTaskOptions( @@ -192,15 +207,12 @@ class _ExamplePageState extends State { } void _onReceiveTaskData(Object data) { - if (data is int) { - print('count: $data'); - } + print('onReceiveTaskData: $data'); + _receivedTaskData.value = data; } - void _sendRandomData() { - final Random random = Random(); - final int data = random.nextInt(100); - FlutterForegroundTask.sendDataToTask(data); + void _incrementCount() { + FlutterForegroundTask.sendDataToTask(MyTaskHandler.incrementCountCommand); } @override @@ -220,6 +232,7 @@ class _ExamplePageState extends State { void dispose() { // Remove a callback to receive data sent from the TaskHandler. FlutterForegroundTask.removeTaskDataCallback(_onReceiveTaskData); + _receivedTaskData.dispose(); super.dispose(); } @@ -242,6 +255,32 @@ class _ExamplePageState extends State { } Widget _buildContentView() { + return Column( + children: [ + Expanded(child: _buildCommunicationText()), + _buildServiceControlButtons(), + ], + ); + } + + Widget _buildCommunicationText() { + return ValueListenableBuilder( + valueListenable: _receivedTaskData, + builder: (context, data, _) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('You received data from TaskHandler:'), + Text('$data', style: Theme.of(context).textTheme.headlineMedium), + ], + ), + ); + }, + ); + } + + Widget _buildServiceControlButtons() { buttonBuilder(String text, {VoidCallback? onPressed}) { return ElevatedButton( onPressed: onPressed, @@ -249,13 +288,14 @@ class _ExamplePageState extends State { ); } - return Center( + return Padding( + padding: const EdgeInsets.all(8.0), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ buttonBuilder('start service', onPressed: _startService), buttonBuilder('stop service', onPressed: _stopService), - buttonBuilder('send random data', onPressed: _sendRandomData), + buttonBuilder('increment count', onPressed: _incrementCount), ], ), );