Skip to content

🐛 [firebase_messaging] The problem that initState () is called even if the app is terminated #6517

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
jinnyum opened this issue Jul 1, 2021 · 22 comments
Labels
platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working

Comments

@jinnyum
Copy link

jinnyum commented Jul 1, 2021

Bug report

Describe the bug

I quit the app by swiping on iOS,
Why is initstate called when a push is received in this state?

Steps to reproduce

Steps to reproduce the behavior:

  1. Swipe in ios to quit the app.
  2. Even if it is terminated, initstate() is called internally when a push message is received.

Expected behavior

I thought the app would do nothing.

Sample project

Providing a minimal example project which demonstrates the bug in isolation from your main App greatly enhances the chance of a timely fix.
Please link to the public repository URL.


Additional context

I did not see an explanation that initState would be called even though the app was terminated.
Is this a bug?
Or is it normal?

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, 2.2.1, on Microsoft Windows [Version 10.0.19042.1052], locale ko-KR)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] VS Code (version 1.57.1)
[√] Connected device (3 available)

• No issues found!


Flutter dependencies

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

Click To Expand

Dart SDK 2.13.1
Flutter SDK 2.2.1
ordermgn 1.0.0+3

dependencies:

  • battery_optimization 0.1.0 [flutter]
  • cupertino_icons 1.0.2
  • device_info 2.0.0 [flutter device_info_platform_interface]
  • dio 3.0.10 [http_parser path]
  • drag_down_to_pop 0.2.1 [flutter]
  • firebase_core 1.3.0 [firebase_core_platform_interface firebase_core_web flutter meta]
  • firebase_messaging 10.0.2 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
  • flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine]
  • flutter_absolute_path 1.0.6 [flutter]
  • flutter_app_badger 1.2.0 [flutter]
  • flutter_local_notifications 5.0.0+4 [flutter flutter_local_notifications_platform_interface platform timezone]
  • flutter_localizations 0.0.0 [flutter intl characters clock collection meta path typed_data vector_math]
  • flutter_phone_direct_caller 2.0.0 [flutter]
  • flutter_svg 0.22.0 [flutter meta path_drawing vector_math xml]
  • fluttertoast 7.1.8 [flutter flutter_web_plugins]
  • heic_to_jpg 0.2.0 [flutter]
  • hello 0.0.1 [flutter]
  • http 0.12.2 [http_parser path pedantic]
  • jiffy 4.0.0 [intl]
  • multi_image_picker 4.8.00 [flutter meta]
  • path 1.8.0
  • path_provider 2.0.1 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows]
  • photo_view 0.10.3 [flutter]
  • provider 4.3.3 [collection flutter nested]
  • pull_to_refresh 1.6.4 [flutter]
  • rxdart 0.18.1
  • shared_preferences 2.0.4 [meta flutter shared_preferences_platform_interface shared_preferences_linux shared_preferences_macos shared_preferences_web shared_preferences_windows]
  • sqflite 1.3.2+4 [flutter sqflite_common path]

dev dependencies:

  • flutter_launcher_icons 0.9.0 [args image path yaml]
  • flutter_native_splash 1.1.7+1 [image meta path xml yaml]
  • flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data]

