分类 前端 下的文章






个人简介





个人简介





个人照片

姓名:张三


一个热爱编程和旅行的开发者。




技能



  • HTML

  • CSS

  • JavaScript




联系方式


邮箱:zhangsan@example.com


电话:123-456-7890






© 2025 张三






在开发我的 Flutter 应用时,遇到了一个非常棘手的问题:
• 用 flutter run 在手机上调试,一切正常。首页的 浏览按钮 能顺利打开相册,右上角的 语言切换功能 也能正常工作。
• 但一旦用命令打包成 release APK(例如 flutter build apk --release --split-per-abi),安装到真机后,这些功能全部失效了:相册打不开、语言无法切换。

图片
一开始我以为是权限没声明、资源没打包,但查了半天都没找到问题。后来在 logcat 中看到了关键日志:
E/flutter : [ERROR:flutter/runtime/dart_vm_initializer.cc(40)]


Unhandled Exception: MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)


这行报错信息点醒了我 —— 插件没有被注册!所有依赖平台通道的插件都挂了,包括 permission_handler 和国际化相关的插件。
问题根源:ProGuard / R8 混淆


Flutter 在 release 模式下会开启 R8/ProGuard 混淆优化。如果没有正确配置,部分插件的注册类可能被裁剪掉,导致在运行时抛出 MissingPluginException
换句话说:插件不是坏了,而是被优化掉了。
解决方案我最后的解决方案分两步:
. 快速重现和定位问题我写了一个 rebuild.bat 脚本,把清理、依赖获取、打包、安装和日志查看串联起来:
@echo off


echo ========================================


echo MediaBox Rebuild and Install


echo ========================================



echo Step 1: Cleaning...


call flutter clean



echo Step 2: Getting dependencies...


call flutter pub get



echo Step 3: Generating localization...


call flutter gen-l10n



echo Step 4: Building APK (NO obfuscation for testing)...


call flutter build apk --release --no-obfuscate



echo Step 5: Uninstalling old version...


adb uninstall com.example.flutter4



echo Step 6: Installing new APK...


adb install build\app\outputs\flutter-apk\app-release.apk



echo Installation Complete!


pause



echo Showing logs (Ctrl+C to stop)...


adb logcat -c


adb logcat *:E Flutter:V DEBUG:V


运行后如图:

图片
用这个脚本打包并运行,能立刻看到 logcat 里的报错,确认是 MissingPluginException。

图片
2. 禁用 ProGuard
混淆临时方案:
完全禁用ProGuard已修改 `android/app/build.gradle.kts`:
buildTypes {



release {



signingConfig = signingConfigs.getByName("debug")





// 暂时禁用混淆



isMinifyEnabled = false



isShrinkResources = false



}



}


**优点**:
✅ 所有插件都能正常工作
-✅ 权限请求正常
✅ 文件选择器正常
✅ 语言切换正常
**缺点**:
❌ APK体积会变大(约50-60MB)
❌ 代码不被混淆保护
为了验证问题是否出在混淆,我又写了一个 fix_and_rebuil
@echo off


title MediaBox Quick Fix


color 0C



echo ========================================


echo PLUGIN REGISTRATION FIX


echo ========================================



echo Step 1: Cleaning...


call flutter clean



echo Step 2: Getting dependencies...


call flutter pub get



echo Step 3: Building APK (NO ProGuard)...


call flutter build apk --release --no-shrink



echo Step 4: Uninstalling old version...


adb uninstall com.example.flutter4



echo Step 5: Installing new APK...


adb install build\app\outputs\flutter-apk\app-release.apk



echo Installation Complete!


pause



cls


echo ========================================


echo LIVE LOGS (Ctrl+C to stop)


echo ========================================


adb logcat -c


adb logcat -v time | findstr /i "flutter AUDIO LANG perm"


重新安装后,所有功能恢复正常。验证了问题确实是 R8/ProGuard 导致插件注册丢失

