firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.71k stars 3.97k forks source link

FlutterJNI.loadLibrary called more than once #9964

Closed penhorwood closed 5 months ago

penhorwood commented 1 year ago

Bug report

Describe the bug The FlutterJNI.loadLibrary is called twice.

Error message displayed in the Debug Console W/FlutterJNI(10613): FlutterJNI.loadLibrary called more than once W/FlutterJNI(10613): FlutterJNI.prefetchDefaultFontManager called more than once

Steps to reproduce

Steps to reproduce the behavior:

  1. Start a simple Flutter App with FirebaseMessaging
  2. Use the FirebaseMessaging.onBackgroundMessage( backgroundRouter );
  3. Run the App in Debug or Release mode

Expected behavior

The FlutterJNI.loadLibrary will only be called once.

Sample project

https://github.com/penhorwood/firetwice

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, 3.3.8, on Microsoft Windows [Version 10.0.19044.2251], locale en-US) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.3) [√] Android Studio (version 2021.2) [√] Connected device (1 available) [√] HTTP Host Availability ```


darshankawar commented 1 year ago

Closing as duplicate of https://github.com/firebase/flutterfire/issues/9912. Please upgrade plugin version to latest to see the fix.

penhorwood commented 1 year ago

This is not a duplicate as this is still happening

I have all of the latest fixes but the duplicate Flutter.JNI.loadLibrary is still loading twice

penhorwood commented 1 year ago

Here are two screenshots of my app loading today - 11/24/2022 One is with the onBackgroundMessage used the other with that line commented out. You can see that make the difference in whether Flutter.JNI.loadLibrary loads twice.

image

2nd without onBackgroundMessage

image

darshankawar commented 1 year ago

Thanks for the feedback @penhorwood Can you please provide a complete minimal reproducible code sample in text format that shows the behavior ?

penhorwood commented 1 year ago

I have a complete example here https://github.com/penhorwood/firetwice. That is my minimal reproducible code sample. If you want me to post the files here I can.

darshankawar commented 1 year ago

Thanks for the update. I looked at the repo you provided above and observed that the background handler is not the topmost method, unlike in the plugin example.

https://github.com/firebase/flutterfire/blob/26087bb2d1747eb5db82c98424b6d63071137529/packages/firebase_messaging/firebase_messaging/example/lib/main.dart#L47

Also, try to have the @pragma('vm:entry-point') annotation as mentioned in the comments above the declaration and see if it helps in your case.

penhorwood commented 1 year ago

I followed your instructions. No change on the results.

W/FlutterJNI( 5559): FlutterJNI.loadLibrary called more than once W/FlutterJNI( 5559): FlutterJNI.prefetchDefaultFontManager called more than once

You can view my changes on the repo.

penhorwood commented 1 year ago

Just an FYI. I think when it says top most method it is talking about as in not part of a class. Where it is in main.dart should not matter but that is just my current understanding. I could be wrong.

darshankawar commented 1 year ago

Thanks for the update. Using the sample repo, I do see the same behavior as reported. Keeping it open for team's attention and insights.

Lyokone commented 1 year ago

Thanks for the report, I'm investigating this

This error is caused by line 159 in FlutterFirebaseMessagingBackgroundExecutor.java. Not sure if we can intervene here.

mark8044 commented 1 year ago

Seeing the same thing here

sadaqatdev commented 1 year ago

D/FlutterGeolocator(29054): Creating service. D/FlutterGeolocator(29054): Binding to location service. D/FlutterLocationService(29054): Creating service. D/FlutterLocationService(29054): Binding to location service. D/FlutterGeolocator(29054): Flutter engine connected. Connected engine count 1 W/FlutterJNI(29054): FlutterJNI.loadLibrary called more than once W/FlutterJNI(29054): FlutterJNI.prefetchDefaultFontManager called more than once W/FlutterJNI(29054): FlutterJNI.init called more than once D/FlutterGeolocator(29054): Flutter engine connected. Connected engine count 2

pushpendraKh commented 1 year ago

I am also facing the same issue. @darshankawar Any progress on this?

eudorolshop commented 1 year ago

this issue happened to me. occurs when the application is first run only and in the app foreground.

after receiving/displaying notification in foreground then after a few seconds the app got crashed (force close/Wait & Ok Prompt). if i choose Wait, the app and notification (fcm) running smoothly.

I've tried various ways to overcome this issue, but no significant result.

please, any workaround for this issue?

library use :

firebase_messaging: 14.2.2 firebase_core: 2.5.0

flutter doctor :

[√] Flutter (Channel stable, 3.7.3, on Microsoft Windows [Version 10.0.18363.592], locale en-US)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web

Error Log : Attempted to start a duplicate background isolate. Returning

danielgomezrico commented 1 year ago

@eudorolshop that seems like a different issue, WDYT?

@Lyokone is still happening to me on:

  firebase_core: 2.4.1
  firebase_crashlytics: 3.0.11
  firebase_analytics: 10.1.0
  firebase_messaging: 14.2.1

And on:

  firebase_core: 2.5.0
  firebase_crashlytics: 3.0.12
  firebase_analytics: 10.1.1
  firebase_messaging: 14.2.2
eudorolshop commented 1 year ago

@eudorolshop that seems like a different issue, WDYT?

@danielgomezrico sometimes i got this issue too, FlutterJNI.loadlibrary called more than once. at least related to this.

sadaqatdev commented 1 year ago

this cause by location plugin

cindyha commented 1 year ago

It's still happening to me on firebase_messaging: ^14.2.4 firebase_core: ^2.6.1

firebase_messaging_issue

lybur commented 1 year ago

The same happens to me when the app is in its first launch. I'm using firebase_messaging: ^14.1.1 image

danielgomezrico commented 1 year ago

Maybe this is related to this other issue?

penhorwood commented 1 year ago

Any movement on this bug? This is still happening to me with firebase_messaging: 14.5.0

juliavi commented 1 year ago

Same here. Any updates on this issue?

abdalmonem commented 1 year ago

@darshankawar

This issue is serous danger! I investigate it , and i come with: 1 - The main isolate called one time in the background 2 - The main isolate thats triggered from the "FCM" going to load the plugins and act normally as a UI isolate, and keep trying render widgets. 3 - When "main" get trigger by FCM notification the "onBackgroundMessage" going to re register it self with another one, (here we got the error ) , and this is why you got just one. 4 - Even if "onBackgroundMessage" handler is not crashed in first time , it will going to call it self in a recursion way

The normal behave : The "FCM" trigger the main isolate but should skip at least run "runapp()", this going to solve the issue if we call "onBackgroundMessage" inside runApp and not directly in the main.

Suggested solution: Provide a way to check which "VM entry point" has called the main. This will provide way to avoid re initiate "onBackgroundMessage" and give the developers options to deal logically on They way.

yeikel16 commented 1 year ago

The same happens to me when the app is in its first launch.

Captura de pantalla 2023-08-01 a la(s) 3 20 31 p m
abdalmonem commented 1 year ago

@yeikel16 i believe we can skip this issue if Dart team add any way to find the name of entry-pointthat ran the main

milindgoel15 commented 1 year ago

It happens with my app and I am not using firebase messaging. The packages I am using are firebase core, performance and analytics. So I don't think it's an issue on messaging. Probably related to core

larsien commented 1 year ago

I also faced this issue. When I get duplicated push notification in background state then that log is found.

This is my log when I duplicated push notification and not

D/FLTFireMsgReceiver(24096): broadcast received for message W/FlutterJNI(24096): FlutterJNI.loadLibrary called more than once I/ResourceExtractor(24096): Found extracted resources res_timestamp-53-1692196013697 W/FlutterJNI(24096): FlutterJNI.prefetchDefaultFontManager called more than once W/FlutterJNI(24096): FlutterJNI.init called more than once I/FLTFireBGExecutor(24096): Creating background FlutterEngine instance. I/FLTFireMsgService(24096): Service has not yet started, messages will be queued. W/ato.pesca.debu(24096): Accessing hidden method Landroid/os/WorkSource;->add(I)Z (unsupported,test-api, reflection, allowed) W/ato.pesca.debu(24096): Accessing hidden method Landroid/os/WorkSource;->add(ILjava/lang/String;)Z (unsupported,test-api, reflection, allowed) W/ato.pesca.debu(24096): Accessing hidden method Landroid/os/WorkSource;->get(I)I (unsupported, reflection, allowed) W/ato.pesca.debu(24096): Accessing hidden method Landroid/os/WorkSource;->getName(I)Ljava/lang/String; (unsupported, reflection, allowed) D/CompatibilityChangeReporter(24096): Compat change id reported: 160794467; UID 11208; state: ENABLED I/TRuntime.CctTransportBackend(24096): Making request to: https://firebaselogging-pa.googleapis.com/v1/firelog/legacy/batchlog I/FLTFireMsgService(24096): FlutterFirebaseMessagingBackgroundService started! I/TRuntime.CctTransportBackend(24096): Status Code: 200

And this is a log when push notification is not duplicated ( normal state)

D/FLTFireMsgReceiver(26894): broadcast received for message W/ato.pesca.debu(26894): Accessing hidden method Landroid/os/WorkSource;->add(I)Z (unsupported,test-api, reflection, allowed) W/ato.pesca.debu(26894): Accessing hidden method Landroid/os/WorkSource;->add(ILjava/lang/String;)Z (unsupported,test-api, reflection, allowed) W/ato.pesca.debu(26894): Accessing hidden method Landroid/os/WorkSource;->get(I)I (unsupported, reflection, allowed) W/ato.pesca.debu(26894): Accessing hidden method Landroid/os/WorkSource;->getName(I)Ljava/lang/String; (unsupported, reflection, allowed) D/CompatibilityChangeReporter(26894): Compat change id reported: 160794467; UID 11208; state: ENABLED

nukeolay commented 1 year ago

Have same issue. Any success with solving it?

egedib commented 1 year ago

It happens with my app and I am not using firebase messaging. The packages I am using are firebase core, performance and analytics. So I don't think it's an issue on messaging. Probably related to core

That's the separate issue - this issue is for the problem related to onBackgroundMessage - check the opening comment. I suggest creating a separate issue, but check StackOverflow first.

I also faced this issue. When I get duplicated push notification in background state then that log is found.

I suspect this is also a different issue - I have this problem with onBackgroundMessage, but the notifications are arriving only once.

aly22 commented 1 year ago

Was facing the same problem, After writing @pragma('vm:entry-point') before the top level function it fixed it. Like this:

@pragma('vm:entry-point')
Future<void> _firebaseBackgroundMessage(RemoteMessage message) async {
  if (message.notification != null) {
    print('A message received');
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [
    SystemUiOverlay.top,
    SystemUiOverlay.bottom,
  ]);
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await PushNotifications.init();

  runApp(const MyApp());
  FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundMessage);
}
penhorwood commented 1 year ago

I tried the @pragma('vm:entry-point') above my methods. It made no difference.

georgidimitrovx commented 1 year ago

This issue was resolved in my case when I removed "just_audio_background" package from pubspec.yaml. If you don't have this package, go through other packages you have and check if any of them invoke a call to main(). This can be done by removing one package at a time and running the app to check if the invocation occurs.

Why it happens When the just_audio_background plugin is set up to handle background audio tasks, it essentially starts up a new Flutter instance (a new isolate) to manage audio playback in the background. This new isolate requires an entry point, which usually is the main() function.

What to do if you need to use "just_audio_background"

  1. You should create a distinct entry point for background processing that doesn't involve running your entire app. This ensures that the audio processing logic runs in isolation, without unnecessary overhead.
    void audioPlayerTaskEntrypoint() {
    AudioServiceBackground.run(() => MyAudioTask());
    }
  2. Modify AndroidManifest.xml: In your Android configuration, you need to specify this separate entry point:
    <application ...>
    ...
    <service android:name="com.ryanheise.just_audio_background.AudioHandlerService">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
        <meta-data
            android:name="com.ryanheise.just_audio_background.android_entry_point"
            android:value="audioPlayerTaskEntrypoint" />
    </service>
    </application>

    By doing the above, when the just_audio_background plugin needs to spin up its background service, it will specifically call the audioPlayerTaskEntrypoint() function, rather than your primary main() function.

xwarzdev commented 1 year ago

Any update? Same problem here 2 main apps running in callstack, tried the pragma anotation but didnt work. If I dont call FirebaseMessaging.onBackgroundMessage( _handler ); only 1 main app running in callstack.

firebase_messaging: ^14.7.4 firebase_core: ^2.22.0

[UPDATE] Well, I was testing things, and one of that thing works: This is part of my main.dart file

`

   @pragma('vm:entry-point')
        Future<void> _handlebackGroundNotification(RemoteMessage message) async {
          await Firebase.initializeApp();
            navigatorKey.currentState?.push(MaterialPageRoute(builder: (context) => 
            NotificationPlaceholderRoute({message:message})));
       }

  void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    await Hive.initFlutter();
    await Hive.openBox('auth_box');
    await FirebaseHelper().initFirebaseMessaging();
    const InitialDataLoad initialDataLoad = InitialDataLoad();
    await initialDataLoad.loadCombos();
    runApp(const MyApp());
  }

` I intialize the app like that, and I only see in the callstack one main execution. image

As you see, I dont call _handlebackGroundNotification in any part of the main.dart file (and in other part of the app neither).

Then I closed the app image

and send a notification from firebase web, and it works perfectly. image

If someone can follow the steps I describe above and test what I did works, will be apreciated.

micant commented 11 months ago

If someone can follow the steps I describe above and test what I did works, will be apreciated.

I have the same configuration as you.

If I register FirebaseMessaging.onBackgroundMessage(_handler), I get two calls of main in my call stack and I get some unexpected behaviour, where routing via context works some of the time. If I remove the handler, everything works as expected.

Edit - the issue stated with routing above was a bug on my end and not related to the issue of duplicate isolates. I've since moved this feature into production and haven't encountered any issues related to it.

gabrielgiovans commented 10 months ago

I am having the same issue when using the FirebaseMessaging.onBackgroundMessage(_handler) function.

FirebaseMessaging Version: 14.7.9

Any updates on this bug? I see threads with dates of 2 years or more and no solution...

mr-bipolar commented 9 months ago

if(Firebase.apps.isEmpty){ await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); }

shivkumarordrio commented 7 months ago

This issue was resolved in my case when I removed "just_audio_background" package from pubspec.yaml. If you don't have this package, go through other packages you have and check if any of them invoke a call to main(). This can be done by removing one package at a time and running the app to check if the invocation occurs.

Why it happens When the just_audio_background plugin is set up to handle background audio tasks, it essentially starts up a new Flutter instance (a new isolate) to manage audio playback in the background. This new isolate requires an entry point, which usually is the main() function.

What to do if you need to use "just_audio_background"

  1. You should create a distinct entry point for background processing that doesn't involve running your entire app. This ensures that the audio processing logic runs in isolation, without unnecessary overhead.
void audioPlayerTaskEntrypoint() {
  AudioServiceBackground.run(() => MyAudioTask());
}
  1. Modify AndroidManifest.xml: In your Android configuration, you need to specify this separate entry point:
<application ...>
    ...
    <service android:name="com.ryanheise.just_audio_background.AudioHandlerService">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
        <meta-data
            android:name="com.ryanheise.just_audio_background.android_entry_point"
            android:value="audioPlayerTaskEntrypoint" />
    </service>
</application>

By doing the above, when the just_audio_background plugin needs to spin up its background service, it will specifically call the audioPlayerTaskEntrypoint() function, rather than your primary main() function.

I am facing same issue. But I am not able to understand your solution. Please help me


Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  if (message.notification != null) {
    print('Handling a background message ${message.messageId}');
    final notification = AppNotification.fromMessage(message, false);
    NotificationWriter.writeNotification(notification);
  }
}

void main() {
  run();
}

void run() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp(
      options: {
        Env.dev: defaultTargetPlatform == TargetPlatform.iOS
            ? prod.DefaultFirebaseOptions.currentPlatform
            : dev.DefaultFirebaseOptions.currentPlatform,
        Env.prod: prod.DefaultFirebaseOptions.currentPlatform
      }[Config.env]!,
    );
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    await JustAudioBackground.init(
      androidNotificationChannelId: 'com.ryanheise.bg_demo.channel.audio',
      androidNotificationChannelName: 'Audio playback',
      androidNotificationOngoing: true,
      androidNotificationClickStartsActivity: true,
      androidResumeOnClick: true,
      androidShowNotificationBadge: true,
      androidStopForegroundOnPause: true,
    );
    runApp(
      ProviderScope(
        parent: ref,
        child: const MyApp(),
      ),
    );
}```
corepuncher commented 6 months ago

Same issue here. I made sure to use a single instance of FirebaseMessaging, but did not help. Seems like an annoyance more than anything.