Xamarin CameraView的Shutter方法Android9报错的替代方案
问题场景
基于Xamarin开发适配iOS、Android的跨平台相机应用,因需要在拍照过程中同步展示额外信息,未使用系统MediaPicker实现相机访问,选用了Xamarin Community Toolkit的CameraView控件。
开发测试全程在Android 11模拟器上完成,未做低版本Android兼容性验证:项目目标Android版本设为11,最低兼容版本为Android 5.1。应用在Android 9设备上可正常启动运行,但触发拍照操作时抛出System.NullReferenceException异常,错误提示为Object reference not set to an instance of an object。
触发拍照的方法代码如下:
private void CaptureImage(object sender, EventArgs e) { xctCameraView.Shutter(); }
对应页面XAML布局代码:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:xct="http://xamarin.com/schemas/2020/toolkit" Title="Prenez une photo" BackgroundColor="Transparent" x:Class="App1.CameraViewPage"> <Grid x:Name="myGrid"> <xct:CameraView x:Name="xctCameraView" CaptureMode="Photo" MediaCaptured="MediaCaptured" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/> <StackLayout VerticalOptions="EndAndExpand" Spacing="2" Padding="6"> <Button WidthRequest="70" HeightRequest="70" CornerRadius="40" BackgroundColor="Transparent" BorderColor ="White" BorderWidth="8" Clicked="CaptureImage" x:Name="captureBtn" HorizontalOptions="Center" VerticalOptions="Center"/> </StackLayout> <StackLayout VerticalOptions="StartAndExpand" Spacing="2" Padding="6"> <Label x:Name="labelOfMine" x:FieldModifier="public" Text="" BackgroundColor="LightYellow"> </Label> </StackLayout> </Grid> </ContentPage>
问题根因
这个异常是Android版本间相机服务初始化时序差异导致的:
Android 11上CameraView加载后会快速完成底层相机捕获会话的实例化,页面加载完成后直接点击拍照不会触发空引用;但Android 9及更早版本上,底层相机会话的初始化是异步执行的,如果在会话还未完成实例化时就直接调用Shutter()方法,就会访问到空的会话对象,抛出空引用异常。
修复方案
- 调用拍照方法前增加状态校验,只有相机实例可用时才触发快门:
private void CaptureImage(object sender, EventArgs e) { if (xctCameraView?.IsAvailable == true) { xctCameraView.Shutter(); } }
- 增加相机状态监听,在相机未完成初始化前禁用拍照按钮,避免用户误点触发异常,同时在页面生命周期中手动管理相机启停,减少初始化异常概率:
protected override void OnAppearing() { base.OnAppearing(); // 页面显示时启动相机 _ = xctCameraView.StartCameraAsync(); // 默认禁用拍照按钮 captureBtn.IsEnabled = false; // 监听相机可用状态变化 xctCameraView.AvailabilityChanged += OnCameraAvailabilityChanged; } private void OnCameraAvailabilityChanged(object sender, bool isAvailable) { // 相机可用时启用按钮,不可用时禁用 captureBtn.IsEnabled = isAvailable; } protected override void OnDisappearing() { base.OnDisappearing(); // 移除事件监听,避免内存泄漏 xctCameraView.AvailabilityChanged -= OnCameraAvailabilityChanged; // 页面离开时停止相机,释放硬件资源 _ = xctCameraView.StopCameraAsync(); }
- 补充配置校验:确认Android项目已声明相机权限和硬件特性,避免权限缺失导致相机初始化失败,在
AndroidManifest.xml中添加以下配置:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false" />
同时要在应用运行时动态申请相机权限,不要仅依赖安装时的静态权限声明。
内容的提问来源于stack exchange,提问作者Ailex 62534
相关产品推荐
相关产品推荐

