Search code examples
node.jsflutterfirebasefirebase-cloud-messaging

FirebaseCloudMessaging : PlatformException (PlatformException(null-error, Host platform returned null value for non-null return value., null, null))


I'm trying to send notifications from an Node.js API to a Flutter application. First, I want to make my application able to receive notifications from Firebase.

But, when I initializeApp, I got an issue :

PlatformException (PlatformException(null-error, Host platform returned null value for non-null return value., null, null))

and this, in the console:

E/flutter (25357): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: PlatformException(null-error, Host platform returned null value for non-null return value., null, null)
E/flutter (25357): #0      FirebaseCoreHostApi.optionsFromResource (package:firebase_core_platform_interface/src/pigeon/messages.pigeon.dart:250)
package:firebase_core_platform_interface/…/pigeon/messages.pigeon.dart:1
E/flutter (25357): <asynchronous suspension>
E/flutter (25357): #1      MethodChannelFirebase.initializeApp (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:89)
package:firebase_core_platform_interface/…/method_channel/method_channel_firebase.dart:1
E/flutter (25357): <asynchronous suspension>
E/flutter (25357): #2      Firebase.initializeApp (package:firebase_core/src/firebase.dart:40)
package:firebase_core/src/firebase.dart:1
E/flutter (25357): <asynchronous suspension>
E/flutter (25357): #3      main (package:notifappfcm/main.dart:13)
package:notifappfcm/main.dart:1

I've been looking for a solution to this problem, but I really can't find it.

This is my application code:

main.dart

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'mainscreen.dart';

Future<void> _firebadeMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp(); // options: DefaultFirebaseConfig.platformOptions
  print('Handling a background message ${message.messageId}');
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  FirebaseMessaging.onBackgroundMessage(_firebadeMessagingBackgroundHandler);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MainScreen(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

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

  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

mainscreen.dart

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class MainScreen extends StatefulWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  late AndroidNotificationChannel channel;
  late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

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

    requestPermission();
    loadFCM();
    listenFCM();
    // Get device's notification token
    getToken();
  }


  void getToken() async {
    await FirebaseMessaging.instance.getToken().then((token) => print(token));
  }

  void requestPermission() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    NotificationSettings settings = await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      print('User granted permission');
    } else if (settings.authorizationStatus ==
        AuthorizationStatus.provisional) {
      print('User granted provisional permission');
    } else {
      print('User declined or has not accepted permission');
    }
  }

  void listenFCM() async {
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      RemoteNotification? notification = message.notification;
      AndroidNotification? android = message.notification?.android;
      if (notification != null && android != null && !kIsWeb) {
        flutterLocalNotificationsPlugin.show(
            notification.hashCode,
            notification.title,
            notification.body,
            NotificationDetails(
                android: AndroidNotificationDetails(channel.id, channel.name,
                    // ignore: todo
                    // TODO add a proper drawable resource to android (now using one that already exists)
                    icon: 'launch_background')));
      }
    });
  }

  void loadFCM() async {
    if (!kIsWeb) {
      channel = const AndroidNotificationChannel(
        'high_importance_channel', // id
        'High Importance Notifications', // title
        importance: Importance.high,
        enableVibration: true,
      );

      flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

      /// Create an Android Notification Channel.
      ///
      /// We use this channel in the `AndroidManifest.xml` file to override the
      /// default FCM channel to enable heads up notifications.
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);

      /// Update the iOS foreground notification presentation options to allow
      /// heads up notifications.
      await FirebaseMessaging.instance
          .setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Container(
        height: 40,
        width: 200,
        color: Colors.red,
      ),
    ));
  }
}

Solution

  • Make sure you have added the Firebase SDK dependencies in the Project Level build.gradle file and Application Level build.gradle file

    Dependencies to be added in Project Level build.gradle:

    buildscript {
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
      }
      dependencies {
        ...
        // Add this line
        classpath 'com.google.gms:google-services:4.3.13'
      }
    }
    
    allprojects {
      ...
      repositories {
        // Check that you have the following line (if not, add it):
        google()  // Google's Maven repository
        ...
      }
    }
    

    Dependencies to be added in App Level build.gradle:

    apply plugin: 'com.android.application'
    // Add this line
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
      // Import the Firebase BoM
      implementation platform('com.google.firebase:firebase-bom:30.2.0')
    
      // Add the dependency for the Firebase SDK for Google Analytics
      // When using the BoM, don't specify versions in Firebase dependencies
      implementation 'com.google.firebase:firebase-analytics'
    
      // Add the dependencies for any other desired Firebase products
      // https://firebase.google.com/docs/android/setup#available-libraries
    }