You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 14:12:16