PoorMillionaire
PoorMillionaire

Reputation: 377

Flutter: Can't use any plugin in onBackgroundMessage

I am using Firebase Push Notifications and I want to execute some of my code when onBackgroundMessage is triggered. It actually gets triggered because I print in console, but I tried to use several plugins and no luck. I get error every time something like (Unhandled Exception: MissingPluginException(No implementation found for method play on channel flutter_ringtone_player)). I believe this is because there is no context of application in background state of application, but what is this function good for then and what can I actually do in it?

I would like to play sound when onBackgroundMessage is triggered.

    super.initState();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
      },
      onBackgroundMessage: myBackgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
      },
    );

static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {        
  FlutterRingtonePlayer.play(
    android: AndroidSounds.notification,
    ios: IosSounds.glass,
    looping: true, // Android only - API >= 28
    volume: 0.8, // Android only - API >= 28
    asAlarm: true, // Android only - all APIs
  );

    print("background message executed");

  return null;
}

Upvotes: 11

Views: 13784

Answers (3)

Fahima Mokhtari
Fahima Mokhtari

Reputation: 2062

To avoid such issues, I suggest remaining uptodate with the latest version of firebase_messaging on flutter (flutter version >= 1.12). As stated in the official doc:

If you are using Flutter Android Embedding V2 (Flutter Version >= 1.12) then no additional integration steps are required for Android.

In order to proceed using firebase in this case, follow the following steps:

  1. In your pubspec.yaml file, add these two dependencies:

    firebase_core: ^0.7.0
    firebase_messaging: ^8.0.0-dev.15  
    
  2. Run flutter pub get

Code samples:

Before using any firebase service, you need to use await Firebase.initializeApp(); as stated here

Code sample to receive Firebase Push when the app is in the foreground:

FirebaseMessaging _messaging;
await Firebase.initializeApp();
  _messaging = FirebaseMessaging.instance;
   //App is in the foreground

  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    print('Got a message, app is in the foreground!');
    print('Message data: ${message.data}');

    if (message.notification != null) {
      print('Message also contained a notification: ${message.notification}');
    }
  });

Code Sample App is in the background/Termintated:

You need to define a top-level function (a function that is outside the class). The latter will be called when a message occurs and the app is in the background: According to the doc, it should be as following:

Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage message,
) async {
   await Firebase.initializeApp();
   print('onBackgroundMessage received: $message');
  
 }

Then, the above mentioned will be used here:

 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

Upvotes: 3

PoorMillionaire
PoorMillionaire

Reputation: 377

Here is a working code. When device receive push notification (Firebase), onBackgroundMessage is executed and custom sound is played even if the app is closed.

main.dart

static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async {        
    final assetsAudioPlayer = AssetsAudioPlayer();

    assetsAudioPlayer.open(
        Audio("assets/audio/alarm.mp3"),
    );

    print("sound played");

    return null;
  }

  void initState() {
    super.initState();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
      },
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
      },
      onBackgroundMessage: myBackgroundMessageHandler
    );
  }

Application.kt

import com.github.florent37.assetsaudioplayer.AssetsAudioPlayerPlugin

class Application : FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }   

    override fun registerWith(registry: PluginRegistry) {
        AssetsAudioPlayerPlugin.registerWith(registry?.registrarFor("com.github.florent37.assetsaudioplayer"))

        FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
    }
}

Upvotes: 4

Mark
Mark

Reputation: 1170

Try registering the plugins that you need to use in myBackgroundMessageHandler in your Android's Application class. Here is an example of my Application.kt:

class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
    super.onCreate()
    FlutterFirebaseMessagingService.setPluginRegistrant(this)
}

override fun registerWith(registry: PluginRegistry?) {
    PathProviderPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"))
    FlutterLocalNotificationsPlugin.registerWith(registry?.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"))
    FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
}
}

Upvotes: 4

Related Questions