如何使用 FCM 插件正确注册插件
Posted
技术标签:
【中文标题】如何使用 FCM 插件正确注册插件【英文标题】:How do I correctly register a plugin with the FCM plugin 【发布时间】:2020-10-30 09:40:55 【问题描述】:我正在使用https://pub.dev/packages/firebase_messaging v6.0.16 和颤振 v1.17.5
[√] Flutter (Channel stable, v1.17.5, on Microsoft Windows [Version 10.0.18362.900], locale en-US)
[√] android toolchain - develop for Android devices (Android SDK version 29.0.3)
[√] Android Studio (version 4.0)
[√] VS Code (version 1.47.0)
我正在尝试在 myBackgroundMessageHandler 中调用 AppAvailability.launchApp('com.companyname.appname');
处的插件
class CloudMessagingService extends NotificationService
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
void configure()
if (Platform.isios) _firebaseMessaging.requestNotificationPermissions(IosNotificationSettings());
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async
if (isDataNotification(message)) return;
print('onMessage');
,
onLaunch: (Map<String, dynamic> message) async
if (isDataNotification(message)) return;
print('onLaunch');
,
onResume: (Map<String, dynamic> message) async
if (isDataNotification(message)) return;
print('onResume');
,
onBackgroundMessage: myBackgroundMessageHandler,
);
static Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) async
print('on background message');
AppAvailability.launchApp('com.companyname.appname'); // it will throw an error when it tries to call the method channel in the app availability plugin
return message;
但我收到以下错误
E/flutter (28000): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method launchApp on channel com.pichillilorenzo/flutter_appavailability)
E/flutter (28000): #0 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:154
E/flutter (28000): <asynchronous suspension>
E/flutter (28000): #1 MethodChannel.invokeMethod
package:flutter/…/services/platform_channel.dart:329
E/flutter (28000): #2 AppAvailability.launchApp
package:flutter_appavailability/flutter_appavailability.dart:95
E/flutter (28000): #3 CloudMessagingService.myBackgroundMessageHandler
package:moto_picto/…/firebase/cloud_messaging_service.dart:43
E/flutter (28000): #4 _fcmSetupBackgroundChannel.<anonymous closure>
package:firebase_messaging/firebase_messaging.dart:38
E/flutter (28000): #5 MethodChannel._handleAsMethodCall
package:flutter/…/services/platform_channel.dart:409
E/flutter (28000): #6 MethodChannel.setMethodCallHandler.<anonymous closure>
package:flutter/…/services/platform_channel.dart:377
E/flutter (28000): #7 _DefaultBinaryMessenger.handlePlatformMessage
package:flutter/…/services/binding.dart:199
E/flutter (28000): #8 _invoke3.<anonymous closure> (dart:ui/hooks.dart:290:15)
E/flutter (28000): #9 _rootRun (dart:async/zone.dart:1184:13)
E/flutter (28000): #10 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (28000): #11 _CustomZone.runGuarded (dart:async/zone.dart:979:7)
E/flutter (28000): #12 _invoke3 (dart:ui/hooks.dart:289:10)
E/flutter (28000): #13 _dispatchPlatformMessage (dart:ui/hooks.dart:164:5)
插件在应用程序范围内没有任何问题。我尝试的每个插件都会发生这种情况!
所以我认为问题在于,根据我在这篇文章中的理解,FCM 所做的隔离没有被颤振引擎包裹。
https://github.com/flutter/flutter/issues/13937#issuecomment-656239596
但您需要创建一个自定义的应用程序类,该类挂钩到 插件后台 FlutterNativeView 的初始化。
我确实按照说明将我的 Application.kt 更改为以下内容
package com.companyname.appname
import `in`.jvapps.system_alert_window.SystemAlertWindowPlugin
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
import io.flutter.view.FlutterMain
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin
import android.os.Build
import android.app.NotificationManager
import android.app.NotificationChannel
public class Application: FlutterApplication(), PluginRegistrantCallback
override fun onCreate()
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
createNotificationChannels();
SystemAlertWindowPlugin.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"));
if (!registry!!.hasPlugin("in.jvapps.system_alert_window"))
SystemAlertWindowPlugin.registerWith(registry!!.registrarFor("in.jvapps.system_alert_window"));
fun createNotificationChannels()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
val name = "groupChannel";
val descriptionText = "This is the group channel";
val importance = NotificationManager.IMPORTANCE_HIGH;
val mChannel = NotificationChannel("59054", name, importance);
mChannel.description = descriptionText;
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager;
notificationManager.createNotificationChannel(mChannel);
还有我的 MainActivity.kt
package com.companyname.appname
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);
还有我的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.companyname.appname">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE " />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 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=".Application"
android:label="App Name"
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>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
</application>
</manifest>
通知似乎正确显示为抬头通知,我可以调用我的 BackgroundMessageHandler 并执行代码,只是我无法对 myBackgroundMessageHandler 中的任何插件执行任何操作。我正确实施了吗?
它总是会在myBackgroundMessageHandler
中的AppAvailability.launchApp('com.companyname.appname');
这一行抛出错误,因为如果插件未注册,则隔离无法调用方法通道。
我还查看了这篇 github 帖子
Similar problem
但我的 Application.kt 是这样设置的
我尝试做flutter clean -> 卸载应用程序-> 安装应用程序。问题仍然存在。就像他们在这里描述的那样
MissingPluginException(No implementation found for method show on channel dexterous.com/flutter/local_notifications)
编辑:当我使用 DeviceApp 插件时,也会发生同样的事情。我换了
AppAvailability.launchApp('com.companyname.appname');
与
DeviceApps.openApp('com.companyname.appname');
于是我在Application.kt的registerWith方法中添加了以下2行,似乎是围绕着缺少插件异常
if (!registry!!.hasPlugin("fr.g123k.deviceapps"))
DeviceAppsPlugin.registerWith(registry!!.registrarFor("fr.g123k.deviceapps"));
但错误变为
E/flutter (25583): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'android.content.pm.PackageManager android.app.Activity.getPackageManager()' on a null object reference, null)
E/flutter (25583): #0 StandardMethodCodec.decodeEnvelope
package:flutter/…/services/message_codecs.dart:569
E/flutter (25583): #1 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:156
E/flutter (25583): <asynchronous suspension>
E/flutter (25583): #2 MethodChannel.invokeMethod
package:flutter/…/services/platform_channel.dart:329
E/flutter (25583): #3 DeviceApps.openApp
package:device_apps/device_apps.dart:81
E/flutter (25583): #4 CloudMessagingService.myBackgroundMessageHandler
package:moto_picto/…/firebase/cloud_messaging_service.dart:73
E/flutter (25583): #5 _fcmSetupBackgroundChannel.<anonymous closure>
package:firebase_messaging/firebase_messaging.dart:38
E/flutter (25583): #6 MethodChannel._handleAsMethodCall
package:flutter/…/services/platform_channel.dart:409
E/flutter (25583): #7 MethodChannel.setMethodCallHandler.<anonymous closure>
package:flutter/…/services/platform_channel.dart:377
E/flutter (25583): #8 _DefaultBinaryMessenger.handlePlatformMessage
package:flutter/…/services/binding.dart:199
E/flutter (25583): #9 _invoke3.<anonymous closure> (dart:ui/hooks.dart:290:15)
E/flutter (25583): #10 _rootRun (dart:async/zone.dart:1184:13)
E/flutter (25583): #11 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (25583): #12 _CustomZone.runGuarded (dart:async/zone.dart:979:7)
E/flutter (25583): #13 _invoke3 (dart:ui/hooks.dart:289:10)
E/flutter (25583): #14 _dispatchPlatformMessage (dart:ui/hooks.dart:164:5)
所以现在它不再说插件丢失,而是说PlatformException(error, Attempt to invoke virtual method 'android.content.pm.PackageManager android.app.Activity.getPackageManager()
编辑 2:
我刚刚注意到最新的错误https://github.com/g123k/flutter_plugin_device_apps/issues/31 可能是插件本身之一。去看看现在不同的插件是否可以工作
我希望我提供了足够的信息,如果需要更多信息或问题是否需要更改,请告诉我。我可以在几分钟内回复。
【问题讨论】:
【参考方案1】:原来它只是我第一次编辑后的插件!刚刚使用共享偏好进行了尝试,它可以工作!
MY_PACKAGE_NAME
import `in`.jvapps.system_alert_window.SystemAlertWindowPlugin
import fr.g123k.deviceapps.DeviceAppsPlugin
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
import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin
import android.os.Build
import android.app.NotificationManager
import android.app.NotificationChannel
public class Application: FlutterApplication(), PluginRegistrantCallback
override fun onCreate()
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
SystemAlertWindowPlugin.setPluginRegistrant(this);
createNotificationChannels();
FlutterMain.startInitialization(this);
override fun registerWith(registry: PluginRegistry?)
if (!registry!!.hasPlugin("io.flutter.plugins.firebasemessaging"))
FirebaseMessagingPlugin.registerWith(registry!!.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
if (!registry!!.hasPlugin("in.jvapps.system_alert_window"))
SystemAlertWindowPlugin.registerWith(registry!!.registrarFor("in.jvapps.system_alert_window"));
if (!registry!!.hasPlugin("plugins.flutter.io.shared_preferences"))
SharedPreferencesPlugin.registerWith(registry!!.registrarFor("plugins.flutter.io.shared_preferences"));
fun createNotificationChannels()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
val name = "groupChannel";
val descriptionText = "This is the group channel";
val importance = NotificationManager.IMPORTANCE_HIGH;
val mChannel = NotificationChannel("59054", name, importance);
mChannel.description = descriptionText;
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager;
notificationManager.createNotificationChannel(mChannel);
【讨论】:
以上是关于如何使用 FCM 插件正确注册插件的主要内容,如果未能解决你的问题,请参考以下文章
如何正确全局注册和使用 Vue Rangedate Picker 组件?
如何使用 Nuxt.js 实现 Firebase 云消息传递 (FCM)