transitive dependencies:

  • archive 3.1.2 [crypto path]
  • args 2.0.0
  • async 2.6.1 [meta collection]
  • boolean_selector 2.1.0 [source_span string_scanner]
  • characters 1.1.0
  • charcode 1.2.0
  • clock 1.1.0
  • collection 1.15.0
  • crypto 3.0.1 [collection typed_data]
  • device_info_platform_interface 2.0.1 [flutter meta plugin_platform_interface]
  • fake_async 1.2.0 [clock collection]
  • ffi 1.0.0
  • file 6.1.0 [meta path]
  • firebase_core_platform_interface 4.0.1 [collection flutter meta plugin_platform_interface]
  • firebase_core_web 1.1.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
  • firebase_messaging_platform_interface 3.0.2 [firebase_core flutter meta plugin_platform_interface]
  • firebase_messaging_web 2.0.2 [firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins js meta]
  • flutter_local_notifications_platform_interface 3.0.0 [flutter plugin_platform_interface]
  • flutter_web_plugins 0.0.0 [flutter js characters collection meta typed_data vector_math]
  • http_parser 3.1.4 [charcode collection source_span string_scanner typed_data]
  • image 3.0.2 [archive meta xml]
  • intl 0.17.0 [clock path]
  • js 0.6.3
  • matcher 0.12.10 [stack_trace]
  • meta 1.3.0
  • nested 1.0.0 [flutter]
  • path_drawing 0.5.1 [vector_math meta path_parsing flutter]
  • path_parsing 0.2.1 [vector_math meta]
  • path_provider_linux 2.0.0 [path xdg_directories path_provider_platform_interface flutter]
  • path_provider_macos 2.0.0 [flutter]
  • path_provider_platform_interface 2.0.1 [flutter meta platform plugin_platform_interface]
  • path_provider_windows 2.0.0 [path_provider_platform_interface meta path flutter ffi win32]
  • pedantic 1.11.0
  • petitparser 4.0.2 [meta]
  • platform 3.0.0
  • plugin_platform_interface 2.0.0 [meta]
  • process 4.1.0 [file path platform]
  • shared_preferences_linux 2.0.0 [flutter file meta path path_provider_linux shared_preferences_platform_interface]
  • shared_preferences_macos 2.0.0 [shared_preferences_platform_interface flutter]
  • shared_preferences_platform_interface 2.0.0 [flutter]
  • shared_preferences_web 2.0.0 [shared_preferences_platform_interface flutter flutter_web_plugins meta]
  • shared_preferences_windows 2.0.0 [shared_preferences_platform_interface flutter file meta path path_provider_platform_interface path_provider_windows]
  • sky_engine 0.0.99
  • source_span 1.8.1 [collection path term_glyph]
  • sqflite_common 1.0.3+3 [synchronized path meta]
  • stack_trace 1.10.0 [path]
  • stream_channel 2.1.0 [async]
  • string_scanner 1.1.0 [charcode source_span]
  • synchronized 2.2.0+2
  • term_glyph 1.2.0
  • test_api 0.3.0 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher]
  • timezone 0.7.0 [path]
  • typed_data 1.3.0 [collection]
  • vector_math 2.1.0
  • win32 2.0.0 [ffi]
  • xdg_directories 0.2.0 [meta path process]
  • xml 5.0.2 [collection meta petitparser]
  • yaml 3.1.0 [collection source_span string_scanner]

@jinnyum jinnyum added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Jul 1, 2021
@darshankawar darshankawar added the triage Issue is currently being triaged. label Jul 2, 2021
@darshankawar
Copy link

@jinnyum
According to the iOS documentation, there are some pre-conditions that should be met before the application can receive message payloads via FCM.

When app is terminated using swipe and a push notification is received, you'll need to manually open the app so that the background message to work and act upon received push.
On iOS, if the user swipes away the application from app Switcher, it must be manually reopened again for background messages to start working again.

https://firebase.flutter.dev/docs/messaging/usage/#receiving-messages

Does this info help to answer your question ?

@darshankawar darshankawar added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jul 2, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 2, 2021

My question is that even if the app is closed, the app will be executed internally if the push is received.
Is it normal for the initstate build function to run if the app is completely terminated and the push is received?
I'm not saying that I want to receive the payload.

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 2, 2021
@markusaksli-nc
Copy link
Contributor

Hi @jinnyum
I'm not sure what you mean by initState being called when the app is terminated? initState is a flutter specific widget lifecycle function that only gets called on the UI thread when UI is being actively rendered. Maybe you meant the onBackgroundMessage callback?

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jul 5, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 5, 2021

Hi @jinnyum
I'm not sure what you mean by initState being called when the app is terminated? initState is a flutter specific widget lifecycle function that only gets called on the UI thread when UI is being actively rendered. Maybe you meant the onBackgroundMessage callback?

I'm not talking about onBackgroundMessage .
As you said initstate and build should only be called at render time.
But the problem is that it gets called even when the app is completely closed. ( <- This is the key point.)
I haven't seen any documentation on this.
So my question is whether this is a bug or not.
And, From the second push message on, onBackgroundMessage is called.
In the first push message, I guess the render function was also called while the system internally loads the program once.
Of course I don't know if my predictions are correct or not.
If this is not an error, can you tell the difference between running it on the system and running it by the user?

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 5, 2021
@markusaksli-nc
Copy link
Contributor

Can you provide a minimal complete reproducible code sample?

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jul 6, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 7, 2021

