Closed
Description
Bug Description
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.
To Reproduce
Steps to reproduce the behavior:
- Define TOP-LEVEL or STATIC background handler method
myBackgroundMessageHandler
- Config
myBackgroundMessageHandler
asonBackgroundMessage
inside the_firebaseMessaging.configure()
- Run
- It throws exception when the process dive into the
_firebaseMessaging.configure()
- When I remove
onBackgroundMessage
as comment, it runs normally.
My codes
homePage.dart
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();
}
.
.
.
Application.kt
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)
}
}
MainActivity.kt
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()
}
}
}
}
android/build.gradle
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
}
android/app/build.gradle
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
AndroidManifest.xml
<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>
Exception Details
homePage.dart
firebase_messaging.dart
platform_channel.dart
message_codecs.dart
Development Env
flutter doctor
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!