Skip to content
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

[firebase_messaging] Conflicts with other plugins using the PluginRegistry in GeneratedPluginRegistrant via FlutterFire's PluginRegistry.PluginRegistrantCallback #1591

Closed
NateNjuguna opened this issue Dec 10, 2019 · 14 comments
Labels
platform: android Issues / PRs which are specifically for Android. plugin: messaging type: bug Something isn't working

Comments

@NateNjuguna
Copy link

NateNjuguna commented Dec 10, 2019

io.flutter.plugins.GeneratedPluginRegistrant.registerWith doesn't work as expected when called from io.flutter.plugins.firebasemessagingFlutterFirebaseMessagingService.startBackgroundIsolate
This registrant groups together all plugins for a single registration run thus causing other plugins depending on the full class API for io.flutter.plugin.common.PluginRegistry.Registrar (for example: Registrar.activity() returns a null object reference) to malfunction. I believe this happens because the io.flutter.view.FlutterNativeView created by io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.startBackgroundIsolate does not create a drawing surface as indicated ( Lines 154 - 165 )

    // Note that we're passing `true` as the second argument to our
    // FlutterNativeView constructor. This specifies the FlutterNativeView
    // as a background view and does not create a drawing surface.
    backgroundFlutterView = new FlutterNativeView(context, true);
    if (appBundlePath != null && !isIsolateRunning.get()) {
      if (pluginRegistrantCallback == null) {
        throw new RuntimeException("PluginRegistrantCallback is not set.");
      }
      FlutterRunArguments args = new FlutterRunArguments();
      args.bundlePath = appBundlePath;
      args.entrypoint = flutterCallback.callbackName;
      args.libraryPath = flutterCallback.callbackLibraryPath;
      backgroundFlutterView.runFromBundle(args);
      pluginRegistrantCallback.registerWith(backgroundFlutterView.getPluginRegistry());
    }

The call to registerWith receives a registry with some limited API since the aim is to provide a background service for receiving messages in the background. This however causes other plugins like flutter_autofill - which depend on Registrar.activity() to return Activity; to crumble and fail to work as expected.

To Reproduce
Steps to reproduce the behavior:

  1. Create a new flutter project with the latest version
  2. Install the FlutterAutofill package
  3. Create the simple example form provided in the readme section
  4. Run the app on the device. launches and works as expected
  5. Add the firebase_messaging package and follow the instructions to add background message handling support
  6. Attempt a build or run the app on the device.
  7. The app reports a problem with null object reference on line 114 of com.applaudsoft.flutter_autofill.FlutterAutofillPlugin for the registrar.activity() call.

Expected behavior
io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.pluginRegistrantCallback.registerWith should pass a registry that creates a valid registrar in GeneratedPluginRegistrant compatible with other plugins (for example: plugins dependent on a drawing surface, activity e.t.c to work)

Additional context
I managed to get mine working by creating a new FirebaseCloudMessagingPluginRegistrant and calling FirebaseMessagingPlugin.registerWith as the only plugin registration to support the background messaging. I replaced GeneratedPluginRegistrant with this custom registrant for in the Application.java found in the readme section as shown below.
Also allowing the default GeneratedPluginRegistrant to register the plugin a second time from the default MainActivity.java ensures I still get my other plugins to work as expected before adding firebase_messaging. I am not sure this is the best fix but my plugins work as expected and I assume the problem has to be with the registry provided by io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService on line 164.

FirebaseCloudMessagingPluginRegistrant.java

package <my app package name>;

import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;

public final class FirebaseCloudMessagingPluginRegistrant{
  public static void registerWith(PluginRegistry registry) {
    if (alreadyRegisteredWith(registry)) {
      return;
    }
    FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
  }

  private static boolean alreadyRegisteredWith(PluginRegistry registry) {
    final String key = FirebaseCloudMessagingPluginRegistrant.class.getCanonicalName();
    if (registry.hasPlugin(key)) {
      return true;
    }
    registry.registrarFor(key);
    return false;
  }
}

Application.java

package <my app package name>;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;

public class Application extends FlutterApplication implements PluginRegistrantCallback {
  @Override
  public void onCreate() {
    super.onCreate();
    FlutterFirebaseMessagingService.setPluginRegistrant(this);
  }

  @Override
  public void registerWith(PluginRegistry registry) {
    FirebaseCloudMessagingPluginRegistrant.registerWith(registry);
  }
}

MainActivity.java

package <my app package name>;

import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }
}
@NateNjuguna NateNjuguna added the type: bug Something isn't working label Dec 10, 2019
@iapicca
Copy link

iapicca commented Dec 11, 2019

Hi @NateNjuguna
can you please provide your updated flutter doctor -v
and your flutter run --verbose?

Please note that flutter_autofill is a 3rd party plugin,
to address the problem with said plugin you might want to open an issue in the dedicated github

Thank you

@iapicca iapicca added the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Dec 11, 2019
@NateNjuguna
Copy link
Author

NateNjuguna commented Dec 11, 2019

I'm using flutter_autofill just as an example,

The main problem however is having plugins registered via FlutterFirebaseMessagingService.pluginRegistrantCallback.registerWith(PluginRegistry) which calls GeneratedPluginRegistrant.registerWith(PluginRegistry) (i.e. in the sample Application.java given in the readme section of the documentation) will cause exceptions for plugins that need or expect to register at later or different stages (i.e. at the default MainActivity.java file that works fine before adding firebase_messaging and it's background fix to the mix)

Here's my flutter doctor -v

[√] Flutter (Channel stable, v1.9.1+hotfix.6, on Microsoft Windows [Version 10.0.18362.476], locale en-KE)
    • Flutter version 1.9.1+hotfix.6 at <$HOME>\.flutter
    • Framework revision 68587a0916 (3 months ago), 2019-09-13 19:46:58 -0700
    • Engine revision b863200c37
    • Dart version 2.5.0

 
[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at <$HOME>/.android
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • ANDROID_HOME = <$HOME>/.android
    • ANDROID_SDK_ROOT = <$HOME>/.android
    • Java binary at: C:\Program Files\Java\jdk1.8.0_172\bin\java
    • Java version Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
    • All Android licenses accepted.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/setup/#android-setup for detailed instructions).

[√] VS Code, 64-bit edition (version 1.40.2)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension version 3.7.0

[√] Connected device (1 available)
    • XXXXXX • 192.168.1.155:5555 • android-arm64 • Android 9 (API 28)

! Doctor found issues in 1 category.

and flutter run --verbose when the error occurs

D/ViewRootImpl@a62c401[MainActivity]( 6144): Relayout returned: old=[0,0][720,1560] new=[0,0][720,1560] result=0x5 surface={false 0} changed=true
D/ViewRootImpl@a62c401[MainActivity]( 6144): stopped(true) old=false
D/SurfaceView( 6144): windowStopped(true) false io.flutter.view.FlutterView{607568a VFE...... ........ 0,0-720,1476} of ViewRootImpl@a62c401[MainActivity]
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): Failed to handle method call
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window android.app.Activity.getWindow()' on a null object reference
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at com.applaudsoft.flutter_autofill.FlutterAutofillPlugin.init(FlutterAutofillPlugin.java:114)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at com.applaudsoft.flutter_autofill.FlutterAutofillPlugin.<init>(FlutterAutofillPlugin.java:42)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at com.applaudsoft.flutter_autofill.FlutterAutofillPlugin.registerWith(FlutterAutofillPlugin.java:50)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:17)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at <my app package name>.Application.registerWith(Application.java:18)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.startBackgroundIsolate(FlutterFirebaseMessagingService.java:164)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.onMethodCall(FirebaseMessagingPlugin.java:134)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:222)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:96)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:656)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at android.os.MessageQueue.next(MessageQueue.java:326)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at android.os.Looper.loop(Looper.java:181)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at android.app.ActivityThread.main(ActivityThread.java:7091)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
E/MethodChannel#plugins.flutter.io/firebase_messaging( 6144): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

@gerryhigh
Copy link

I'm seeing the same thing. I'm using the device_calendar plugin with the exact same error traceback.

I'm on 6.0.9 version of the plugin on the master channel.

Flutter (Channel master, v1.13.3-pre.23, on Microsoft Windows [Version 10.0.18362.535], locale en-US)
• Flutter version 1.13.3-pre.23
• Framework revision c06bf6503a (2 days ago), 2019-12-13 17:42:35 -0500
• Engine revision e0e0ac0a68
• Dart version 2.8.0 (build 2.8.0-dev.0.0 45db297095)

@NateNjuguna
Copy link
Author

Did you try the fix above? It worked for me

@gerryhigh
Copy link

I haven't tried the fix yet.

@NateNjuguna
Copy link
Author

Updated flutter doctor -v

[√] Flutter (Channel stable, v1.12.13+hotfix.5, on Microsoft Windows [Version 10.0.18363.535], locale en-KE)
    • Flutter version 1.12.13+hotfix.5 at <$HOME>\.flutter
    • Framework revision 27321ebbad (6 days ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at <$HOME>\.android
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • ANDROID_HOME = <$HOME>\.android
    • ANDROID_SDK_ROOT = <$HOME>\.android
    • Java binary at: <$JAVA_HOME>\bin\java
    • Java version Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
    • All Android licenses accepted.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/setup/#android-setup for detailed instructions).

[√] VS Code, 64-bit edition (version 1.40.2)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension version 3.7.1

[√] Connected device (1 available)
    • XXXXXX • 192.168.1.155:5555 • android-arm64 • Android 9 (API 28)

! Doctor found issues in 1 categories.

@gerryhigh
Copy link

I was using a really old version of the device_calendar plugin. Once I updated it my error went away. I then look at the change log and found this issue which they address for headless execution:

builttoroam/device_calendar#101

@DomingoMG
Copy link

It worked for me. I have used your answer to help others correct the error. At least it is a temporary solution.

@NateNjuguna
Copy link
Author

NateNjuguna commented Jan 2, 2020

Hi,
I found a clue as to why this may be a problem for those upgrading to 1.12+ from earlier versions
See Supporting the new Android plugins APIs.
This pretty much explains why my solution works and why I get NULL from PluginRegistry.Registrar.activity()

@tharit-haup
Copy link

FirebaseCloudMessagingPluginRegistrant.registerWith(registry);

You save my life. Btw, Why register multiple plugins in Application.java make it crash?

@NateNjuguna
Copy link
Author

@tharit-haup see my last comment. I posted a link as to why this may be happening

@iapicca iapicca removed the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Feb 7, 2020
@kirstywilliams
Copy link
Contributor

Hey @NateNjuguna I'm reviewing issues, is this still an issue or can it be closed? Looks like it's been solved with a version upgrade?

@helenaford helenaford added plugin: messaging platform: android Issues / PRs which are specifically for Android. labels Apr 21, 2020
@NateNjuguna
Copy link
Author

I've been using the fix I mentioned above and it's been working so far. The version upgrade doen't help

@Salakar
Copy link
Member

Salakar commented Nov 5, 2020

Hey all 👋

As part of our roadmap (#2582) we've just shipped a complete rework of the firebase_messaging plugin that aims to solve this and many other issues. Specifically; messaging now supports v2 embedding.

If you can, please try out the dev release (see the migration guide for upgrading and for changes) and if you have any feedback then join in the discussion here.

Given the scope of the rework I'm going to go ahead and close this issue in favor of trying out the latest plugin.

Thanks everyone.

@Salakar Salakar closed this as completed Nov 5, 2020
@firebase firebase locked and limited conversation to collaborators Dec 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform: android Issues / PRs which are specifically for Android. plugin: messaging type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants