Flutterfire: [firebase_messaging] Need Kotlin documentation and example

Created on 6 Apr 2020  路  28Comments  路  Source: FirebaseExtended/flutterfire

Describe the bug
At https://pub.dev/packages/firebase_messaging step 6 of backgrond messaging talks about MainActivity.java but it does not exist for my Flutter project.
image

Looks like a lot of others have this issue https://stackoverflow.com/questions/59225943/flutter-project-mainactivity-java-is-missing

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. '...'
  3. See error or incorrect behavior

Expected behavior
A clear and concise description of what you expected to happen.

Additional context
Add any other context about the problem here.

crowd android messaging documentation

Most helpful comment

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.

Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

All 28 comments

Hi @giorgio79
Your project has Kotlin instead of Java . You can implement MainActivity.kt from this answer

or you can create Flutter project with java support an follow the steps to implement firebase_messaging

Closing, as this isn't an issue with firebase_messaging itself,
if you disagree please write in the comments and I will reopen it
Thank you

Thanks Taha. Perhaps the documentaiton could be improved at https://pub.dev/packages/firebase_messaging
I assume the kotlin based projects will prevail over pure Java, as Flutter rocks.

Hi @giorgio79
Yes, it should be updated

PS, it is also unclear whether we should paste the stuff after what is in MainActivity.kt or overwrite what is in there? For now, I just pasted after what was in there...

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
//https://stackoverflow.com/questions/59984162/firebase-messaging-handle-background-message-in-kotlin/60634673#60634673
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

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


class Application : FlutterApplication(), PluginRegistrantCallback {
    fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

    fun registerWith(registry: PluginRegistry?) {
        GeneratedPluginRegistrant.registerWith(registry)
    }
}

Ok, I think the Google team needs to do a better job. I am unsuccessful so far in updating my main Kotlin file, getting errors like this based on the linked stackoverflow kotlin example... The imports are also totally different from the default kotlin file provided out of the box...

package me.exampleapp

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
//https://stackoverflow.com/questions/59984162/firebase-messaging-handle-background-message-in-kotlin/60634673#60634673
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService


class Application : FlutterApplication(), PluginRegistrantCallback {
    fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

    fun registerWith(registry: PluginRegistry?) {
        GeneratedPluginRegistrant.registerWith(registry)
    }
}

Launching lib\main.dart on Pixel 2 in debug mode...
Running Gradle task 'assembleDebug'...
C:\AndroidStudioProjects\exampleapp\android\app\src\main\kotlin\me\exampleapp\MainActivity.kt: (15, 9): 'onCreate' hides member of supertype 'FlutterApplication' and needs 'override' modifier
C:\AndroidStudioProjects\exampleapp\android\app\src\main\kotlin\me\exampleapp\MainActivity.kt: (20, 9): 'registerWith' hides member of supertype 'PluginRegistrantCallback' and needs 'override' modifier
C:\AndroidStudioProjects\exampleapp\android\app\src\main\kotlin\me\exampleapp\MainActivity.kt: (21, 48): Type mismatch: inferred type is PluginRegistry? but FlutterEngine was expected

FAILURE: Build failed with an exception.

Lol I am finding so many issues around this and the plugin page has no up to date documentation ... WTF Simple carelessness...

https://github.com/FirebaseExtended/flutterfire/issues/1684
https://github.com/FirebaseExtended/flutterfire/issues/1613

Thanks Taha! Looking forward to a working Kotlin / Flutter example. The example linked from firebase_messaging pub dart page is 3 years old and Java based... https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging/example

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.

Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.

Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

Yes, It works! Thank You

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.

Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

Can you share everything you've done?
Did you remove your MainActivity file? Did you update your AndroidManifest.xml android:name?

You have to update the AndroidManifest.xml as well.

-        android:name="io.flutter.app.FlutterApplication"
+        android:name=".Application"

and add:

            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

inside the <activity tag.

You have to update the AndroidManifest.xml as well.

-        android:name="io.flutter.app.FlutterApplication"
+        android:name=".Application"

and add:

            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

inside the <activity tag.

Is there more of your implementation you can share? Like a spoonfeeding of information?

How did you declare your myBackgroundMessageHandler function?

What are you using for MainActivity.kt?

What are you using for Application.kt?

What does your AndroidManifest have in it?
Does the package name at the top match what's in google-services.json? Does it match what's in the MainActivity.kt?

What version of the actual plugin are yo using in pubspec?

What version of the android/app/build.gradle dependency are you using?
Ex: implementation "com.google.firebase:firebase-messaging:XXXX

My mind is blown by this plugin. None of it makes sense, thanks in advance.

@bretie you need to follow the pub.dev documentation https://pub.dev/packages/firebase_messaging

The only thing that change from that for flutter kotlin projects is the code below the step that says:

_2. Add an Application.java class to your app in the same directory as your MainActivity.java. This is typically found in /android/app/src/main/java//._

If the proccess is too complicated you can search for a youtube video

@bretie you need to follow the pub.dev documentation https://pub.dev/packages/firebase_messaging

The only thing that change from that for flutter kotlin projects is the code below the step that says:

_2. Add an Application.java class to your app in the same directory as your MainActivity.java. This is typically found in /android/app/src/main/java//._

If the proccess is too complicated you can search for a youtube video

I can assure you it's not too complicated. When it comes to background messages using this plug it tends to be inconsistent compatibility. It requires unique steps for every other person that aren't documented. Hence, me asking for your full implementation.

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.

Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

I' ve spend around 2 hours to find fix for this. Thanks a lot. You saved me.

@giorgio79 Did you find a solution yet for this ?

Update: based in another plugin that I'm using in another app, I'm ussing this code for handle background message in kotlin... I don't know is better than stackoverflow answer, but works.
Application.kt

package your.app.package

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

I' ve spend around 2 hours to find fix for this. Thanks a lot. You saved me.

Buddy, you saved my day.

@giorgio79 , I struggled with this for many hours. Even the above solutions didn't work for me. Finally found a way solve this. Here is how I managed to fix this.

  1. Change AndroidManifest.xml name properties as below.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app">
    <application
        android:name=".Application">
           <activity
            android:name=".MainActivity">
           </activity>
    </application>
</manifest>
  1. Empty MainActivity.kt file as below.
package com.example.app

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {}
  1. Add FirebaseCloudMessagingPluginRegistrant.kt file in same directory.
package com.example.app

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

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

    private fun alreadyRegisteredWith(registry: PluginRegistry?): Boolean {
        val key: String? = FirebaseCloudMessagingPluginRegistrant::class.java.canonicalName
        if (registry?.hasPlugin(key)!!) {
            return true
        }
        registry.registrarFor(key)
        return false
    }
}
  1. Add Application.kt file in same directory.
package com.example.app

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

class Application : FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

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

You have to update the AndroidManifest.xml as well.

-        android:name="io.flutter.app.FlutterApplication"
+        android:name=".Application"

and add:

            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

inside the <activity tag.

thanks a lot @hectorAguero and @hpadrao ,
i misstype changing android:name --> .Application inside activity instead of android:name inside application tag.

Totally lost with Kotlin implementation. This issue has been open for 5 months. We need an immediate solution.

@giorgio79 , I struggled with this for many hours. Even the above solutions didn't work for me. Finally found a way solve this. Here is how I managed to fix this.

  1. Change AndroidManifest.xml name properties as below.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app">
    <application
        android:name=".Application">
           <activity
            android:name=".MainActivity">
           </activity>
    </application>
</manifest>
  1. Empty MainActivity.kt file as below.
package com.example.app

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {}
  1. Add FirebaseCloudMessagingPluginRegistrant.kt file in same directory.
package com.example.app

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

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

    private fun alreadyRegisteredWith(registry: PluginRegistry?): Boolean {
        val key: String? = FirebaseCloudMessagingPluginRegistrant::class.java.canonicalName
        if (registry?.hasPlugin(key)!!) {
            return true
        }
        registry.registrarFor(key)
        return false
    }
}
  1. Add Application.kt file in same directory.
package com.example.app

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

class Application : FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

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

Esta es la solucion al problema. A mi me funcion perfectamente. No me habia dado cuenta que no tenia los archivos en un mismo directorio. Espero que esto le sirva a otras personas.

This took me a while to figure out but here is a working solution:

You'll need two files in the SAME directory as your MainActivity.kt. The two files:

MainActivity.kt

This file will stay the same.

package com.example.app

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}

Application.kt

package com.example.app

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

class Application : FlutterApplication(), PluginRegistrantCallback {

    override fun onCreate() {
        super.onCreate()
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
        FlutterMain.startInitialization(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
        if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging")) {
            FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        }
    }
}

You then need to update your AndroidManifest.xml to point at these two files. You do this like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app">
    <!-- 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"
         -->
    <application
        android:name=".Application"
        android:label="example"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"

So, you've essentially replaced the application file and kept the main activity the same.

Don't forget

You need to drop this in the AndroidManifest.xml file as well within the activity tags.

<intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

No Application.kt any more.

I follow this doc and it works fine.
https://firebase.flutter.dev/docs/messaging/overview

firebase_core: ^0.5.1
firebase_messaging: ^8.0.0-dev.5

ps. I am using Flutter Android Embedding V2

Hope this helps.

I also moved my app from Kotlin to Java. Kotlin first development is a lie and we shouldn't rely on fancy announcements.

Deprecated doc killing many apps including mine. There r many solutions but I don't know which one should be final. Plz consider to update the doc

didnt read a lot of these posts, but i managed to get push working on an emulator, running a flutter build.

the main thing u gotta use is PlatformChannel, to call a method written in kt/java files from the flutter widget or flutter file.
u gotta setup the channel on both sides of the code, so flutter calls method using PlatformChannel and kotlin/java recieves the call.

i succesfully got a push message from the console on a flutter app.

the instructions provided online are OK but somewhat confusing with all the classes (somewhat bulky) u gotta use, especially if ure not experienced.

i have found the solution for this problem
first you have to create 2 files in the same directory of MainActivity.kt:
1- Application.kt:

` package

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(), PluginRegistrantCallback {

override fun onCreate() {
    super.onCreate()
    FlutterFirebaseMessagingService.setPluginRegistrant(this);
}

override fun registerWith(registry: PluginRegistry?) {
    io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
}

} `

``2- create FirebaseCloudMessagingPluginRegistrant.kt: package

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

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

private fun alreadyRegisteredWith(registry: PluginRegistry?): Boolean {
    val key: String? = FirebaseCloudMessagingPluginRegistrant::class.java.canonicalName
    if (registry?.hasPlugin(key)!!) {
        return true
    }
    registry.registrarFor(key)
    return false
}

}`

3- then modify MainActivity.kt to look like:
`package

import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}
`

4- reference MainActivity.kt and Application.kt in Androidmainfest.xml file:
a- <application android:name="com.blablabla.Application"
b-<activity android:name="com.blablabla.MainActivity"

Was this page helpful?
0 / 5 - 0 ratings