85

As soon as I updated the flutter to version 1.12.13 I found this issue and can't fix it. I did as the firebase_messaging tutorial sent and got the following error: "error: incompatible types: PluginRegistry cannot be converted to FlutterEngine GeneratedPluginRegistrant.registerWith (registry); " My code is as follows:

package io.flutter.plugins;

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

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;

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

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
      NotificationChannel channel = new NotificationChannel("messages","Messages", NotificationManager.IMPORTANCE_LOW);
  NotificationManager manager = getSystemService(NotificationManager.class);
  manager.createNotificationChannel(channel);
    }
  }

  @Override
  public void registerWith(PluginRegistry registry) {
    GeneratedPluginRegistrant.registerWith(registry);
  }
}
Gabriel G. Pavan
  • 1,047
  • 1
  • 7
  • 12

9 Answers9

115

Replace this code line:

GeneratedPluginRegistrant.registerWith(registry);

with this:

FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));

Make sure to import:

import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
Taufiq Rahman
  • 5,600
  • 2
  • 36
  • 44
mehrdad seyrafi
  • 3,084
  • 2
  • 19
  • 16
  • 13
    It worked... just remember to import the class mentioned. import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin; – zion Apr 29 '20 at 17:48
  • 1
    One important note: if you use different plugins on the flutter side of your background message callback, you also need to add the line "MyPlugin.registerWith(registry.registrarFor("package.MyPlugin")); for each used plugin. they won't be added by the GeneratedPluginRegistrant, as it's no longer executed by the background process. – Jeff S. Oct 28 '20 at 13:00
  • "registrarFor" is deprecated in latest update. What's the alternative? – BLB Apr 05 '21 at 06:22
  • correct! adding some thing to this. not only this FirebaseMessagingPlugin.instead you can use the plugin name that you use in your case.. like android_alarm_manager or flt_worker. – RusJaI May 01 '21 at 15:56
  • If I do this, it keeps installing apk for ever – Lea González Cuello Nov 11 '21 at 15:10
38

Updated on December 31, 2019.

You should not use the Firebase cloud messaging tool to send notifications, as it forces you to use the title and body.

You must send a notification without the title and body. have the application in the background, that should work for you.

If it works for you, I would appreciate it if you could give me a vote on this answer, thank you.


I have found a temporary solution. 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.

My AndroidManifest.xml file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="Your Package"> // CHANGE THIS

    <application
        android:name=".Application"
        android:label="" // YOUR NAME APP
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        <!-- BEGIN: Firebase Cloud Messaging -->    
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        <!-- END: Firebase Cloud Messaging -->    
        </activity>
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

My Application.java

package YOUR PACKAGE HERE;

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);
  }
}

My FirebaseCloudMessagingPluginRegistrant.java

package YOUR PACKAGE HERE;

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;
  }
}

Send Notification in dart:

Future<void> sendNotificationOnBackground({
  @required String token,
}) async {
  await firebaseMessaging.requestNotificationPermissions(
    const IosNotificationSettings(sound: true, badge: true, alert: true, provisional: false),
  );
  await Future.delayed(Duration(seconds: 5), () async {
    await http.post(
    'https://fcm.googleapis.com/fcm/send',
     headers: <String, String>{
       'Content-Type': 'application/json',
       'Authorization': 'key=$SERVERTOKEN', // Constant string
     },
     body: jsonEncode(
     <String, dynamic>{
       'notification': <String, dynamic>{

       },
       'priority': 'high',
       'data': <String, dynamic>{
         'click_action': 'FLUTTER_NOTIFICATION_CLICK',
         'id': '1',
         'status': 'done',
         'title': 'title from data',
         'message': 'message from data'
       },
       'to': token
     },
    ),
  );
  });  
}

I added a wait with a duration of 5 seconds so you can put the application in the background and verify that the message in the background is running

DomingoMG
  • 1,827
  • 2
  • 23
  • 44
  • I tried is your solution but I was unsuccessful, in ONLAUNCH, ONRESUME and ONMESSAGE states appeared, only on ONBACKGROUND not. I put the file FirebaseCloudMessagingPluginRegistrant.java in the same folder as Application.java, was that right? I hope the Flutter team will solve this problem soon. By then I will have to use version 1.9.1, although I want to use 1.12.13 so badly – Gabriel G. Pavan Dec 27 '19 at 00:30
  • Could you create a project and give me the link on your github for me to download and try to run it on my Firebase test project? – Gabriel G. Pavan Dec 27 '19 at 00:32
  • I leave a structure that has helped me send push notifications with dart – DomingoMG Dec 31 '19 at 13:54
  • This worked. Not sure why, but it did. Hope the flutter team fixes this in the next release – Avi Jan 30 '20 at 07:41
  • where I put the FirebaseCloudMessagingPluginRegistrant.JAVA, in the same folder as the Application or in a firebasemessaging folder? I still couldn't get it to work – Gabriel G. Pavan Feb 17 '20 at 20:28
  • Exactly, you should put it in the folder: => /Android/app/src/java/com.example/Here. If you use kotlin, use Vinicius Zani's answer. I would appreciate it if you valued my answer as a solution, thank you. – DomingoMG Mar 26 '20 at 13:46
  • I would also like to know how to add a custom channel – anonymous-dev Jun 30 '20 at 13:19
29

A port of DomingoMG's code to Kotlin can be found below (file paths included). Tested and working on 10.2020.

/pubspec.yaml

firebase_messaging: ^7.0.0

/android/app/src/main/kotlin/Application.kt

package YOUR_PACKAGE_HERE

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: FlutterApplication(), PluginRegistrantCallback {
  override fun onCreate() {
    super.onCreate()
    FlutterFirebaseMessagingService.setPluginRegistrant(this)
  }

  override fun registerWith(registry: PluginRegistry) {
    FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
  }
}

