当前位置:首页 > 技术 > 正文内容

使用C#和Xamarin开发移动应用:相机二维码扫描基础

访客 技术 2026年10月16日 2

本文将介绍如何使用C#和Xamarin调用设备相机扫描二维码,并讲解相关的基础知识,包括相机预览、Activity跳转传值以及二维码的识别与读取。

1. 实现相机预览

首先,我们需要创建一个新的Activity,命名为 SaoYiSaoActivity,并为其准备一个布局文件 SaoYiSao.axml。在布局文件中,添加一个 SurfaceView控件,用于显示相机预览画面。为了让 SurfaceView铺满整个屏幕,可以设置其布局参数。

在 SaoYiSaoActivity 的 OnCreate 方法中,加载布局文件并初始化 SurfaceView:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.SaoYiSao);

    var surfaceView = FindViewById<SurfaceView>(Resource.Id.surfaceView1);
    var surfaceHolder = surfaceView.Holder;
    surfaceHolder.AddCallback(this); // 设置SurfaceHolder的回调为当前Activity
    surfaceHolder.SetType(SurfaceType.PushBuffers); // 表示Surface不包含原生数据
    surfaceHolder.SetFixedSize(300, 200); // 设置Surface的大小
}

为了处理相机预览和SurfaceView的生命周期事件,SaoYiSaoActivity 需要实现 Android.Hardware.Camera.IPreviewCallback 和 ISurfaceHolderCallback 接口。这些接口提供了 OnPreviewFrame, SurfaceChanged, SurfaceCreated, 和 SurfaceDestroyed 等方法。

实现 SurfaceCreated 方法来初始化相机:

public void SurfaceCreated(ISurfaceHolder holder)
{
    camera = Android.Hardware.Camera.Open(); // 打开相机
    var parameters = camera.GetParameters();
    parameters.PictureFormat = ImageFormatType.Jpeg; // 设置图片格式
    camera.SetParameters(parameters); // 应用相机参数
    camera.SetPreviewCallback(this); // 设置预览回调
    camera.SetPreviewDisplay(holder); // 设置预览Surface
    camera.StartPreview(); // 开始预览
}

实现 SurfaceDestroyed 方法来释放相机资源:

public void SurfaceDestroyed(ISurfaceHolder holder)
{
    holder.RemoveCallback(this);
    camera.SetPreviewCallback(null); // 移除预览回调
    camera.StopPreview(); // 停止预览
    camera.Release(); // 释放相机
    camera = null;
}

OnPreviewFrame(byte[] data, Android.Hardware.Camera camera) 方法会在每一帧预览画面被捕获时调用。data 参数包含了当前帧的图像数据。

2. Activity跳转与传值

为了从主界面跳转到 SaoYiSaoActivity 并接收扫描结果,我们可以在主界面的MainActivity中添加一个按钮,并为其添加点击事件处理:

btnScan.Click += delegate
{
    var intent = new Intent(this, typeof(SaoYiSaoActivity));
    intent.AddFlags(ActivityFlags.SingleTop); // 设置启动模式
    StartActivityForResult(intent, 1); // 启动Activity并设置请求码
};

要接收从 SaoYiSaoActivity 返回的数据,需要重写MainActivity的 OnActivityResult 方法:

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == Result.Ok)
    {
        var qrCodeData = data.GetStringExtra("code");
        // 在这里处理获取到的二维码数据,例如加载到WebView
        // webView.LoadUrl(qrCodeData);
        Toast.MakeText(this, "扫描结果: " + qrCodeData, ToastLength.Short).Show();
    }
}

3. 二维码识别与读取

在.NET生态中,常用的二维码解析库是 ZXing.Net。由于在移动端无法直接使用 System.Drawing (GDI+),因此选择 ZXing.Net.Mobile。可以在NuGet包管理器中搜索并安装 ZXing.Net.Mobile。

创建一个 CodeDecoder 方法来解析二维码:

public string CodeDecoder(byte[] data, int width, int height)
{
    // 创建YUV格式的源
    var source = new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
    // 二值化处理
    var bitmap = new BinaryBitmap(new HybridBinarizer(source));
    // 使用QRCodeReader进行解析
    var reader = new QRCodeReader();
    var result = reader.decode(bitmap);

    return result?.Text; // 返回解析到的文本,如果解析失败则返回null
}

在 SaoYiSaoActivity 的 OnPreviewFrame 方法中调用 CodeDecoder 来识别二维码:

public void OnPreviewFrame(byte[] data, Android.Hardware.Camera camera)
{
    try
    {
        var parameters = camera.GetParameters();
        int previewWidth = parameters.PreviewSize.Width;
        int previewHeight = parameters.PreviewSize.Height;

        var decodedData = CodeDecoder(data, previewWidth, previewHeight);

        if (decodedData != null)
        {
            // 解析成功,跳转回主界面并传递结果
            var intent = new Intent(this, typeof(MainActivity));
            intent.PutExtra("code", decodedData); // 传递解析结果
            SetResult(Result.Ok, intent); // 设置返回结果
            Finish(); // 关闭当前Activity
        }
    }
    catch (IOException)
    {
        // 处理可能的IO异常
    }
}

通过以上步骤,即可实现相机二维码扫描功能,并将扫描结果传递回主界面。

标签: C#Xamarin

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

PHPStan 有什么用?怎么用?

PHPStan 是一个 PHP 的静态分析工具,在不运行代码的情况下就能帮你发现潜在问题,比如:传错类型(把 string 传给接受 int 的函数)访问不存在的属性 / 方法null 没处理好永远不会执行到的代码数组 key/值类型不一致返回值不符合声明注释和真实类型不匹配它非常适合:想提升代码质量、减少线上 bug、统一团队风格的人(尤其是中大型项目)。一、PHPStan 有什么用(通俗点说)...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。