仅当应用程序打开时才会出现通知:Flutter

问题描述 投票:0回答:1

问题很详细

我使用 Awesome_notifications 包。 通知有时会很好地发挥作用,但有时它们仅在应用程序打开时才起作用。 Awesome_notifications 包说这是由于设备的省电模式造成的。
参见图片:[1]:https://i.sstatic.net/4ajWVQ9L.jpg

注意:我根据用户指定的时间安排通知
2:如何使用
背景_获取

太棒了_通知

//代码

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:device_preview/device_preview.dart';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:showcaseview/showcaseview.dart';
import 'package:upgrader/upgrader.dart';
import 'package:background_fetch/background_fetch.dart';

// [Android-only] This "Headless Task" is run when the Android app is terminated with `enableHeadless: true`
// Be sure to annotate your callback function to avoid issues in release mode on Flutter >= 3.3.0
@pragma('vm:entry-point')
void backgroundFetchHeadlessTask(HeadlessTask task) async {
  String taskId = task.taskId;
  bool isTimeout = task.timeout;
  if (isTimeout) {
    // This task has exceeded its allowed running-time.
    // You must stop what you're doing and immediately .finish(taskId)
    print("[BackgroundFetch] Headless task timed-out: $taskId");
    BackgroundFetch.finish(taskId);
    return;
  }
  print('[BackgroundFetch] Headless event received.');
  // Do your work here...
  //Notification
  notfi();
  BackgroundFetch.finish(taskId);
}

TimeOfDay _timeOfDay =  const TimeOfDay(hour:5, minute: 0);



void main()async{
  WidgetsFlutterBinding.ensureInitialized();

  await Permission.notification.isDenied.then(
          (value) {

        if (value) {
          Permission.notification.request();
        }

      }
  );


  AwesomeNotifications().initialize(
    null,
    [
      NotificationChannel(

        channelKey: 'basic_keyadh',
        channelName: 'chnneladhs',
        channelDescription: 'fghjks',
        importance: NotificationImportance.Max,
        //channelShowBadge:true,
        defaultRingtoneType: DefaultRingtoneType.Notification,
        onlyAlertOnce: true,


      ),


    ],

    channelGroups: [
      NotificationChannelGroup(

          channelGroupName: 'Basic group',
          channelGroupKey: 'basic_channel_group'

      ),
    ],
    debug: true,
  );
 // await NotificationService.initializeNotifications();
  

  runApp(DevicePreview(enabled: true,builder: (context) =>  const MyApp23 (),


  ),
  );

BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);

}
class MyApp23 extends StatefulWidget {
  const MyApp23({super.key});

  @override
  State<MyApp23> createState() => _MyApp23State();


}

class _MyApp23State extends State<MyApp23> with WidgetsBindingObserver {




// Be sure to annotate your callback function to avoid issues in release mode on Flutter >= 3.3.0

  @override
  void initState() {
    super.initState();
    initPlatformState();


  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    // Configure BackgroundFetch.
    int status = await BackgroundFetch.configure(BackgroundFetchConfig(
        minimumFetchInterval: 15,
        stopOnTerminate: false,
        enableHeadless: true,
        requiresBatteryNotLow: false,
        requiresCharging: false,
        requiresStorageNotLow: false,
        requiresDeviceIdle: false,
        requiredNetworkType: NetworkType.NONE
    ), (String taskId) async {  // <-- Event handler
      // This is the fetch-event callback.
      print("[BackgroundFetch] Event received $taskId");
      setState(() {

      });
      // IMPORTANT:  You must signal completion of your task or the OS can punish your app
      // for taking too long in the background.
      BackgroundFetch.finish(taskId);
    }, (String taskId) async {  // <-- Task timeout handler.
      // This task has exceeded its allowed running-time.  You must stop what you're doing and immediately .finish(taskId)
      print("[BackgroundFetch] TASK TIMEOUT taskId: $taskId");
      BackgroundFetch.finish(taskId);
    });
    print('[BackgroundFetch] configure success: $status');
    setState(() {

    });

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
  }

  @override
  void dispose(){

    WidgetsBinding.instance.removeObserver(this);
    super.dispose();


  }


