Flutter camera包iOS端权限变更致应用崩溃问题求助
解决Flutter camera包iOS权限修改后崩溃问题
问题分析
iOS系统在应用后台修改相机权限后,会强制应用重新处理相关硬件资源。camera包官方示例未适配这种场景下的相机资源释放与重新初始化逻辑,导致非法访问相机资源触发SIGKILL崩溃。
解决方案
1. 监听应用生命周期,前台回调重置相机
在Flutter层通过WidgetsBindingObserver监听应用回到前台的事件,此时先释放旧相机资源,再重新检查权限并初始化相机:
class CameraPage extends StatefulWidget { @override _CameraPageState createState() => _CameraPageState(); } class _CameraPageState extends State<CameraPage> with WidgetsBindingObserver { CameraController? _controller; List<CameraDescription>? _cameras; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _initCamera(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); _controller?.dispose(); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 应用回到前台时重置相机 if (state == AppLifecycleState.resumed) { _resetCamera(); } } Future<void> _initCamera() async { final status = await Permission.camera.status; if (status.isGranted) { _cameras = await availableCameras(); _controller = CameraController( _cameras![0], ResolutionPreset.medium, ); await _controller?.initialize(); if (mounted) setState(() {}); } } Future<void> _resetCamera() async { // 必须先释放旧控制器,避免资源冲突 await _controller?.dispose(); // 重新初始化相机 await _initCamera(); } // 引导用户前往设置的逻辑 void _openAppSettings() async { await openAppSettings(); } @override Widget build(BuildContext context) { return Scaffold( body: _controller?.value.isInitialized == true ? CameraPreview(_controller!) : Center( child: ElevatedButton( onPressed: _openAppSettings, child: const Text("前往设置开启相机权限"), ), ), ); } }
2. 原生层补充权限变化监听(可选)
如果Flutter层监听不够及时,可在iOS的AppDelegate中添加系统权限通知监听,通过MethodChannel通知Flutter层重置相机:
import UIKit import Flutter import AVFoundation @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) // 监听相机设备连接/断开通知(权限变化会触发此类通知) NotificationCenter.default.addObserver( self, selector: #selector(cameraPermissionChanged), name: NSNotification.Name.AVCaptureDeviceWasConnected, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(cameraPermissionChanged), name: NSNotification.Name.AVCaptureDeviceWasDisconnected, object: nil ) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } @objc func cameraPermissionChanged() { let channel = FlutterMethodChannel(name: "your.app.channel/camera_permission", binaryMessenger: window?.rootViewController as! FlutterBinaryMessenger) channel.invokeMethod("resetCamera", arguments: nil) } }
在Flutter层注册MethodChannel接收通知:
@override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // 注册MethodChannel const MethodChannel _channel = MethodChannel('your.app.channel/camera_permission'); _channel.setMethodCallHandler((call) async { if (call.method == 'resetCamera') { await _resetCamera(); } }); _initCamera(); }
3. 强化权限检查逻辑
确保在初始化相机前严格校验权限状态,避免未授权时尝试访问相机资源,推荐使用permission_handler包进行权限管理。
关键注意事项
- 每次重置相机必须先释放旧的CameraController,再创建新实例,避免硬件资源占用冲突
- 权限变化后不可复用原有相机实例,必须重新获取相机列表并初始化
- 操作UI前检查
mounted状态,避免页面销毁后执行无效更新
内容的提问来源于stack exchange,提问作者Saad Bashir
相关产品推荐
相关产品推荐