图片

n图片
最终方案


开发测试阶段
可以直接禁用混淆(--no-shrink),保证功能完整。上线前
在 android/app/proguard-rules.pro 里加上保留规则,避免插件类被裁剪:
-keep class io.flutter.** { *; }


-keep class io.flutter.plugins.** { *; }


-keep class com.baseflow.permissionhandler.** { *; }


总结


这次经历让我很深刻地体会到
1. Debug 和 Release 的构建环境差别很大,release 的 bug 必须在 release 包里复现,光靠 debug 跑是发现不了的。
2. MissingPluginException 大多数时候不是插件坏了,而是混淆把关键类优化掉了。
3. 遇到这种问题,第一步就是用脚本快速复现、查看日志,定位到具体报错。
这次我用 Claude 4.5 Sonnet 给出的脚本方案解决了 GPT-5 没能解决的实际问题,过程曲折,但收获很大。希望这篇文章能帮到遇到同样问题的开发者。

在之前的文章鸿蒙Flutter实战:09-现有Flutter项目支持鸿蒙中,介绍了如何改造项目,适配鸿蒙平台。

文中讲述了整体的理念和思路,本文更进一步,结合可实操的项目代码,详细说明如何实施。

通过模块化、鸿蒙壳工程,结合 FVM 管理多版本 Flutter SDK,最终,保持原 Flutter 代码纯净,最小化修改,完成了鸿蒙化的适配示例。

本项目代码地址:GitHub地址

准备工作

1.安装 FVM

dart pub global activate melos

2.使用 FVM 安装 Flutter SDK

分别安装官方的3.22版本,以及鸿蒙社区的 3.22.0 版本

3.搭建 Flutter鸿蒙开发环境

搭建项目架构

创建目录

# 创建项目目录
mkdir flutter-ohos-demo

设置使用的 Flutter SDK 版本 推荐在 VsCode 的命令行中执行以下命令,这将创建 .fvm 目录, .vscode/setting.json 文件, 和.fvmrc 文件

fvm use 3.22.0


初始化工作区间

创建目录,项目结构如下所示:

.
├──  packages
│   ├── apps  #该目录用于存放各端应用壳工程
│   ├── common #该目录用于存放公共库,均为纯 dart 代码,不依赖于 ios/android 等原生实现
│   │   ├── domains #领域对象,存放各类实体文件,如枚举/模型/vo/事件等
│   │   ├── extensions #存放扩展类文件,对于类的扩展方法/属性
│   │   ├── services #服务类:如请求服务/授权服务/缓存服务/平台调用服务/路由服务/工具类等
│   │   └── widgets #通用小型 widgets, 纯dart编写的 Flutter UI 组件
│   ├── components #封装组件库,可以依赖于第三方库/第三方插件,或依赖于 plugins中的插件
│   │   ├── image_uploader
│   │   └── player
│   ├── modules
│   │   ├── address
│   │   ├── home
│   │   ├── me
│   │   ├── message
│   │   ├── order
│   │   ├── shop
│   │   └── support
│   └── plugins #插件库,自行封装的插件库,依赖于原生平台(ios/android)的代码
│       └── printer
├── README.md
├── melos.yaml
└── pubspec.yaml


运行 melos bootstrap

melos bootstrap


开始编写代码

在各个 package 初始化代码,如在 packages/common/domains 目录运行

fvm flutter create --template package .

创建壳工程

新建两个壳工程,一个为 app,另外一个为 ohos_app


App 壳工程

进入 package/apps/app 目录, 创建 app 项目,该项目为一个 App 项目,用于各平台(ios/android/mac 等, 不包含鸿蒙)打包

fvm flutter create --template app --org com.moguyun.flutter app

增加依赖项

修改 pubspec.yaml,添加以下内容

services:
   path: '../../common/services'
 domains:
   path:  '../../common/domains'
 widgets:
   path: '../../common/widgets'

 home:
   path: '../../modules/home'
 me:
   path: '../../modules/me'
 support:
   path: '../../modules/support'


安装依赖

运行以下命令,安装依赖

fvm flutter pub get


切换鸿蒙 Flutter SDK

首先在 flutter-ohos-demo 项目根目录,将 Flutter 版本切换到鸿蒙化的版本

fvm use custom_3.22.0

SDK 变更以后,需要重启 IDE (或者 Dart:Restart Analysis Server),以便让 Flutter 插件重启


创建 ohos_app 项目

进入 packages/apps 目录,创建 ohos_app 项目

fvm flutter create --template app --platforms ohos --org com.moguyun.flutter ohos_app


增加依赖项

进入 packages/apps/ohos_app 目录中的 pubspec.yaml, 同样增加依赖项

services:
   path: '../../common/services'
 domains:
   path:  '../../common/domains'
 widgets:
   path: '../../common/widgets'

 home:
   path: '../../modules/home'
 me:
   path: '../../modules/me'
 support:
   path: '../../modules/support'

三方库鸿蒙化适配

编辑 pubspec.yaml文件,增加以下配置,通过 dependency_overrides 来替换鸿蒙化的三方库,注意鸿蒙化的库与原库,保持版本统一

# 鸿蒙适配
dependency_overrides:
  flutter_inappwebview:
    git:
      url: https://gitee.com/openharmony-sig/flutter_inappwebview.git
      path: "flutter_inappwebview"

每次修改完 pubspec.yaml,使用 fvm flutter pub get 更新下依赖安装。


运行调试

用 Deveco 打开apps/ohos_app/ohos 目录。


在 Deveco 左上角 打开 File -> Project Structure..., 点击 Siging Configs, 勾选 Automatically generate signature, 对鸿蒙项目签名。

在 ohos_app 目录下,使用 fvm flutter run,或者点击运行按钮,运行flutter项目。


注意事项


  1. melos.yaml 文件中的 sdkPath: .fvm/flutter_sdk 配置了 melos 使用的 flutter SDK 版本,即由FVM 配置的当前项目版本
  2. 每次切换 Flutter SDK 时,都会修改文件 .fvm/, vscode/settings.json 文件
  3. ohos_app/pubsec.yaml 中的 dependency_overrides, 仅添加需要鸿蒙化的三方库
  4. ohos-3.22 在 build 时,有的 har 包可能确实,建议保持 ohos-Flutter 版本最新,如果还是不行,可以考虑手动复制 har 包(使用 3.7 构建出来)ohos_app/pubsec.yaml 中的 dependency_overrides, 仅添加需要鸿蒙化的三方库
  5. 已知插件删除问题,如果删除插件,可能需要在ohos里面手动修改代码,移除相关依赖ohos/oh-package.json5


如何判断三方库是否需要鸿蒙化,简而言之,如果三方库由纯 Dart 实现,则不需要单独适配,直接使用;如果三方库依赖系统底层实现,则需要鸿蒙化适配。

ohos-3.22 在 build 时,有的 har 包可能确实,建议保持 ohos-Flutter 版本最新,如果还是不行,可以考虑手动复制 har 包(使用 3.7 构建出来)

三方库的适配情况,可以查询 Gitee/Github,或者查阅表格 Flutter三方库适配计划

应用截图

总结

  1. 通过 FVM 管理多个 Flutter SDK 版本,仅在鸿蒙调测打包时,切换到 ohos-flutter SDK
  2. 通过 apps 壳工程,将鸿蒙化适配的代码,尽量在 ohos_app 项目中完成。通过 pub 包管理的 dependency_overrides 配置,逐个替换鸿蒙化的三方库
  3. 通过 melos 管理多包项目,Flutter 项目进行模块化、组件化、插件化拆分,职责分离,平台抽象,不同平台组合打包,有效解决平台不一致问题


参考资料

鸿蒙flutter实战——环境搭建