Skip to content

咨询关于1.2.2版本 #20

Closed
Closed

Description

@zhujianguo

首先感谢您好的迅速修复和反馈!!!🙏
我有一个小疑问:
使用1.2.2版本,在这个之前我需要手动去修改我工程的build文件
// ── native_workmanager 1.2.1:修复 applyMiddleware StackOverflow ──
// Enqueue.kt 使用 NativeWorkmanagerPlugin.applyMiddleware(...) 会绑定到
// NativeWorkmanagerPlugin+Middleware.kt 里 Companion 扩展;其函数体写成
// applyMiddleware(...) 时 Kotlin 会再次解析为同一扩展,导致无限递归。
// 与同包 CommandProcessor / ChainHelper 一致,改为调用顶层 internal applyMiddleware。
tasks.register('patchNativeWorkmanagerEnqueueApplyMiddleware') {
group = 'build'
description = 'Patches native_workmanager Enqueue.kt to avoid applyMiddleware StackOverflow (v1.2.1).'
doLast {
def flutterProjectDir = rootProject.projectDir.parentFile
def depsFile = new File(flutterProjectDir, '.flutter-plugins-dependencies')
if (!depsFile.exists()) {
logger.warn('patchNativeWorkmanager: .flutter-plugins-dependencies missing, skip.')
return
}
def parsed = new groovy.json.JsonSlurper().parse(depsFile)
String pluginPath = null
parsed.plugins?.android?.each { p ->
if (p.name == 'native_workmanager') {
pluginPath = p.path as String
}
}
if (pluginPath == null) {
logger.warn('patchNativeWorkmanager: native_workmanager not in plugin list, skip.')
return
}
def enqueueKt = new File(
pluginPath,
'android/src/main/kotlin/dev/brewkits/native_workmanager/NativeWorkmanagerPlugin+Enqueue.kt')
if (!enqueueKt.exists()) {
logger.warn("patchNativeWorkmanager: not found: ${enqueueKt}")
return
}
def text = enqueueKt.getText('UTF-8')
def buggy = 'NativeWorkmanagerPlugin.applyMiddleware(context, workerClassName, inputJson)'
def fixed = 'applyMiddleware(context, workerClassName, inputJson)'
if (text.contains(buggy)) {
enqueueKt.write(text.replace(buggy, fixed), 'UTF-8')
logger.lifecycle('patchNativeWorkmanager: updated NativeWorkmanagerPlugin+Enqueue.kt')
} else if (text.contains(fixed)) {
logger.lifecycle('patchNativeWorkmanager: Enqueue.kt already OK')
} else {
logger.warn('patchNativeWorkmanager: expected call not found (plugin version changed?)')
}
}
}

