Flutter应用后台/关闭时调用Android原生代码实现会话通知快捷方式问题
问题根本原因
- 最初将MethodChannel注册在MainActivity中,应用退后台/被杀后Activity销毁,对应的通道实例也随之销毁,自然无法响应调用。
- 你后续在Service中新建独立FlutterEngine注册通道的方案会出现
MissingPluginException,是因为Dart侧后台触发调用的isolate和Service中新建的FlutterEngine不属于同一个上下文,通道注册完全错位,同时你报错提到的saveBitmapAsCircle方法对应的通道没有在这个新的FlutterEngine中注册,自然找不到实现。
推荐解决方案(无需处理Flutter生命周期兼容,适配全场景)
你当前的核心诉求是收到推送后生成会话快捷方式并展示通知,完全可以绕过Dart调用原生的链路,直接在原生侧处理全部逻辑:
- 原生侧实现
FirebaseMessagingService子类,接管推送接收逻辑:
class MyFirebaseMessagingService : FirebaseMessagingService() { private val CHANNEL = "..." // 复用你之前的创建快捷方式逻辑 private fun createConversationShortcut(personName: String, personIcon: String): String { val person = Person.Builder() .setName(personName) .setIcon(IconCompat.createWithContentUri(personIcon)) .build() val shortcutId = personName.lowercase(Locale.ROOT).replace(" ", "_") + "_shortcut" val shortcut = ShortcutInfoCompat.Builder(this, shortcutId) .setLongLived() .setIntent(Intent(Intent.ACTION_VIEW)) .setPerson(person) .setShortLabel(personName) .build() ShortcutManagerCompat.addDynamicShortcuts(this, listOf(shortcut)) return shortcutId } override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) // 解析推送参数里的personName、personIcon、通知内容等字段 val personName = remoteMessage.data["personName"] ?: return val personIcon = remoteMessage.data["personIcon"] ?: return val notificationTitle = remoteMessage.data["title"] ?: return val notificationContent = remoteMessage.data["content"] ?: return // 生成shortcutId val shortcutId = createConversationShortcut(personName, personIcon) // 直接在原生侧构建带shortcutId的通知展示即可,无需传回Dart侧 // 其他通知配置和MessagingStyle配置也可以直接在原生侧写,调用NotificationManager展示通知即可 } }
- 不要忘记在
AndroidManifest.xml中注册这个服务:
<service android:name=".MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
该方案完全不依赖FlutterEngine的存活状态,应用退后台、被杀场景都可以正常运行。
备选方案:必须从Dart侧调用原生的处理方式
如果你的业务逻辑必须在Dart侧处理,再调用原生创建快捷方式,可以通过全局FlutterEngine实现:
- 自定义
Application类,初始化全局共用的FlutterEngine,统一注册所有MethodChannel:
class MyApp : Application() { lateinit var globalFlutterEngine: FlutterEngine private val CHANNEL = "..." override fun onCreate() { super.onCreate() // 初始化全局FlutterEngine globalFlutterEngine = FlutterEngine(this) globalFlutterEngine.dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) // 统一注册所有需要的MethodChannel,包括createConversationShortcut和saveBitmapAsCircle MethodChannel(globalFlutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when(call.method) { "createConversationShortcut" -> { val personName = call.argument<String>("personName") val personIcon = call.argument<String>("personIcon") if (personName != null && personIcon != null) { val shortcutId = createConversationShortcut(personName, personIcon) result.success(shortcutId) } else { result.error("argument-error", "Too few arguments", null) } } "saveBitmapAsCircle" -> { // 在这里实现对应的逻辑,不要只在MainActivity中注册 } else -> result.notImplemented() } } } private fun createConversationShortcut(personName: String, personIcon: String): String { // 复用之前的创建快捷方式逻辑 } }
- 在MainActivity中复用这个全局FlutterEngine,不要重复创建:
class MainActivity: FlutterActivity() { override fun provideFlutterEngine(context: Context): FlutterEngine { return (application as MyApp).globalFlutterEngine } }
- 不需要再单独在Service中注册通道,所有调用都会走全局FlutterEngine的通道,不会再出现找不到实现的问题。
内容的提问来源于stack exchange,提问作者arzi89
相关产品推荐
相关产品推荐