  @override
  Widget build(BuildContext context) {


    //Set the fit size (Find your UI design, look at the dimensions of the device screen and fill it in,unit in dp)
    return ScreenUtilInit(
      //designSize: const Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,

      // Use builder only if you need to use library outside ScreenUtilInit context
      builder: (_ , child) {
        return ShowCaseWidget(
          builder : (context) =>  MaterialApp(
            debugShowCheckedModeBanner: false,
            //title: 'First Method',
            // You can use the library anywhere in the app even in theme
            theme: ThemeData(
              primarySwatch: Colors.blue,
              textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp),
            ),
            home: UpgradeAlert(
                dialogStyle: UpgradeDialogStyle.cupertino,
                upgrader: Upgrader(
                  //  minAppVersion:"1.0.0",
                  debugLogging:true,
                  debugDisplayAlways:true,
                  languageCode:'ar',
                  messages: UpgraderMessages(
                    code: 'ar',
                  ),
                  // durationUntilAlertAgain: const Duration(days: 1),
                ),
                child: child),
          ),
        );
      },
      child:  const Demo(),
    );
  }

}


///Stings
class Demo extends StatefulWidget{
  const Demo({super.key});

  @override
  State<Demo> createState() => _DemoState();
}

class _DemoState extends State<Demo> with SingleTickerProviderStateMixin {

  @override
  void initState() {
    super.initState();

    getSavedData();
  }

  getSavedData() async {
    final pref = await SharedPreferences.getInstance();


    //appData.MyColor = Color(pref.getInt('MyColor')??Colors.white.value);
    //appData.col1= pref.getBool('col1') ??appData.col1;
    //appData.col2= pref.getBool('col2') ??appData.col2;
    // get the saved value from stored prefs
    // and make sure to do it inside `setState`
    // cannot use DateTime.parse because _timeOfDaybgm.toString() doesn't return a value
    // DateTime.parse can understand
    setState(() {
      int  ssavedHour = pref.getInt('_timeOfDay') ?? _timeOfDay.hour;
      int  ssavedMinute = pref.getInt('_timeOfDay2') ??_timeOfDay.minute;
      _timeOfDay = TimeOfDay(hour: ssavedHour, minute: ssavedMinute);

      //////////////////////////////////////////////////////////////////////////////////



    });
  }


  @override
  void dispose(){


    super.dispose();


  }



  @override
  Widget build(BuildContext context) {

   // notfi();


    return Scaffold(

      appBar: AppBar(


        automaticallyImplyLeading: false,

        centerTitle:true,

        backgroundColor:const Color.fromARGB(255, 241, 204, 100),
        scrolledUnderElevation: 0.0,
        title:const Text(

          "Demo",
          style: TextStyle(


            color:Colors.white,
            fontWeight: FontWeight.bold,
          )
          ,),

      ) ,
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        //mainAxisAlignment: MainAxisAlignment.center,
        children: [

          Center(
            child: TextButton(onPressed: () async {
              


              final TimeOfDay?timeOfDay = await showTimePicker(


                  context: context,
                  initialEntryMode: TimePickerEntryMode.dialOnly,

                  initialTime:_timeOfDay,

                  builder: (BuildContext context, Widget? child){

                    return Theme(
                      data: Theme.of(context).copyWith(

                          textTheme:   const TextTheme(
                            // ignore: deprecated_member_use
                            button:  TextStyle(

                              //fontSize:  BoodyTextSize(),

                            ),
                            // ignore: deprecated_member_use
                            subtitle1: TextStyle(


                            ),

                            // ignore: deprecated_member_use
                            bodyText2: TextStyle(

                              //fontSize: Titlesize(),
                              color:Color.fromARGB(255, 239, 158, 52),
                            ),

                          ),
                          colorScheme: const ColorScheme.light(
                            onBackground:Color.fromARGB(255, 253, 199, 126),
                            tertiaryContainer: Color.fromARGB(255, 253, 199, 126),
                            primary:Color.fromARGB(255, 253, 199, 126),
                          )),
                      child: child!,
                    ) ;
                  }

              );
              if (timeOfDay!= null) {
                setState(() {
                  _timeOfDay=timeOfDay;

                });
                // ignore: use_build_context_synchronously
                FocusScope.of(context).unfocus();
                final prefs = await SharedPreferences.getInstance();
                // changed setString to setInt, just makes it easier
                await prefs.setInt('_timeOfDay', _timeOfDay.hour);
                await prefs.setInt('_timeOfDay2', _timeOfDay.minute);
              }




            }, child: const Text("Schedule",style: TextStyle(color: Colors.red),)),
          )

        ],
      ) ,
    );
  }
}

//Notification
notfi() {

  AwesomeNotifications().createNotification(
    schedule:NotificationCalendar(
      //  allowWhileIdle:true,
      //  preciseAlarm: true,
      hour: _timeOfDay.hour,
      minute: _timeOfDay.minute,
      second: 0,
      repeats: true,

    ),
    /*  actionButtons: <NotificationActionButton>[
        NotificationActionButton(

          key: 'accept',
          label: 'قراه',
          color: const Color.fromARGB(183, 79, 34, 240),
        ),
        NotificationActionButton(
          key: 'reject',
          label: 'اغلاق ',
          color: const Color.fromARGB(183, 79, 34, 240),
        ),
      ],*/
    content: NotificationContent(

     // icon: 'resource://mipmap/shado',
      id:2,
      channelKey: 'basic_keyadh',
      title: 'He works',
      // body: '',


    ),
  );

}

我想使用background_fetch包,但问题是我不知道获取通知的方法和代码放在哪里。是后台调用函数里面吗?!
感谢所有帮助过我的人。

flutter firebase notifications android-notifications awesome-notifications
1个回答
0
投票

您自己使这个实现变得复杂,使用:Awesome_notificationAwesome_notification_fcm

并在main.dart中初始化:

await Notify.initializeNotification();
await Notify.initializeRemoteNotifications();

创建通知:

class Notify {
  static Future initializeNotification() async {
    AwesomeNotifications().requestPermissionToSendNotifications();
    AwesomeNotifications().initialize(
      null,
      [
        /// create channels
      ]
  }

  static Future<bool> instantNotify(String title) async {
    final AwesomeNotifications awesomeNotifications = AwesomeNotifications();
    return await awesomeNotifications.createNotification(
      content: NotificationContent(
        id: Random().nextInt(100),
        title: title,
        body: "Notification that delivers instantly on trigger.",
        channelKey: 'channel_key',
      ),
    );
  }

  static Future<bool> scheduleNotification() async {
    final AwesomeNotifications awesomeNotifications = AwesomeNotifications();
    return await awesomeNotifications.createNotification(
      schedule: NotificationInterval(interval: 10),
      content: NotificationContent(
        id: Random().nextInt(100),
        title: "Scheduled Notification",
        body: "So this notification will get triggered when it's 9 pm on my device and the date is December 9, 2021.",
        channelKey: 'channel_key_different',
        wakeUpScreen: true,
        autoDismissible: false,
        category: NotificationCategory.Reminder,
      ),
    );
  }

  static Future<void> retrieveScheduledNotifications() async {
    final AwesomeNotifications awesomeNotifications = AwesomeNotifications();
    List<NotificationModel> scheduledNotifications = await awesomeNotifications.listScheduledNotifications();
    print(scheduledNotifications);
  }

  ///  *********************************************
  ///     INITIALIZATION METHODS
  ///  *********************************************

  static Future<void> initializeRemoteNotifications() async {
    await Firebase.initializeApp();
    await AwesomeNotificationsFcm().initialize(
      onFcmSilentDataHandle: mySilentDataHandle,
      onFcmTokenHandle: myFcmTokenHandle,
      onNativeTokenHandle: myNativeTokenHandle,
      // This license key is necessary only to remove the watermark for
      // push notifications in release mode. To know more about it, please
      // visit http://awesome-notifications.carda.me#prices
      // licenseKeys: null,
      debug: true,
    );
  }

  ///  *********************************************
  ///     REMOTE NOTIFICATION EVENTS
  ///  *********************************************

  /// Use this method to execute on background when a silent data arrives
  /// (even while terminated)
  @pragma("vm:entry-point")
  static Future<void> mySilentDataHandle(FcmSilentData silentData) async {
    print('"SilentData": ${silentData.toString()}');

    if (silentData.createdLifeCycle != NotificationLifeCycle.Foreground) {
      print("bg");
    } else {
      print("FOREGROUND");
    }

    print("starting long task");
    await Future.delayed(const Duration(seconds: 4));
    final url = Uri.parse("http://google.com");
    final re = await http.get(url);
    print(re.body);
    print("long task done");
  }

  /// Use this method to detect when a new fcm token is received
  @pragma("vm:entry-point")
  static Future<void> myFcmTokenHandle(String token) async {
    debugPrint('FCM Token:"$token"');
  }

  /// Use this method to detect when a new native token is received
  @pragma("vm:entry-point")
  static Future<void> myNativeTokenHandle(String token) async {
    debugPrint('Native Token:"$token"');
  }

  // Request FCM token to Firebase
  Future<String> getFirebaseMessagingToken() async {
    showInAppMessage();
    String firebaseAppToken = '';
    if (await AwesomeNotificationsFcm().isFirebaseAvailable) {
      try {
        firebaseAppToken = await AwesomeNotificationsFcm().requestFirebaseAppToken();
        print(firebaseAppToken);
      } catch (exception) {
        debugPrint('$exception');
      }
    } else {
      debugPrint('Firebase is not available on this project');
    }
    return firebaseAppToken;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.