Flutter使用workmanager包时引擎停止运行闪退 疑似与flutter_tesseract_ocr冲突
问题现象
该问题仅在使用 workmanager 包时触发,触发注册的后台任务后应用直接崩溃,初步怀疑是workmanager与部分Google相关依赖包或 flutter_tesseract_ocr 包存在兼容性冲突。
业务实现代码
void callbackDispatcher() { Workmanager().executeTask((task, inputData) { print('I dont know what happens so help'); return Future.value(true); }); } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); FirebaseMessaging.onBackgroundMessage(_firebasePushHandler); MobileAds.instance.initialize(); await CacheHelper.init(); await EasyLocalization.ensureInitialized(); await CacheHelper.removeData('isshown'); DioHelper.init(); //Work manager initializtion Workmanager().initialize( callbackDispatcher, // 顶层回调调度函数 ); index = CacheHelper.getData(key: 'index') ?? 0; String? uid = CacheHelper.getData(key: 'uid'); await NotificationApi.init(); BlocOverrides.runZoned( () { runApp( EasyLocalization( supportedLocales: const [Locale('en'), Locale('ar')], path: 'assets/lang', // 翻译文件存放路径 assetLoader: const CodegenLoader(), fallbackLocale: const Locale('en'), child: MyApp(uid)), ); }, blocObserver: MyBlocObserver(), ); } /// 后台任务注册逻辑 Widget build(BuildContext context) { return GestureDetector( onTap: () { HapticFeedback.lightImpact(); setState(() { controller!.forward(); }); // Workmanager().cancelAll(); Workmanager().registerOneOffTask('awsomeNotification', 'notify', initialDelay: const Duration(seconds: 5)); }, child: CardStack(controller!, widget.slideNum, widget.slideText), ); }
崩溃运行日志
W/MediaSessionCompat(12770): Couldn't find a unique registered media button receiver in the given context. W/FlutterJNI(12770): FlutterJNI.loadLibrary called more than once I/ResourceExtractor(12770): Found extracted resources res_timestamp-1-1656733798661 W/FlutterJNI(12770): FlutterJNI.prefetchDefaultFontManager called more than once W/FlutterJNI(12770): FlutterJNI.init called more than once D/AndroidRuntime(12770): Shutting down VM E/AndroidRuntime(12770): FATAL EXCEPTION: main E/AndroidRuntime(12770): Process: com.areading.amaa, PID: 12770 E/AndroidRuntime(12770): java.lang.NullPointerException: Attempt to invoke virtual method 'void com.googlecode.tesseract.android.TessBaseAPI.recycle()' on a null object reference E/AndroidRuntime(12770): at io.paratoner.flutter_tesseract_ocr.FlutterTesseractOcrPlugin.onDetachedFromEngine(FlutterTesseractOcrPlugin.java:42) E/AndroidRuntime(12770): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.remove(FlutterEngineConnectionRegistry.java:270) E/AndroidRuntime(12770): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.remove(FlutterEngineConnectionRegistry.java:280) E/AndroidRuntime(12770): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.removeAll(FlutterEngineConnectionRegistry.java:288) E/AndroidRuntime(12770): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.destroy(FlutterEngineConnectionRegistry.java:121) E/AndroidRuntime(12770): at io.flutter.embedding.engine.FlutterEngine.destroy(FlutterEngine.java:425) E/AndroidRuntime(12770): at be.tramckrijte.workmanager.BackgroundWorker.stopEngine$lambda-2(BackgroundWorker.kt:137) E/AndroidRuntime(12770): at be.tramckrijte.workmanager.BackgroundWorker.lambda$u5fs2CPxJ29Hdjbap5WYUt2tGrg(Unknown Source:0) E/AndroidRuntime(12770): at be.tramckrijte.workmanager.-$$Lambda$BackgroundWorker$u5fs2CPxJ29Hdjbap5WYUt2tGrg.run(Unknown Source:2) E/AndroidRuntime(12770): at android.os.Handler.handleCallback(Handler.java:938) E/AndroidRuntime(12770): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(12770): at android.os.Looper.loopOnce(Looper.java:210) E/AndroidRuntime(12770): at android.os.Looper.loop(Looper.java:299) E/AndroidRuntime(12770): at android.app.ActivityThread.main(ActivityThread.java:8168) E/AndroidRuntime(12770): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(12770): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) E/AndroidRuntime(12770): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037) I/WM-WorkerWrapper(12770): Worker result SUCCESS for Work [ id=58f0ee16-1de5-42d8-ae78-1d789ea5125f, tags={ be.tramckrijte.workmanager.BackgroundWorker } ] D/OOMEventManagerFK(12770): checkEventAndDumpForJE: 0 I/Process (12770): Sending signal. PID: 12770 SIG: 9 Lost connection to device. Exited (sigterm)
根因定位
从崩溃栈可以明确问题触发链路:
- workmanager执行完后台任务后,会销毁后台执行使用的独立FlutterEngine实例
- 引擎销毁过程中会回调所有已注册插件的
onDetachedFromEngine生命周期方法 - flutter_tesseract_ocr 插件的该回调方法没有做非空判断,直接对从未初始化过(后台任务未使用OCR能力,TessBaseAPI实例为null)的对象调用
recycle()方法,触发空指针异常 - 异常未被捕获,直接导致应用进程被系统强制终止,设备连接断开。
修复方案
- 临时本地修复:打开本地pub缓存中
flutter_tesseract_ocr插件的android源码文件,路径为~/.pub-cache/hosted/pub.dev/flutter_tesseract_ocr-<对应版本号>/android/src/main/java/io/paratoner/flutter_tesseract_ocr/FlutterTesseractOcrPlugin.java,定位到onDetachedFromEngine方法,在调用recycle()前增加非空判断:
@Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { // 新增非空判断逻辑 if (tessBaseAPI != null) { tessBaseAPI.recycle(); } channel.setMethodCallHandler(null); }
- 长期方案:如果不需要在workmanager的后台任务中使用OCR能力,可以在workmanager的回调调度逻辑中屏蔽无关插件的自动注册;也可以将该问题提交给flutter_tesseract_ocr插件维护者,等待官方发布修复版本。
内容的提问来源于stack exchange,提问作者abdallah mostafa
相关产品推荐
相关产品推荐