// DartWorker 头less 引擎默认不注册任何 Flutter 插件;仅为调试任务注册
// flutter_local_notifications,使 Dart 侧 plugin.show 可用(不启用全量 GeneratedPluginRegistrant,避免 BLE 等副作用)。
tasks.register('patchNativeWorkmanagerFlutterEngineLocalNotifications') {
group = 'build'
description = 'Patches native_workmanager FlutterEngineManager + build.gradle for FLN on worker engine.'
doLast {
def flutterProjectDir = rootProject.projectDir.parentFile
def depsFile = new File(flutterProjectDir, '.flutter-plugins-dependencies')
if (!depsFile.exists()) {
logger.warn('patchNativeWorkmanagerFLN: .flutter-plugins-dependencies missing, skip.')
return
}
def parsed = new groovy.json.JsonSlurper().parse(depsFile)
String pluginPath = null
parsed.plugins?.android?.each { p ->
if (p.name == 'native_workmanager') {
pluginPath = p.path as String
}
}
if (pluginPath == null) {
logger.warn('patchNativeWorkmanagerFLN: native_workmanager not found, skip.')
return
}

    def nwGradle = new File(pluginPath, 'android/build.gradle')
    if (nwGradle.exists() && !nwGradle.text.contains('UREVO_FLN_WORKER_ENGINE_DEPS')) {
        nwGradle.append('''

// UREVO_FLN_WORKER_ENGINE_DEPS (app/build.gradle 补丁): DartWorker 引擎注册 FLN 所需
dependencies {
implementation project(':flutter_local_notifications')
}
''')
logger.lifecycle('patchNativeWorkmanagerFLN: appended FLN dependency to native_workmanager/android/build.gradle')
}

    def engineKt = new File(
            pluginPath,
            'android/src/main/kotlin/dev/brewkits/native_workmanager/engine/FlutterEngineManager.kt')
    if (!engineKt.exists()) {
        logger.warn("patchNativeWorkmanagerFLN: not found: ${engineKt}")
        return
    }
    def kt = engineKt.getText('UTF-8')
    if (kt.contains('UREVO: FlutterLocalNotificationsPlugin registered on worker engine')) {
        logger.lifecycle('patchNativeWorkmanagerFLN: FlutterEngineManager.kt already patched')
        return
    }
    def anchor = '''            )

        // Destroy the engine on any init failure so we don't leak'''
    if (!kt.contains(anchor)) {
        logger.warn('patchNativeWorkmanagerFLN: FlutterEngineManager anchor not found (plugin version changed?)')
        return
    }
    def insert = '''            )

        // UREVO: 仅注册 flutter_local_notifications,供 DartWorker 内本地通知(避免全量插件注册)。
        try {
            flutterEngine.getPlugins().add(
                com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin()
            )
            NativeLogger.d("UREVO: FlutterLocalNotificationsPlugin registered on worker engine")
        } catch (e: Exception) {
            NativeLogger.e("UREVO: FlutterLocalNotificationsPlugin register failed", e)
        }

        // Destroy the engine on any init failure so we don't leak'''
    engineKt.write(kt.replace(anchor, insert), 'UTF-8')
    logger.lifecycle('patchNativeWorkmanagerFLN: patched FlutterEngineManager.kt')
}

}

afterEvaluate {
tasks.named('preBuild').configure {
dependsOn(
'patchNativeWorkmanagerEnqueueApplyMiddleware',
'patchNativeWorkmanagerFlutterEngineLocalNotifications',
)
}
}
才能解决之前反馈的这两个问题
#17
#18

=============================================

我刚更新了最新版本1.2.2之后,去掉这段代码,
首先https://github.com/brewkits/native_workmanager/issues/17这个问题得到了解决
其次https://github.com/brewkits/native_workmanager/issues/18我没有按照去自注册插件

Image 我的后台任务中的通知和读取Google health的数据也能正常触发。 而且我在触发后台任务时,我前台通过蓝牙连接设备也没有触发断开了。 这个是我收到的奇怪的表现,但是我很喜欢这个表现。只是有点不明白你们做了什么调整。 1、首先第一蓝牙不断开,是因为我默认设置的是registerPlugins: false。 2、但是我没有自注册flutter的通知组件,按你所说,理论是不会触发,结果我得到的是会触发通知,我也没注册Google health的插件,它也能正常去读取到数据。这是表现让我很意外,但是是我想要的结果。 以下是我的核心代码: /// 在 `main` 里于 [WidgetsFlutterBinding.ensureInitialized] 之后调用一次即可。 /// /// **Android**:使用 [DartWorker] 且需在进程被杀后仍能执行时,宿主还需完成 /// [native_workmanager Android 配置](https://github.com/brewkits/native_workmanager/blob/main/doc/ANDROID_SETUP.md) ///(自定义 `Application` + `Configuration.Provider`、移除默认 WorkManager 初始化等)。 /// 主工程 `urevo_flutter` 已接入 `UrevoApplication` 与清单项。 Future initializeDebugPageNativeWorkmanager() { return NativeWorkManager.initialize( dartWorkers: { kDebugPageNativeWorkmanagerCallbackId: debugPageNativeWorkmanagerNotifyTask, }, ); }

==========================

import android.app.Application
import android.content.Context
import androidx.work.Configuration
import androidx.work.DelegatingWorkerFactory
import dev.brewkits.kmpworkmanager.background.data.KmpWorkerFactory
import dev.brewkits.native_workmanager.SimpleAndroidWorkerFactory
import dev.brewkits.native_workmanager.engine.FlutterEngineManager

