Flutter项目模拟器运行正常,部分Android真机调用三方包时异常
问题概述
Flutter项目集成了SharedPreferences、SQFlite、Path Provider插件,在Pixel 3a/4模拟器、Android10小米Redmi 9上运行正常,但在Android12的一加Nord、三星Galaxy M33设备上触发异常:
- SharedPreferences/Path Provider抛出:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel., null, null) - SQFlite抛出:
Unhandled Exception: MissingPluginException(No implementation found for method getDatabasesPath on channel com.tekartik.sqflite)
已尝试flutter clean、flutter pub get、升级依赖等操作,未解决问题。异常触发点为调用SharedPreferences.getInstance()时。
相关代码片段:
主文件初始化代码:
@override void initState() { print("Init State"); appState = Provider.of<AppState>(context, listen: false); initializeColors(); super.initState(); } void initializeColors() async { final fileState = Provider.of<StorageDetails>(context, listen: false); await fileState.initializeDirectory(); await appState.initializeColors(); // 调用SharedPreferences初始化逻辑 }
颜色初始化文件代码:
Future<void> initializeColors() async { await loadColorsFromSharedPreferences(); } Future<void> loadColorsFromSharedPreferences() async { SharedPreferences prefs = await SharedPreferences.getInstance(); labelColor = Color(prefs.getInt('labelColor') ?? (0xFFE7B9AA)); accentColor = Color(prefs.getInt('accentColor') ?? (0xFFD4582F)); labelTextColor = Color(prefs.getInt('labelTextColor') ?? (0xFF000000)); disabledButtonColor = Color(prefs.getInt('disabledButtonColor') ?? (0xFFD9D9D9)); appTheme = prefs.getInt('appTheme') ?? 0; if (appTheme == 1) { setDarkTheme(); print('DarkThemeSet'); } else { setLightTheme(); print('LightThemeSet'); } }
核心原因
- Android12+包可见性限制:Android12及以上系统默认启用包可见性规则,应用无法直接访问其他第三方包或系统组件,导致Flutter插件与原生通道无法建立连接。
- 初始化时机不当:在Widget未完全挂载时调用原生插件方法,可能导致通道初始化未完成就触发调用。
- 构建缓存残留:旧的原生构建缓存可能导致插件注册信息未正确更新。
优雅解决方案
1. 配置Android包可见性
在android/app/src/main/AndroidManifest.xml中添加<queries>标签,声明应用需要访问的组件,确保Flutter插件能正常与原生通信:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 其他现有配置 --> <queries> <!-- 允许访问Android核心应用组件,适配Flutter插件通道 --> <intent> <action android:name="android.intent.action.MAIN"/> </intent> </queries> <!-- 其他现有配置 --> </manifest>
2. 调整初始化时机
修改主文件的initState方法,使用WidgetsBinding.instance.addPostFrameCallback延迟初始化操作,确保Widget树完全构建后再调用原生插件:
@override void initState() { super.initState(); print("Init State"); appState = Provider.of<AppState>(context, listen: false); // 延迟到Widget构建完成后执行异步初始化 WidgetsBinding.instance.addPostFrameCallback((_) { initializeColors(); }); } void initializeColors() async { final fileState = Provider.of<StorageDetails>(context, listen: false); await fileState.initializeDirectory(); await appState.initializeColors(); }
3. 彻底清理并重建项目
执行以下步骤清除残留缓存,确保插件正确注册:
- 运行
flutter clean - 删除
android/app/build目录 - 运行
flutter pub get - 重新构建项目:
flutter run --debug
4. 锁定兼容的插件版本
避免盲目升级所有依赖,选择支持Android12的稳定版本,修改pubspec.yaml:
dependencies: flutter: sdk: flutter shared_preferences: ^2.2.2 sqflite: ^2.3.0 path_provider: ^2.1.1 provider: ^6.1.1
执行flutter pub get更新依赖。
内容的提问来源于stack exchange,提问作者kris
相关产品推荐
相关产品推荐

