Skip to content

🐛 [firebase_messaging] getToken() hangs forever on iOS #3778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
emvaized opened this issue Oct 5, 2020 · 4 comments · Fixed by #4012
Closed

🐛 [firebase_messaging] getToken() hangs forever on iOS #3778

emvaized opened this issue Oct 5, 2020 · 4 comments · Fixed by #4012
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. Stale Issue with no recent activity type: bug Something isn't working

Comments

@emvaized
Copy link

emvaized commented Oct 5, 2020

Bug report

Describe the bug
The initialization code on iOS fails to execute.

Steps to reproduce

   print('configuring fcm...');
   _firebaseMessaging.configure();

   print('requesting ios permissions...');
   _firebaseMessaging.requestNotificationPermissions();

   print('getting fcm token...');
   token = await _firebaseMessaging.getToken();

   print('finished getting fcm token');
   print("FirebaseMessaging token: $token");

finished getting fcm token never gets printed in console, not on iOS emulator nor on real device.

Expected behavior

On Android the same code works just fine with no errors.

Additional context

I tried the solution suggested here by restricting access to Firebase Installations API in Google Cloud Console specifically for iOS key, but it seems to not help.


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand
Doctor summary (to see all
details, run flutter doctor
-v):
[✓] Flutter (Channel stable,
    1.22.0, on Mac OS X
    10.15.7 19H2, locale
    ru-UA)
 
[✓] Android toolchain -          develop for Android          devices (Android SDK
    version 30.0.0)
[✓] Xcode - develop for iOS
    and macOS (Xcode 11.7)
[✓] Android Studio (version
    4.0)
[✓] VS Code (version 1.49.2)
[✓] Connected device (1
    available)

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand
firebase_messaging: 7.0.2

@emvaized emvaized added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Oct 5, 2020
@Fasuh
Copy link

Fasuh commented Oct 6, 2020

I have encountered the same issue, restricting the key didn't help.

@Unown-Fashion
Copy link

@Fasuh
Just found the solution, which was - needed to initialise a 'standard Firebase app' on iOS

@TahaTesser
Copy link

hi @emvaized

  1. Please add the following in your pubspec.yaml
  firebase_core: ^0.5.0+1
  firebase_messaging: ^7.0.3
  1. Run this code sample
complete code sample
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

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

Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
  if (message.containsKey('data')) {
    // Handle data message
    final dynamic data = message['data'];
  }

  if (message.containsKey('notification')) {
    // Handle notification message
    final dynamic notification = message['notification'];
  }

  // Or do other work.
}

final Map<String, Item> _items = <String, Item>{};
Item _itemForMessage(Map<String, dynamic> message) {
  final dynamic data = message['data'] ?? message;
  final String itemId = data['id'];
  final Item item = _items.putIfAbsent(itemId, () => Item(itemId: itemId))
    ..status = data['status'];
  return item;
}

class Item {
  Item({this.itemId});
  final String itemId;

  StreamController<Item> _controller = StreamController<Item>.broadcast();
  Stream<Item> get onChanged => _controller.stream;

  String _status;
  String get status => _status;
  set status(String value) {
    _status = value;
    _controller.add(this);
  }

  static final Map<String, Route<void>> routes = <String, Route<void>>{};
  Route<void> get route {
    final String routeName = '/detail/$itemId';
    return routes.putIfAbsent(
      routeName,
      () => MaterialPageRoute<void>(
        settings: RouteSettings(name: routeName),
        builder: (BuildContext context) => DetailPage(itemId),
      ),
    );
  }
}

class DetailPage extends StatefulWidget {
  DetailPage(this.itemId);
  final String itemId;
  @override
  _DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  Item _item;
  StreamSubscription<Item> _subscription;

  @override
  void initState() {
    super.initState();
    _item = _items[widget.itemId];
    _subscription = _item.onChanged.listen((Item item) {
      if (!mounted) {
        _subscription.cancel();
      } else {
        setState(() {
          _item = item;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Item ${_item.itemId}"),
      ),
      body: Material(
        child: Center(child: Text("Item status: ${_item.status}")),
      ),
    );
  }
}

class PushMessagingExample extends StatefulWidget {
  @override
  _PushMessagingExampleState createState() => _PushMessagingExampleState();
}

class _PushMessagingExampleState extends State<PushMessagingExample> {
  String _homeScreenText = "Waiting for token...";
  bool _topicButtonsDisabled = false;

  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
  final TextEditingController _topicController =
      TextEditingController(text: 'topic');

  Widget _buildDialog(BuildContext context, Item item) {
    return AlertDialog(
      content: Text("Item ${item.itemId} has been updated"),
      actions: <Widget>[
        FlatButton(
          child: const Text('CLOSE'),
          onPressed: () {
            Navigator.pop(context, false);
          },
        ),
        FlatButton(
          child: const Text('SHOW'),
          onPressed: () {
            Navigator.pop(context, true);
          },
        ),
      ],
    );
  }

  void _showItemDialog(Map<String, dynamic> message) {
    showDialog<bool>(
      context: context,
      builder: (_) => _buildDialog(context, _itemForMessage(message)),
    ).then((bool shouldNavigate) {
      if (shouldNavigate == true) {
        _navigateToItemDetail(message);
      }
    });
  }

  void _navigateToItemDetail(Map<String, dynamic> message) {
    final Item item = _itemForMessage(message);
    // Clear away dialogs
    Navigator.popUntil(context, (Route<dynamic> route) => route is PageRoute);
    if (!item.route.isCurrent) {
      Navigator.push(context, item.route);
    }
  }

  @override
  void initState() {
    super.initState();
    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        _showItemDialog(message);
      },
      onBackgroundMessage: myBackgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
        _navigateToItemDetail(message);
      },
      onResume: (Map<String, dynamic> message) async {
        print("onResume: $message");
        _navigateToItemDetail(message);
      },
    );
    _firebaseMessaging.requestNotificationPermissions(
        const IosNotificationSettings(
            sound: true, badge: true, alert: true, provisional: true));
    _firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered: $settings");
    });
    _firebaseMessaging.getToken().then((String token) {
      assert(token != null);
      setState(() {
        _homeScreenText = "Push Messaging token: $token";
      });
      print(_homeScreenText);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Push Messaging Demo'),
        ),
        // For testing -- simulate a message being received
        floatingActionButton: FloatingActionButton(
          onPressed: () => _showItemDialog(<String, dynamic>{
            "data": <String, String>{
              "id": "2",
              "status": "out of stock",
            },
          }),
          tooltip: 'Simulate Message',
          child: const Icon(Icons.message),
        ),
        body: Material(
          child: Column(
            children: <Widget>[
              Center(
                child: Text(_homeScreenText),
              ),
              Row(children: <Widget>[
                Expanded(
                  child: TextField(
                      controller: _topicController,
                      onChanged: (String v) {
                        setState(() {
                          _topicButtonsDisabled = v.isEmpty;
                        });
                      }),
                ),
                FlatButton(
                  child: const Text("subscribe"),
                  onPressed: _topicButtonsDisabled
                      ? null
                      : () {
                          _firebaseMessaging
                              .subscribeToTopic(_topicController.text);
                          _clearTopicText();
                        },
                ),
                FlatButton(
                  child: const Text("unsubscribe"),
                  onPressed: _topicButtonsDisabled
                      ? null
                      : () {
                          _firebaseMessaging
                              .unsubscribeFromTopic(_topicController.text);
                          _clearTopicText();
                        },
                ),
              ])
            ],
          ),
        ));
  }

  void _clearTopicText() {
    setState(() {
      _topicController.text = "";
      _topicButtonsDisabled = true;
    });
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  FirebaseApp app = await Firebase.initializeApp();
  assert(app != null);
  runApp(
    MaterialApp(
      home: PushMessagingExample(),
    ),
  );
}

App runs fine on physical or simulator

@TahaTesser TahaTesser added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Oct 20, 2020
@google-oss-bot google-oss-bot added the Stale Issue with no recent activity label Oct 29, 2020
@google-oss-bot
Copy link

Hey @emvaized. We need more information to resolve this issue but there hasn't been an update in 7 weekdays. I'm marking the issue as stale and if there are no new updates in the next 7 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@firebase firebase locked and limited conversation to collaborators Dec 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. Stale Issue with no recent activity type: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants