Flutterfire: [firebase_messaging] Background Handler `throws java.lang.Integer cannot be cast to java.lang.Long`

Created on 18 Sep 2019  路  3Comments  路  Source: FirebaseExtended/flutterfire

Describe the bug
When running the application on start the following error is printed to console:

E/FirebaseMessagingPlugin( 6358): There was an exception when getting callback handle from Dart side
W/System.err( 6358): java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
W/System.err( 6358):    at io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.onMethodCall(FirebaseMessagingPlugin.java:126)
W/System.err( 6358):    at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:222)
W/System.err( 6358):    at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:96)
W/System.err( 6358):    at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:656)
W/System.err( 6358):    at android.os.MessageQueue.nativePollOnce(Native Method)
W/System.err( 6358):    at android.os.MessageQueue.next(MessageQueue.java:326)
W/System.err( 6358):    at android.os.Looper.loop(Looper.java:160)
W/System.err( 6358):    at android.app.ActivityThread.main(ActivityThread.java:6669)
W/System.err( 6358):    at java.lang.reflect.Method.invoke(Native Method)
W/System.err( 6358):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
W/System.err( 6358):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Tracing to the source it appears to be this line (126) in FirebaseMessagingPlugin.java:

      try {
        Map<String, Long> callbacks = ((Map<String, Long>) call.arguments);
        setupCallbackHandle = callbacks.get("setupHandle");
        backgroundMessageHandle = callbacks.get("backgroundHandle");
      } catch (Exception e) {
        Log.e(TAG, "There was an exception when getting callback handle from Dart side");
        e.printStackTrace();
      }

Possibly related? (I don't know, I'm really not a in my element here in Java...)

To Reproduce
Steps to reproduce the behavior:

  1. Add FCM to Flutter App.
  2. Register the plugin:

home.dart (included in full just in case)

import "package:cloud_firestore/cloud_firestore.dart";
import "package:firebase_messaging/firebase_messaging.dart";
import "package:flutter/material.dart";
import "package:flutter_hybrid_alert/src/api/firestore.dart";
import "package:flutter_hybrid_alert/src/api/handlers.dart";
import "package:flutter_hybrid_alert/src/api/storage.dart";
import "package:flutter_hybrid_alert/src/models/models.dart";
import "package:flutter_hybrid_alert/src/routes.dart";
import "package:flutter_hybrid_alert/src/store/actions/user_actions.dart";
import "package:flutter_hybrid_alert/src/store/app_state.dart";
import "package:flutter_hybrid_alert/src/store/reducers/auth_reducer.dart";
import "package:flutter_hybrid_alert/src/ui/login.dart";
import "package:flutter_hybrid_alert/src/widgets/indicators/app_loading.dart";
import "package:flutter_local_notifications/flutter_local_notifications.dart";
import "package:flutter_redux/flutter_redux.dart";
import "package:nested_navigators/nested_nav_item.dart";
import "package:nested_navigators/nested_navigators.dart";
import "package:redux/redux.dart";

enum NestedNavItemKey { blacklist, recent, history, settings }

/// showNotification - Init local notifications and show a new one.
void showNotification(String body) {
  final androidInitSettings = AndroidInitializationSettings("@mipmap/ic_launcher");
  final initSettings = InitializationSettings(androidInitSettings, null);
  final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  flutterLocalNotificationsPlugin.initialize(initSettings);

  const String notificationChannel = "HybridAlert";
  final androidPlatformChannelSpecifics = AndroidNotificationDetails(
    notificationChannel,
    notificationChannel,
    "Alerts for Hybrid platform.",
    importance: Importance.Max,
    priority: Priority.High,
    ticker: "ticker",
  );

  final platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, null);
  flutterLocalNotificationsPlugin.show(0, notificationChannel, body, platformChannelSpecifics);
}

Future<dynamic> handleBackgroundNotifications(Map<String, dynamic> message) {
  if (message.containsKey("data")) {
    // Handle data message
    final dynamic data = message["data"];
    showNotification(data["name"]);
  }
}

/// handleNotifications - Force local notifications.
Future<dynamic> handleNotifications(Map<String, dynamic> message) async {
  showNotification(message["data"]["name"]);
}

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomeState();
  }
}

class _HomeState extends State<Home> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  AppUserSettings settings;
  String userId;
  Store store;

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

    // FCM Setup
    _firebaseMessaging.requestNotificationPermissions();
    _firebaseMessaging.getToken().then(handleSetUserToken);

    _firebaseMessaging.configure(
      onMessage: handleNotifications,
      onBackgroundMessage: handleBackgroundNotifications,
    );

    if (userId == null) {
      getStorageUser().then((String id) {
        store.dispatch(SetUserFBEmailAction(id));
        setState(() {
          userId = id;
        });
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    store = StoreProvider.of<AppState>(context);
    final AppState state = store.state;
    final Stream<DocumentSnapshot> userStream =
        userId != null ? usersRef.document(userId).get().asStream() : null;

    return StreamBuilder(
      stream: userStream,
      builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        if (!snapshot.hasData || state.loading.settings) {
          return buildAppLoadingIndicator("Loading settings...");
        }

        /*       Initialize User Store Data
         ======================================== */

        // Set hybrid email in store from firebase
        final AppUser appUser = AppUser.fromJson(snapshot.data.data);
        final String hybridEmail = appUser.email;
        final String stateHybridEmail = state.user.hybridEmail;
        final bool hybridEmailChanged = hybridEmail != stateHybridEmail;
        if (hybridEmailChanged) {
          store.dispatch(SetUserHybridEmailAction(hybridEmail));
        }

        // Set firebase userId as fbEmail.
        if (state.user.fbEmail == null) {
          store.dispatch(SetUserFBEmailAction(userId));
        }

        //  Build the Settings UI.
        return NestedNavigators(
          items: {
            NestedNavItemKey.recent: NestedNavigatorItem(
              initialRoute: Routes.recent,
              icon: Icons.home,
              text: "Recent",
            ),
            NestedNavItemKey.history: NestedNavigatorItem(
              initialRoute: Routes.history,
              icon: Icons.history,
              text: "History",
            ),
            NestedNavItemKey.blacklist: NestedNavigatorItem(
              initialRoute: Routes.blacklist,
              icon: Icons.list,
              text: "Blacklist",
            ),
            NestedNavItemKey.settings: NestedNavigatorItem(
              initialRoute: Routes.settings,
              icon: Icons.settings,
              text: "Settings",
            ),
          },
          generateRoute: (routeSettings) {
            return Routes.generateRoute(routeSettings, store.state);
          },
          buildBottomNavigationItem: (key, item, selected) => BottomNavigationBarItem(
            icon: Icon(
              item.icon,
//          color: Colors.blue,
            ),
            title: Text(
              item.text,
              style: TextStyle(
                fontSize: 18,
              ),
            ),
          ),
          bottomNavigationBarTheme: Theme.of(context).copyWith(
            splashColor: Colors.grey,
          ),
        );
      },
    );
  }
}

class AppHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, AppState>(
      converter: (store) {
        return store.state;
      },
      builder: (BuildContext context, AppState state) {
        final AuthState authState = state.auth;
        final bool firebaseAuth = authState.firebaseAuthenticated;
        final bool hybridAuth = authState.hybridAuthenticated;
        final bool isLoggedIn = hybridAuth && firebaseAuth;
        if (isLoggedIn) {
          return Home();
        }

        return LoginScreen();
      },
    );
  }
}
  1. See error or incorrect behavior

Expected behavior
Should not throw an error on initialization.

Additional context
I'm really not sure what I can do to get this to not throw an error.

bug

Most helpful comment

I have successfully suppressed the error by naming my background handler literally the same as what is being called in the library code... which seems a little ridiculous given that the documentation named the handler something totally different.

source

      try {
        Map<String, Long> callbacks = ((Map<String, Long>) call.arguments);
        setupCallbackHandle = callbacks.get("setupHandle");

        // THIS RIGHT HERE "backgroundHandle" HAS TO BE THE NAME??
        backgroundMessageHandle = callbacks.get("backgroundHandle");
      } catch (Exception e) {
        Log.e(TAG, "There was an exception when getting callback handle from Dart side");
        e.printStackTrace();
      }

All 3 comments

I have successfully suppressed the error by naming my background handler literally the same as what is being called in the library code... which seems a little ridiculous given that the documentation named the handler something totally different.

source

      try {
        Map<String, Long> callbacks = ((Map<String, Long>) call.arguments);
        setupCallbackHandle = callbacks.get("setupHandle");

        // THIS RIGHT HERE "backgroundHandle" HAS TO BE THE NAME??
        backgroundMessageHandle = callbacks.get("backgroundHandle");
      } catch (Exception e) {
        Log.e(TAG, "There was an exception when getting callback handle from Dart side");
        e.printStackTrace();
      }

I have successfully suppressed the error by naming my background handler literally the same as what is being called in the library code... which seems a little ridiculous given that the documentation named the handler something totally different.

source

      try {
        Map<String, Long> callbacks = ((Map<String, Long>) call.arguments);
        setupCallbackHandle = callbacks.get("setupHandle");

        // THIS RIGHT HERE "backgroundHandle" HAS TO BE THE NAME??
        backgroundMessageHandle = callbacks.get("backgroundHandle");
      } catch (Exception e) {
        Log.e(TAG, "There was an exception when getting callback handle from Dart side");
        e.printStackTrace();
      }

This solved to me, thanks.

Hi @DannyHinshaw
given your last message I feel safe to close this issue,
if you disagree please write in the comments
and I will reopen it.
Thank you

Was this page helpful?
0 / 5 - 0 ratings