/android/app/src/main/kotlin/FirebaseCloudMessagingPluginRegistrant.kt

package YOUR_PACKAGE_HERE

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

class FirebaseCloudMessagingPluginRegistrant {
  companion object {
    fun registerWith(registry: PluginRegistry) {
      if (alreadyRegisteredWith(registry)) {
        return;
      }
      FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"))
    }

    fun alreadyRegisteredWith(registry: PluginRegistry): Boolean {
      val key = FirebaseCloudMessagingPluginRegistrant::class.java.name
      if (registry.hasPlugin(key)) {
        return true
      }
      registry.registrarFor(key)
      return false
    }
  }
}
Vinicius Zani
  • 479
  • 4
  • 5
  • 3
    Hi, ``` Execution failed for task ':app:mergeDexDebug'. > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes. Program type already present: com.example.gf_demo.FirebaseCloudMessagingPluginRegistrant ``` – Kamil Apr 28 '20 at 13:48
  • I have a 1.17 project which didn't have a MainActivity.java, and no matter how much cludging I did, I could not get my Flutter app to build with `firebase_messaging`. Using this answer, it built right away! Thank you! – sean.boyer May 11 '20 at 22:51
  • 1
    Could you add in which folder the files need to be placed? – anonymous-dev Jun 30 '20 at 11:44
  • love you man struggled whole day and at last found it – Zeeshan Mehdi Aug 31 '20 at 14:28
  • 3
    Now this error occured Unable to instantiate activity ComponentInfo{com.example.firebase_push_notification_my/com.example.firebase_push_notification_my.Application}: java.lang.ClassCastException: com.example.firebase_push_notification_my.Application cannot be cast to android.app.Activity – scienticious Oct 16 '20 at 12:44
  • Thank you so much! You've saved me a lot of nerves and time by this. I just couldn't find out why push notifications do not come when an app is closed. Now everything works like a charm – Konstantin Nov 09 '20 at 05:31
  • I've got an error e: D:\Namaa\projects\podcasti_mobile\android\app\src\main\kotlin\Application.kt: (6, 27): Unresolved reference: firebasemessaging – Abdulmalek Dery Apr 17 '21 at 12:15
9

Some research and I found this to be working.
Seached up the official Flutterfire repository, and checked out the latest plugins on it. GeneratedPluginRegistrant.registerWith(registry); was not working, which is mentioned on the official docs as well. FlutterFire firebase_messaging.

Using the plugin io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin, which I discovered from Flutterfire GitHub repo

Currently on firabase_messaging: 9.0.0

//
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingBackgroundService;
// Be sure to import the exact Plugin
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingPlugin;

public class Application extends FlutterApplication implements PluginRegistrantCallback {
//
@Override
  public void onCreate() {
    super.onCreate();
    FlutterFirebaseMessagingBackgroundService.setPluginRegistrant(this);
    }
 @Override
  public void registerWith(PluginRegistry registry) {
     FlutterFirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
  }
}
Yuvraj Singh
  • 644
  • 6
  • 6
3

Just Do

GeneratedPluginRegistrant.registerWith((FlutterEngine) registry);

inplace of

GeneratedPluginRegistrant.registerWith(registry);
Srijan
  • 100
  • 1
  • 6
  • 3
    add import io.flutter.embedding.engine.FlutterEngine; – Abdulmalek Dery Aug 07 '20 at 09:22
  • 4
    Got a message saying it can't cast to FlutterEngine. Solution from Inconnu using "registry.registrarFor() worked." – Bikey Aug 29 '20 at 03:21
  • This will work for a short time but eventually you will not be able to run your app. I am now getting the error `E/AndroidRuntime(11500): java.lang.ClassCastException: io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry cannot be cast to io.flutter.embedding.engine.FlutterEngine` – Yonko Kilasi Mar 05 '21 at 14:30
  • This solutions is wrong. App will crash by throwing ClassCastException – Lins Louis Jun 24 '22 at 10:41
1

In addition to DomingoMG's answer, don't forget to remove

@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);

from the mainactivity file under the android folder. If not, you will get an error.

Axes Grinds
  • 756
  • 12
  • 24
  • But where I can register my own MethodChannel, when I'll remove configureFlutterEngine? – Kamil Svoboda Feb 25 '20 at 08:28
  • According to DomingoMG's answer, FirebaseCloudMessagingPluginRegistrant.java already does the registration of "registerWith..." so that is why configureFlutterEngine is no longer needed. Does that answer your question? – Axes Grinds Feb 26 '20 at 10:35
  • I understand the FirebaseCloudMessagingPluginRegistrant.java does the registration instead of configureFlutterEngine. But configureFlutterEngine is place where I can register my own MethodChannel to call native API (please see "Writing custom platform-specific code" on flutter.dev). Where can I register MethodChannel when the method configureFlutterEngine is removed? – Kamil Svoboda Mar 04 '20 at 21:25
  • I don't have any experience with writing platform-specific code. Sorry that I can't help with that information. I hope you found an answer. – Axes Grinds Apr 01 '20 at 01:12
1

I added only water class as extra from the steps in Firebase Messaging package and it was solved :

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;
}}
sevki.ctnr
  • 29
  • 4
1

I found this to work:

@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    // continue with custom method channel registration.
    ...    
}

Not sure if you also need to use cleanUpFlutterEngine to clean method channel registration.

m02ph3u5
  • 3,022
  • 7
  • 38
  • 51
0

Change your MainActivity.java file to: package co.appbrewery.micard;

import io.flutter.embedding.android.FlutterActivity;

public class MainActivity extends FlutterActivity {

}

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 21 '22 at 06:23