Can you provide a minimal complete reproducible code sample?

Token registration sites must be set to their own.

import 'package:dio/dio.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';

import 'dart:async';
import 'dart:io';
import 'package:device_info/device_info.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:firebase_core/firebase_core.dart';

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
}

AndroidNotificationChannel channel;
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

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

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  channel = AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    'This channel is used for important notifications.', // description
    importance: Importance.max,
    enableLights: true,
  );

  flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  runApp(MessagingExampleApp());
}

class MessagingExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Messaging Example App',
     // theme: ThemeData.dark(),
      routes: {
        '/': (context) => Application(),
      },
    );
  }
}

class Application extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _Application();
}

class _Application extends State<Application> {
  bool fcmInitCheck = true;
  FirebaseMessaging messaging;

  Future<void> saveTokenToDatabase(token) async {
    Dio dio = new Dio();
    Response response;

    FormData formData = new FormData.fromMap({
      "pushToken":token
    });

    await dio.post("http://www.mysite.com/tokenRegit.php", data: formData);
  }


  Future<bool> fcmInit() async
  {
    if(fcmInitCheck) {

      fcmInitCheck = false;
      await Firebase.initializeApp();
      messaging = FirebaseMessaging.instance;

      bool getToken = true;

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

        if(settings.authorizationStatus != AuthorizationStatus.authorized)
          getToken = false;
        else {
          await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
            alert: true, // Required to display a heads up notification
            badge: true,
            sound: true,
          );
        }
      }

      if(getToken == false)
        return true;

      String token = await messaging.getToken();
      await saveTokenToDatabase(token);
      messaging.onTokenRefresh.listen(saveTokenToDatabase);
    }
    return true;
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body:FutureBuilder<bool>(
            future: fcmInit(),
            builder:(BuildContext context, AsyncSnapshot<bool> fcmSnapshot)
            {
              if(fcmSnapshot.hasData && fcmSnapshot.connectionState == ConnectionState.done)
              {
                return Text("complete");
              }
              else {
                return Text("loading");
              }
            }
        )
      );
  }
}

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 7, 2021
@markusaksli-nc
Copy link
Contributor

How exactly are you checking that initState is called in this example? You are just overriding it and calling the super.

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jul 7, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 7, 2021

How exactly are you checking that initState is called in this example? You are just overriding it and calling the super.

If you call http as in the code below, the server will check it.
Not only that.
saveTokenToDatabase() inside build() is also called.
So, I confirmed that tokenRegit.php of saveTokenToDatabase() was also called on the server.
( The site address below is a fictitious address. The server should be created and tested by yourself. )

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

  FormData formData = new FormData.fromMap({
    "mode":1
  });

  Dio dio = new Dio();
  dio.post("http://www.mysite.com/test3.php", data: formData);
}

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 7, 2021
@markusaksli-nc
Copy link
Contributor

If that is the case you should be able to narrow the example down to just printing instead of using these third-party package methods and it should still reproduce?

@markusaksli-nc markusaksli-nc removed the Needs Attention This issue needs maintainer attention. label Jul 7, 2021
@markusaksli-nc markusaksli-nc added the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Jul 7, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 7, 2021

If that is the case you should be able to narrow the example down to just printing instead of using these third-party package methods and it should still reproduce?

This situation occurs after the app is completely terminated.
The app is completely shut down and then the log cannot be checked.
Is there a way to check the logs even when the app is completely closed?
If you tell me how to do it, I'll do it.

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

  debugPrint("initState call");
}

(It will be reproduced even if you check with the above code..)
Again, the problem is that it calls Initstate(), Build() after the app exits.
It doesn't seem to have anything to do with third parties package.
And the official manual also sends tokens to the server.
Is it reasonable that there is no error without sending the token to the server?

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 7, 2021
@markusaksli-nc
Copy link
Contributor

Not sure what you mean by "official manual also sends tokens to the server". You should be able to just put

print("initState");

into initState and then open up the Console app on mac and start capturing the device logs. You can filter them down to flutter or Runner or just initState and you should be able to see this logged when the notification is received as you described.

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Jul 8, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 8, 2021

"공식 매뉴얼도 서버로 토큰을 보냅니다"라는 말이 무슨 뜻인지 잘 모르겠습니다. 그냥 넣을 수 있어야합니다

print ( "initState" );

initState다음 맥에서 콘솔 응용 프로그램을 열고 장치 로그를 캡처 시작합니다. 당신은 그들을 아래로 필터링 할 수 있습니다 flutter하거나 Runner아니면 그냥 initState당신이 당신이 설명한대로 통지가 수신 될 때 로그인 볼 수 있어야합니다.

It is reproduced with the code below.
Please check

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

  print ( "initState" );
}

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Jul 8, 2021
@markusaksli-nc
Copy link
Contributor

Seems reproducible with firebase_messaging: ^10.0.3. Although this is another manifestation being able to use the background handler when the app is terminated (until another app is opened).

flutter doctor -v
[✓] Flutter (Channel master, 2.4.0-1.0.pre.146, on macOS 11.4 20F71 darwin-arm, locale en-GB)
    • Flutter version 2.4.0-1.0.pre.146 at /Users/nevercode/development/flutter_master
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 02de429037 (69 minutes ago), 2021-07-09 03:51:04 -0400
    • Engine revision 40373cdcb6
    • Dart version 2.14.0 (build 2.14.0-293.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/nevercode/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Users/nevercode/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.5.1, Build version 12E507
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.2)
    • Android Studio at /Users/nevercode/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      � https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      � https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] Android Studio (version 4.2)
    • Android Studio at /Users/nevercode/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      � https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      � https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)

[✓] Connected device (3 available)
    • Nevercode’s iPhone (mobile) • b668e524315069f3db3661ac11ff1f66afafebdb • ios            • iOS 14.6 18F72
    • macOS (desktop)             • macos                                    • darwin-arm64   • macOS 11.4 20F71 darwin-arm
    • Chrome (web)                • chrome                                   • web-javascript • Google Chrome 91.0.4472.114

• No issues found!

@markusaksli-nc markusaksli-nc added platform: ios Issues / PRs which are specifically for iOS. plugin: messaging and removed Needs Attention This issue needs maintainer attention. triage Issue is currently being triaged. labels Jul 9, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 9, 2021

Sorry but I'm not sure what the answer means.
Are you saying there is no problem?

Seems reproducible with firebase_messaging: ^10.0.3. Although this is another manifestation being able to use the background handler when the app is terminated (until another app is opened).

flutter doctor -v

@jinnyum jinnyum closed this as completed Jul 9, 2021
@markusaksli-nc
Copy link
Contributor

No, I'm saying the issue is reproducible and warrants some investigation.

@markusaksli-nc markusaksli-nc reopened this Jul 9, 2021
@jinnyum
Copy link
Author

jinnyum commented Jul 12, 2021

No, I'm saying the issue is reproducible and warrants some investigation.

The app is being processed as a start, even though the user did not start.
I want to schedule an update for my app.
May I know how long it will take to fix?

@jinnyum
Copy link
Author

jinnyum commented Jul 19, 2021

Can anyone please give me an answer on how this issue is being resolved... T_T

@AyonAB
Copy link

AyonAB commented Aug 27, 2022

Do we have any update on the status of this issue? Do we have any workaround for the time being? This issue is preventing us to put getInitialMessage() or onMessageOpenedApp() in initState(). How else can we get RemoteMessage when a user click on the notification from a terminated state to open the app?

@darshankawar
Copy link

@jinnyum @AyonAB
Did you get a chance to verify this fix ? #9315
It was released in one of the recent plugin versions: https://pub.dev/packages/firebase_messaging/changelog#1202

@AyonAB
Copy link

AyonAB commented Aug 30, 2022

@darshankawar Yes I have tested against the most recent version also which is 13.0.0. The issue is still there.
Moreover in that PR (#9315) you mentioned, @russellwheatley commented that he found this issue.

@jinnyum
Copy link
Author

jinnyum commented Aug 31, 2022

This bug is related to developer spending.
For over a year, this bug would have cost Flutter developers false money.
It would also have caused you to see the wrong access log.
There are a lot of other important bugs, but shouldn't it be a high priority when it comes to costing?
Even now, developers are probably paying for traffic they don't even know about.

@russellwheatley
Copy link
Member

Hi, I've confirmed this as an issue. It is basically calling the main() function in the application. This will be investigated, but please follow this duplicate issue and give a thumbs up for visibility. Thanks.

@firebase firebase locked and limited conversation to collaborators Oct 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants