When the app goes to the fcm configure : _firebaseMessaging.configure(),
it throws exception
PlatformException (PlatformException(error, registrar.activity() must not be null, null))
I also tried handler method as STATIC, but it throws the same exception.
Steps to reproduce the behavior:
myBackgroundMessageHandlermyBackgroundMessageHandler as onBackgroundMessage inside the _firebaseMessaging.configure()_firebaseMessaging.configure()onBackgroundMessage as comment, it runs normally.final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
String _urlBase = url.urlBase;
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
print(data);
}
if (message.containsKey('notification')) {
// Handle notification message
final dynamic notification = message['notification'];
print(notification);
}
// Or do other work.
}
class Homepage extends StatefulWidget {
Homepage({Key key, this.pageIndex}) : super(key: key);
final pageIndex;
@override
_HomepageState createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
//URL launcher
static const platform = const MethodChannel('example.com/channel');
ScrollController _controller;
@override
void initState() {
super.initState();
_regChannel();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
try {
await getUserNotificationLists();
String iconImg;
for (var eachNotification in _userNotificationList) {
if (eachNotification['post_id'] == message['data']['post_id']) {
iconImg = eachNotification['icon_img'];
break;
}
}
showOverlayNotification((context) {
return overlayNotificationCard(
message['notification']['title'],
message['notification']['body'],
iconImg,
message['data']['post_id'],
context);
}, duration: Duration(milliseconds: 5000));
print("onMessage: $message");
} catch (e) {
print(e);
}
},
onBackgroundMessage: Platform.isIOS ? null : myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
getUserNotificationLists();
_getEvent();
_getPinnedEvent();
_checkUser();
_checkFcmToken();
_widgetIndex = widget.pageIndex;
_bIndex = widget.pageIndex;
_controller = ScrollController();
}
.
.
.
package com.example.event
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
class Application : FlutterApplication(), PluginRegistry.PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry?) {
GeneratedPluginRegistrant.registerWith(registry)
}
}
package com.example.event
import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.MethodChannel
import android.os.Build
import android.app.NotificationManager
import android.app.NotificationChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "example.com/channel"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getChannel") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val cid = getString(R.string.default_notification_channel_id)
val checkChannel = notificationManager.getNotificationChannel(cid)
if(checkChannel == null) {
// Create the NotificationChannel
val name = "default"
val importance = NotificationManager.IMPORTANCE_MAX
val mChannel = NotificationChannel(cid, name, importance)
mChannel.description = "default desc"
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
notificationManager.createNotificationChannel(mChannel)
result.success("registerd!")
}
else{
result.success("already registerd!")
}
}
} else {
result.notImplemented()
}
}
}
}
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.google.gms:google-services:4.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.1'
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.event"
minSdkVersion 21
targetSdkVersion 28
multiDexEnabled true
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.facebook.android:facebook-login:[5,6)'
implementation "com.google.firebase:firebase-messaging:20.1.0"
// implementation "com.google.firebase:firebase-analytics:17.2.1"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
apply plugin: 'com.google.gms.google-services' // Google Play services Gradle plugin
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.event">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<!--application - android:name="io.flutter.app.FlutterApplication" -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name=".Application"
android:label="EXAMPLE"
android:icon="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="AbcDeFgHiJKLMNopqrstuvwxyzdklE99dkkdfsdfs"/>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- facebook login -->
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
</application>
</manifest>




Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Mac OS X 10.14.6 18G2022, locale ko-KR)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.1)
[✓] Android Studio (version 3.5)
[✓] VS Code (version 1.41.1)
[✓] Connected device (1 available)
• No issues found!
same here.
getting the same error as well .
Same issue.
same issue.
same issue
i see the Application file:
override fun registerWith(registry: PluginRegistry?) {
GeneratedPluginRegistrant.registerWith(registry)
}
register a PluginRegistry type, but in file GeneratedPluginRegistrant, need "FlutterEngine" type
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
(is auto generated)
i see an error in this documentation plugin
I don't know how to solve it
possibly related to https://github.com/FirebaseExtended/flutterfire/issues/1763
I'm having the same issue, any solutions?
I have the same issue here, no solutions yet? :(
Edit:
I found this solution: https://stackoverflow.com/a/59490722
Instead of:
GeneratedPluginRegistrant.registerWith(registry);
Use:
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
My change was not just that. I used the entire class created by DomingoMG and it worked like a charm.
Most helpful comment
I have the same issue here, no solutions yet? :(
Edit:
I found this solution: https://stackoverflow.com/a/59490722
Instead of:
GeneratedPluginRegistrant.registerWith(registry);Use:
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));My change was not just that. I used the entire class created by DomingoMG and it worked like a charm.