Flutter安卓端打开相机扫描QR码触发致命错误闪退,iOS端无此问题求助
兄弟,我之前也碰到过类似的WebView和相机冲突导致安卓闪退的问题,看你给出的错误日志和代码,大概率是flutter_inappwebview的Hybrid Composition和qr_code_scanner的相机预览争夺SurfaceTexture资源导致的(就是日志里的Check failed: state_ == AttachmentState::kAttached错误),给你几个可行的解决思路,你挨个试试:
1. 先升级依赖包到最新稳定版
你目前用的包版本都比较旧了,这些底层的渲染冲突问题很可能已经在新版本里修复了:
flutter_inappwebview:当前最新稳定版是6.x系列,你用的是5.3.2qr_code_scanner:最新版已经修复了不少安卓相机初始化的问题
修改pubspec.yaml里的依赖:
flutter_inappwebview: ^6.0.0 qr_code_scanner: ^1.0.1 # 或者更高版本 http: ^1.2.1
然后执行flutter pub upgrade更新依赖,再测试是否还闪退。
2. 处理WebView和扫描页的生命周期冲突
Hybrid Composition模式的WebView会占用安卓的SurfaceTexture资源,和相机预览冲突。你需要在跳转到扫描页前暂停WebView,返回后再恢复:
修改Home页面的askPermission方法:
Future<void> askPermission(Uri? url) async { var status = await Permission.camera.status; if (status.isDenied) { await Permission.camera.request(); } if (await Permission.camera.isGranted) { if (url.toString() == "https://link") { // 跳转前暂停WebView,释放资源 await webViewController?.pause(); // 跳转后返回时恢复WebView Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Scanner()) ).then((_) { webViewController?.resume(); }); } } }
3. 修复扫描页的相机重复初始化问题
从日志里的W/CameraPreview(10851): initCamera called twice可以看出,相机被重复初始化了,这也可能导致资源冲突。你可以在扫描页增加生命周期监听,确保相机在页面不可见时暂停,可见时恢复,同时避免重复初始化:
修改Scanner页面的代码:
class _ScannerState extends State<Scanner> with WidgetBindingObserver { final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); bool canScan = true; bool isCameraInitialized = false; QRViewController? controller; // ... 其他变量不变 @override void initState() { super.initState(); // 添加生命周期监听 WidgetsBinding.instance.addObserver(this); } @override void dispose() { // 移除监听 WidgetsBinding.instance.removeObserver(this); controller?.dispose(); super.dispose(); } // 监听页面生命周期 @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (controller == null) return; switch (state) { case AppLifecycleState.paused: controller?.pauseCamera(); // 页面暂停时暂停相机 break; case AppLifecycleState.resumed: controller?.resumeCamera(); // 页面恢复时重启相机 break; default: break; } } void onQRViewCreated(QRViewController controller) { // 如果已有控制器,先销毁再重新赋值,避免重复初始化 this.controller?.dispose(); this.controller = controller; isCameraInitialized = true; controller.scannedDataStream.listen((scanData) async { if (canScan && scanData.code?.isNotEmpty == true) { canScan = false; final lst = await Requests.checkProduct(scanData.code!); if (lst.isEmpty) { showError(); } else { this.controller?.dispose(); Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => Home(Uri.parse(resultUrl + scanData.code!)), ), ); } } }); } // ... 其他方法不变 }
4. 尝试关闭WebView的Hybrid Composition(备选方案)
如果上面的方法都不行,可以尝试关闭flutter_inappwebview的useHybridComposition选项,虽然可能会影响WebView的性能,但可以验证是否是这个选项导致的冲突:
修改Home页面的options:
InAppWebViewGroupOptions options = InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( mediaPlaybackRequiresUserGesture: false, javaScriptEnabled: true, cacheEnabled: true, supportZoom: false, clearCache: false), android: AndroidInAppWebViewOptions(useHybridComposition: false), // 改为false ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, sharedCookiesEnabled: true));
另外,记得确认你的AndroidManifest.xml里已经正确添加了相机权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
先从升级依赖开始试,这是最简单的解决方案,如果还不行再试后面的步骤,应该能解决你的闪退问题!
备注:内容来源于stack exchange,提问作者Muhammed Akar

