rafaelsetragni / awesome_notifications

A complete solution to create Local Notifications and Push Notifications, throught Firebase or another services, using Flutter.
https://discord.awesome-notifications.carda.me
Apache License 2.0
752 stars 326 forks source link

MissingPluginException(No implementation found for method createNewNotification on channel awesome_notifications) #18

Closed thesmalleyes closed 3 years ago

thesmalleyes commented 3 years ago

Hi, I followed your instruction about how to use this package. So, I added initialize channel in my main.dart Then I call create notification from the app, it's work But, when i call it from background, push notification, i got the error mesage

Unable to handle incoming background message.
I/flutter (20190): MissingPluginException(No implementation found for method createNewNotification on channel awesome_notifications)

What's wrong?

rafaelsetragni commented 3 years ago

How are you calling it from background? Paste here a code example

thesmalleyes commented 3 years ago

So I have my backgroundMessageHandler in main.dart I have created channel basic_test in main.dart before runApp.

Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {
  if (message.containsKey('data')) {
    // Handle data message
    final dynamic data = message['data'];
    String title = data['nt']??data['title'];
    String body = data['nm']??data['body'];
    String imageUrl = data['wzrk_bp']??'';
    return title.isEmpty? null : showNotification(title, body, imageUrl);
  }
}

When onBackground triggered, i show notification by call showNotification() method above. show_notifications.dart

class ShowNotifications{
//other method
showNotification(String title, String body, String image)async{
  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: id,
          channelKey: 'basic_test',
          title: title',
          bigPicture:
              'https://i0.wp.com/www.jornadageek.com.br/wp-content/uploads/2018/06/Looney-tunes.png?resize=696%2C398&ssl=1',
          notificationLayout: NotificationLayout.BigPicture,
          payload: {'uuid': 'uuid-test'}));
}
}

Whenever I called showNotification from any screen, the notif is show. But, when onbackground notification triggered, the error happened.

Unable to handle incoming background message.
I/flutter (20190): MissingPluginException(No implementation found for method createNewNotification on channel awesome_notifications)
rafaelsetragni commented 3 years ago

It seems like the plugin is not beeing initialized by Flutter on your background fetch. So there is no native handle registred to receive your background call.

Can you share with me your project on github to me reproduce this error?

Edit: Are you using background_fetch plugin?

thesmalleyes commented 3 years ago

I created a mini example of how I used the package in https://github.com/bayuramadeza/Awesome-Notification-FCM, I think this package should have something like : FirebaseMessagingPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin")) to add in Application.kt to handle this error.

Nope, I didn't use background_fetch

rafaelsetragni commented 3 years ago

Im fixing your source.

First, you SHOULD NOT USE firebase messaging classes on your project directly. You should strictly follow the steps to How to show Local Notifications and, to use firebase messaging which is optional, you should follow the steps to Using Firebase Services (Optional).

Do not do anything else than what is indicate on the documentation. All the firebase class to send FCM was already implemented, managed and installed inside the Awesome Notifications plugin. You dont need to do anything else.

Also, you must respect the structure specified in How to send Push Notifications using Firebase Cloud Messaging (FCM) and do not send push notifications with "notification" field, only "data".

Edit: Example DONE https://github.com/bayuramadeza/Awesome-Notification-FCM

thesmalleyes commented 3 years ago

Thanks!! It works now. But, I still have some questions.

  1. Can the notification show up like heads-up notification, like image below? Screen Shot 2020-10-27 at 13 56 45
  2. Can the notification handle onMessage notification like FCM? So it doesn't need to show in background, instead it pop in app screen.?
  3. The problem I got is the marketing tools use their own data to handle notification, the notification structure is {"data" ; {"title" : title, "body": body, ....}}, So, i can't customize it like the the structure specified in the package notification structure
rafaelsetragni commented 3 years ago
  1. Sure. You can manipulate the entire notification to show as exactly as this example, changing title, body, showWhen, activating BigPicture layout with largeIcon and, for last, including the two actionButtons "Reply" and "Archive".

And also you can control if your notification will automatically shows on foreground or background, using the variables displayOnForeground and displayOnBackground. Its all up to you.

  1. onMessage event is equivalent to displayedStream stream. You just need to listen this stream, as you do on actionStream. Youll always receive the event on displayedStream, even when your app is terminate. Sometimes the streams could not be delivered on exactly time when they happen, but they will be delivered as soon as possible to your Flutter app.

You can check all those combinations on our Notification Life Cycle and Flutter Streams topics.

Also, i do recommend you to watch this video about Dart Streams:

Dart Streams

rafaelsetragni commented 3 years ago

Can i put your example code on our README documentation? This will allows the others to use this example to learn how to use Awesome Notifications and Firebase Cloud Messaging more easly.

And, of course, I want to include your name as thanks for helping the community. Can i?

thesmalleyes commented 3 years ago

Okay, Thankyou so much for your explanation. I got it, Sure, You can put my example code in your README documentation. I'm pleasure to heard it

jenniestrongbow commented 3 years ago

@rafaelsetragni
Hi you mentioned the displayOnBackground option. I did not see it in the documentation. How do I set it? Thanks

lanad22 commented 3 weeks ago

Hello, I am having the same problem but with background task using Workmanager plug in. I have registered both workmanager and awesome-notifications plugins. This is my AppDelegate.swift

SwiftAwesomeNotificationsPlugin.setPluginRegistrantCallback { registry in
              SwiftAwesomeNotificationsPlugin.register(
                with: registry.registrar(forPlugin: "AwesomeNotificationsPlugin")!)
              SharedPreferencesPlugin.register( // replace here
                                with: registry.registrar(forPlugin: "io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")!)
          }

    // Register background tasks only if not already registered
    if !AppDelegate.hasRegisteredBackgroundTask {
        WorkmanagerPlugin.registerBGProcessingTask(withIdentifier: "iOSBackgroundProcessing")

        // Register a periodic task in iOS 13+
        WorkmanagerPlugin.registerPeriodicTask(
            withIdentifier: "locationTracking",
            frequency: NSNumber(value: 15 * 60)
        )

        AppDelegate.hasRegisteredBackgroundTask = true
    }

I have also add the necessary codes in my pod file. Workmanager is working because when I use 'Simulate Background Fetch' to manually perform background fetch from Xcode, I got the notification that Background perform fetch is successful but I did not receive the notification I created in the callbackdispatcher function - I got the missing plugins error instead. This is how I am doing in in main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  AwesomeNotifications().initialize(
    // set the icon to null if you want to use the default app icon
      null,
      [
        NotificationChannel(
            channelGroupKey: 'basic_channel_group',
            channelKey: 'basic_channel',
            channelName: 'Basic notifications',
            channelDescription: 'Notification channel for basic tests',
            defaultColor: Color(0xFF9D50DD),
            ledColor: Colors.white)
      ],
      // Channel groups are only visual and are not required
      channelGroups: [
        NotificationChannelGroup(
            channelGroupKey: 'basic_channel_group',
            channelGroupName: 'Basic group')
      ],
      debug: true
  );

  // Only after at least the action method is set, the notification events are delivered
  AwesomeNotifications().setListeners(
      onActionReceivedMethod:         NotificationController.onActionReceivedMethod,
      onNotificationCreatedMethod:    NotificationController.onNotificationCreatedMethod,
      onNotificationDisplayedMethod:  NotificationController.onNotificationDisplayedMethod,
      onDismissActionReceivedMethod:  NotificationController.onDismissActionReceivedMethod
  );
  await Workmanager().cancelAll();
  await initializeWorkManager();
  Workmanager().registerPeriodicTask(
    "locationTracking", // Unique identifier for the task
    locationTracking,
    frequency: Duration(minutes: 15), // Task name
  );
  Workmanager().printScheduledTasks();
  runApp(const MyApp());
}

Future<void> initializeWorkManager() async {
  await Workmanager().initialize(
    callbackDispatcher,
    isInDebugMode: true,
  );
  print("WorkManager initialization complete.");
}

@pragma('vm:entry-point')
void callbackDispatcher() {
  print("Workmanager task started.");
  Workmanager().executeTask((task, inputData) {
    switch(task){
      case locationTracking:
        print("Task excecuted: $task");
        AwesomeNotifications().createNotification(
          content: NotificationContent(
            id: 10,
            channelKey: 'basic_channel',
            title: "Hello from WorkManager!",
            body: "This is a simple notification triggered by the WorkManager task.",
          ),
        );
        print("Notification sent.");
    }
    return Future.value(true);
  });
}

I have been at this for days. I am not sure what I am missing or doing wrong... Any help and suggestion is appreciated. Thank you!