/**

  • 为 native_workmanager 的 DartWorker

  • 提供进程被杀死后 WorkManager 拉起时的 [Configuration.Provider] 与 callback handle 恢复。

  • 参见官方文档:

  • ANDROID_SETUP.md — Killed-App Support for Dart Workers
    */
    class UrevoApplication : Application(), Configuration.Provider {

    override fun onCreate() {
    super.onCreate()

     val handle = getSharedPreferences(
         "dev.brewkits.native_workmanager",
         Context.MODE_PRIVATE,
     ).getLong("callback_handle", -1L)
    
     if (handle != -1L) {
         FlutterEngineManager.setCallbackHandle(handle)
     }
    

    }

    override val workManagerConfiguration: Configuration
    get() {
    val factory = DelegatingWorkerFactory().apply {
    addFactory(KmpWorkerFactory(SimpleAndroidWorkerFactory(this@UrevoApplication)))
    }
    return Configuration.Builder()
    .setWorkerFactory(factory)
    .build()
    }
    }

==========================================

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.polidea.rxandroidble2.exceptions.BleException;
import com.ryanheise.audioservice.AudioServiceActivity;
import com.ryanheise.audioservice.AudioServiceFragmentActivity;

import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import io.reactivex.exceptions.UndeliverableException;
import io.reactivex.plugins.RxJavaPlugins;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import io.flutter.embedding.android.FlutterActivity;

import android.net.Uri;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.plugins.RxJavaPlugins;

public class MainActivity extends AudioServiceFragmentActivity {
private static final String BLUETOOTH_SERVICE_CHANNEL = "com.xxx.app/bluetooth_service";
private MethodChannel methodChannel;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    RxJavaPlugins.setErrorHandler(throwable -> {
        if (throwable instanceof UndeliverableException && throwable.getCause() instanceof BleException) {
            Log.v("SampleApplication", "Suppressed UndeliverableException: " + throwable);
            return; // ignore BleExceptions as they were surely delivered at least once
        }
        // add other custom handlers if needed
        throw new RuntimeException("Unexpected Throwable in RxJavaPlugins error handler", throwable);
    });
}

@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    
    // 创建MethodChannel用于Flutter与原生通信
    methodChannel = new MethodChannel(
        flutterEngine.getDartExecutor().getBinaryMessenger(),
        BLUETOOTH_SERVICE_CHANNEL
    );
    
    methodChannel.setMethodCallHandler((call, result) -> {
        switch (call.method) {
            case "startForegroundService":
                // 从Flutter获取自定义通知文本
                String notificationText = call.argument("notificationText");
                BluetoothForegroundService.startService(this, notificationText);
                result.success(true);
                break;
            case "stopForegroundService":
                BluetoothForegroundService.stopService(this);
                result.success(true);
                break;
            default:
                result.notImplemented();
                break;
        }
    });
}

}

========================

至于android/app/build.gradle文件,最上面添加的代码,我也删除了,就是为了测1.2.2是否修复了,结果得出上面的表现
期待你的反馈!!!谢谢🙏🙏

Activity

  1. vietnguyentuan2019 commented on Apr 21, 2026

    @vietnguyentuan2019
    Contributor

    Hi @zhujianguo, thank you for upgrading to version 1.2.2 and confirming that the StackOverflowError is fixed!
    你好 @zhujianguo,感谢你升级到 1.2.2 版本并确认 StackOverflowError 问题已修复!

    To answer your question about why flutter_local_notifications and Google Health still work perfectly in the background even though you removed the manual registration and kept registerPlugins: false:
    关于你的疑问:为什么在移除手动注册代码并保持 registerPlugins: false 的情况下,flutter_local_notifications 和 Google Health 依然能在后台正常工作?原因如下:

    1. Why Bluetooth no longer disconnects / 为什么蓝牙不再断开连接:
    This is the exact purpose of registerPlugins: false!
    这正是 registerPlugins: false 的核心作用!
    Previously, the background engine automatically registered all plugins. When the background task finished, the engine was destroyed, triggering onDetachedFromEngine on the Bluetooth plugin, which killed your active foreground connection.
    以前,后台引擎会自动注册所有插件。当后台任务结束、引擎被销毁时,会触发蓝牙插件的 onDetachedFromEngine 清理逻辑,从而强制断开了你前台的蓝牙连接。
    By NOT registering it in the background, your foreground connection remains completely safe.
    现在不在后台注册它,你的前台连接就完全安全了。

    2. Why Notifications and Health still work / 为什么通知和 Health 依然可用:
    Plugins like flutter_local_notifications communicate directly with Android System Services (like NotificationManager).
    像 flutter_local_notifications 这样的插件主要直接与 Android 系统服务(如 NotificationManager)交互。
    Since your main app (foreground) has already set up the permissions and notification channels, the background DartWorker can simply send a signal to the Android OS to display the notification.
    因为你的主应用(前台)已经配置好了权限和通知渠道,后台的 DartWorker 只需要向 Android 系统发送一个显示通知的指令即可。
    It doesn't strictly need the full plugin lifecycle (attach/detach) in the background engine just to trigger a notification or make a simple one-off data read (like Health).
    它并不绝对需要在后台引擎中经历完整的插件生命周期(绑定/解绑)才能触发通知或进行简单的数据读取(如 Health)。

    3. When you MIGHT need to register them / 什么时候你“可能”需要注册它:
    You only need to set registerPlugins: true (or manually register specific plugins) if you encounter a MissingPluginException in the background, or if you specifically need to handle complex background callbacks.
    只有当你在后台遇到 MissingPluginException 报错,或者你需要处理复杂的后台回调时,你才需要开启 registerPlugins: true 或手动注册特定插件。

    In short, your current setup is highly optimized and working exactly as intended! You are successfully utilizing the "Zero-Engine I/O" philosophy.
    简而言之,你目前的配置非常优化,且完全符合设计预期!你成功利用了我们“Zero-Engine I/O”(零引擎 I/O)的理念。

    Let us know if you have any other questions.
    如果还有其他问题,欢迎随时反馈!

  2. zhujianguo commented on Apr 21, 2026

    @zhujianguo
    Author

    你好@zhujianguo感谢您升级到 1.2.2 版本并确认问题 已StackOverflowError修复!@zhujianguo,感谢您升级到1.2.2版本并确认StackOverflowError问题已修复!

    要回答您的问题,flutter_local_notifications即使您删除了手动注册并保留,为什么 Google Health 仍然在后台完美工作registerPlugins: false: 关于您的疑问:为什么在删除手动注册代码并保留registerPlugins: false的情况下,并且flutter_local_notificationsGoogle Health 仍能在后台正常工作?原因如下:

    1.为什么蓝牙不再断开 /为什么蓝牙不再断开连接: 这就是确切的目的registerPlugins: false! 这才是registerPlugins: false核心作用! 之前,后台引擎会自动注册所有插件。当后台任务完成时,引擎被销毁,触发onDetachedFromEngine蓝牙插件,从而杀死了你活跃的前台连接。 之前,后台引擎会自动注册插件。当后台任务结束、引擎被触发连接时,会触发蓝牙插件的onDetachedFromEngine清理逻辑,从而强制破坏了你前台的所有蓝牙。 通过不在后台注册它,你的前台连接仍然是完全安全的。 现在不在后台注册它,你的前台连接就完全安全了。

    2. 为什么通知和健康仍然有效 / 为什么通知和健康仍然可用: 像这样的 插件主要flutter_local_notifications直接与 Android 系统服务(如)交互。NotificationManager由于 你的主应用(前台)已经设置了权限和通知通道,后台只需向 Android 操作系统发送信号即可显示通知。 因为你的主应用(前台)已经配置好权限和通知渠道,后台的只需要向 Android 系统发送一个显示通知的指令即可 。并不严格需要后台引擎中的完整插件生命周期(附加/分离)只是为了触发通知或进行简单的一次性数据读取(如健康)。 它并不绝对需要在后台引擎中经历插件生命周期(绑定/解绑)才能触发通知或进行简单的数据完整读取(如健康)。flutter_local_notifications``NotificationManager``DartWorker``DartWorker

    **3. 当你可能需要注册它们时/什么时候你“可能”需要注册它:**如果你在后台遇到,或者你特别需要处理复杂的后台回调, 你只需要设置(或手动注册特定的插件)。 只有当你在后台遇到报错,或者你需要处理复杂的后台回调时,你才需要开启或手动注册特定的。registerPlugins: true``MissingPluginException``MissingPluginException``registerPlugins: true

    简而言之,您当前的设置经过高度优化,并且完全按照预期工作!您成功地利用了“零引擎 I/O”的理念。 简而言之,您目前的配置非常优化,且完全符合设计预期!您成功地利用了我们“零引擎 I/O”(零引擎 I/O)的理念。

    如果您还有其他问题,请告诉我们。 如果还有其他问题,欢迎反馈!

    感谢你的答疑!🙏🙏

  3. zhujianguo commented on Apr 21, 2026

    @zhujianguo
    Author

    不对,我上午还是正常的,下午同样的代码,开始出现
    Starting work for dev.brewkits.kmpworkmanager.background.data.KmpWorker
    2026-04-21 17:01:50.107 8838-8903 DartCallbackWorker com.urevo.app D DartCallbackWorker started
    2026-04-21 17:01:50.107 8838-8903 DartCallbackWorker com.urevo.app D Executing callback: debug_page_native_workmanager_notify (handle: 8748121046172070908, autoDispose: true, timeoutMs: 300000)
    2026-04-21 17:01:50.122 8838-9320 flutter com.urevo.app I [IMPORTANT:flutter/shell/platform/android/android_context_vk_impeller.cc(62)] Using the Impeller rendering backend (Vulkan).
    2026-04-21 17:01:50.454 8838-8838 flutter com.urevo.app I >>>>>>> [2026-04-21 17:01:50.454230][蓝牙响应数据][srvId:FEE0][charId:FEE0] [ID:URTreadmill_51] [02 51 03 28 00 64 13 08 02 C9 0A 00 00 00 00 00 00 88 03] <<<<<<<<
    2026-04-21 17:01:50.469 8838-8838 flutter com.urevo.app I [debug_page_native_workmanager] DartWorker 开始 body=立即执行
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I [debug_page_native_workmanager] 步数聚合失败: MissingPluginException(No implementation found for method isApiSupported on channel flutter_health_connect)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:364:7)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #1 HealthConnectFactory.isApiSupported (package:flutter_health_connect/src/flutter_health_connect_factory.dart:36:12)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #2 _fetchTodayStepsTotal (package:urevo_flutter_module/page/test/debug_page_native_workmanager_worker.dart:29:10)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #3 debugPageNativeWorkmanagerNotifyTask (package:urevo_flutter_module/page/test/debug_page_native_workmanager_worker.dart:69:13)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #4 Future.timeout. (dart:async/future_impl.dart:1061:7)
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.476 8838-8838 flutter com.urevo.app I #5 _callbackDispatcher. (package:native_workmanager/src/native_work_manager.dart:183:24)
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I #6 MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:607:42)
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I #7 _DefaultBinaryMessenger.setMessageHandler. (package:flutter/src/services/binding.dart:663:22)
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.477 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I [debug_page_native_workmanager] 通知展示失败: MissingPluginException(No implementation found for method initialize on channel dexterous.com/flutter/local_notifications)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:364:7)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #1 AndroidFlutterLocalNotificationsPlugin.initialize (package:flutter_local_notifications/src/platform_flutter_local_notifications.dart:148:12)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #2 debugPageNativeWorkmanagerNotifyTask (package:urevo_flutter_module/page/test/debug_page_native_workmanager_worker.dart:91:5)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #3 Future.timeout. (dart:async/future_impl.dart:1061:7)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #4 _callbackDispatcher. (package:native_workmanager/src/native_work_manager.dart:183:24)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #5 MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:607:42)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I #6 _DefaultBinaryMessenger.setMessageHandler. (package:flutter/src/services/binding.dart:663:22)
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.478 8838-8838 flutter com.urevo.app I
    2026-04-21 17:01:50.499 8838-8903 DartCallbackWorker com.urevo.app D Dart callback completed: debug_page_native_workmanager_notify, result: true
    2026-04-21 17:01:50.500 8838-8903 KMP_WorkManager com.urevo.app I ℹ️ [TaskWorker] KmpWorker success: DartCallbackWorker — Dart callback executed: debug_page_native_workmanager_notify
    2026-04-21 17:01:50.500 8838-8903 KMP_WorkManager com.urevo.app W ⚠️ [TaskScheduler] TaskEventManager: EventStore not initialized, event not persisted
    2026-04-21 17:01:50.509 8838-8979 WM-WorkerWrapper com.urevo.app I Worker result SUCCESS for Work [ id=190ee353-2d2b-4874-8727-2b202ec23a39, tags={ dev.brewkits.kmpworkmanager.background.data.KmpWorker,kmp-worker-task,worker-DartCallbackWorker,debug_page_wm_immediate,DartCallbackWorker,debug_page_native_wm } ]
    2026-04-21 17:01:50.511 8838-8838 WM-Processor com.urevo.app D Processor 190ee353-2d2b-4874-8727-2b202ec23a39 executed; reschedule = false
    2026-04-21 17:01:50.512 8838-8838 WM-SystemJobService com.urevo.app D 190ee353-2d2b-4874-8727-2b202ec23a39 executed on JobScheduler
    2026-04-21 17:01:50.514 8838-8979 WM-GreedyScheduler com.urevo.app D Cancelling work ID 190ee353-2d2b-4874-8727-2b202ec23a39
    这个错误我的理解就是没有做以下动作,我的确也没有做,但是很奇怪,我上午是可以的,难道是我本地缓存的原因?还是说,你这边针对1.2.2版本又有什么改动吗

    Image 我还在持续测试中,这个很奇怪的现象,很有可能是我本地之前有缓存,可是我上午测试了好几遍 ======================== 最终没能复现不通过手动注册插件,也能正常触发通知和读取Google health数据。 我最后还是通过手动注册 NativeWorkmanagerPlugin.setPluginRegistrantCallback( object : NativeWorkmanagerPlugin.Companion.PluginRegistrantCallback { override fun registerWith(engine: FlutterEngine) { engine.plugins.add(FlutterLocalNotificationsPlugin()) engine.plugins.add(FlutterHealthConnectPlugin()) } }, )才正常运行,这个方案我觉得没问题,我很乐意接受。提出这个疑问,只是好奇早上出现不用自注册也能正常运行,现在看来很有可能是我之前本地缓存的原因!!!
  4. vietnguyentuan2019 commented on Apr 21, 2026

    @vietnguyentuan2019
    Contributor

    Hi @zhujianguo,

    Thank you for the detailed feedback in Issue #20. The regression experienced (working in the morning but failing later) is a classic case of what we call "Phantom Success".

    The "Phantom Success" Explained

    Stateless plugins like flutter_local_notifications often interact directly with OS managers. If the app was recently in the foreground, the OS might still hold an active intent or cache that allows the notification to show even if the current background engine hasn't registered the plugin. However, this is not persistent. Once the OS clears its cache or the plugin requires a reverse callback (Native -> Dart), it will throw a MissingPluginException.

    Why we don't auto-register all plugins

    We default registerPlugins to false to uphold our Zero-Engine I/O philosophy. Registering all plugins (like Bluetooth, Camera, or Audio) in a background engine often causes critical side-effects. For example, when the background engine is destroyed, those plugins might trigger their cleanup logic and unintentionally disconnect a foreground Bluetooth session.

    The Solution: Selective Registration (Recommended)

    Instead of enabling registerPlugins: true (which is RAM-heavy and risky), you should use Selective Registration. This allows you to register only the specific plugins you need for background tasks.

    I have updated the README and Setup Guides with clear examples for both Android (Kotlin) and iOS (Swift).

    Quick Example for your case (Kotlin):

    NativeWorkmanagerPlugin.setPluginRegistrantCallback(object : NativeWorkmanagerPlugin.Companion.PluginRegistrantCallback {
        override fun registerWith(engine: FlutterEngine) {
            // Register ONLY what you need
            engine.plugins.add(FlutterLocalNotificationsPlugin())
            engine.plugins.add(FlutterHealthConnectPlugin())
        }
    })

    This keeps your background tasks lean, stable, and conflict-free. This documentation update will be officially part of the 1.2.3 release.

    Thanks for using native_workmanager!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions