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

Viewed 9216

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,
      ),
    ));
  }
}
6 Answers

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
}

Make sure you have these settings in your android/build.gradle

buildscript {

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
  }

  dependencies {
    // ...

    // Add the following line:
    classpath 'com.google.gms:google-services:4.3.13'  // Google Services plugin
  }
}

allprojects {
  // ...

  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
    // ...
  }
}

And then in your android/app/build.gradle:

apply plugin: 'com.android.application'
// Add the following line:
apply plugin: 'com.google.gms.google-services'  // Google Services plugin

android {
  // ...
}

You can follow the steps here

And don't forget to download google-service.json from firebase project console, and put it into android/app folder.

Sometimes FlutterFire cli is not able to update build.gradle files so you get the above error

in project level build.gradle add the firebase dependencies as

   dependencies {
    classpath 'com.android.tools.build:gradle:7.1.2'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath 'com.google.gms:google-services:4.3.10'
    classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
}

in app level build.gradle file apply firebase plugins as

    apply plugin: 'com.google.gms.google-services'
    apply plugin: 'com.google.firebase.crashlytics'

Attention. Manually changing build.gradle files as described above is not a solution. It will either won't work or every build will generate lots of warnings as using deprecated dependencies. Correct solution is this: Firabase should be intialiezed like below:

await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);

For this, you will need to run some commands from command line / terminal:

// Add firebase core into your project
flutter pub add firebase_core
// Generate firebase options file
flutterfire configure
// Import firebase core and generated file
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

For details you can refer here.

The accepted answer still definitely works, but it requires manual operations plus the uncertainty of which Google Services version and Firebase BOM to add.

I recommend using the FlutterFire CLI to configure the project and to automatically set up all these build.gradle dependencies.

Official configuration setup can be found here.

If you are configuring flutter in ios make sure to initilize this in swift file FirebaseApp.configure()

import FirebaseCore //import this on top

Related