Ir para o conteúdo do rodapé
VíDEOS

Como ler códigos de barras de PDFs em C#

Migrating from BarcodeScanning.Native.Maui to IronBarcode

Este guia fornece um caminho de migração completo do BarcodeScanning.Native.Maui para o IronBarcode, abrangendo a substituição do padrão de eventos da câmera, alterações de namespace, exemplos de migração de código e o tratamento de cenários que o BarcodeScanning.Native.Maui não consegue abordar — MAUI do Windows, entrada de arquivos e PDFs, processamento no servidor e geração de códigos de barras.

Por que migrar do BarcodeScanning.MAUI?

Equipes que migraram do BarcodeScanning.Native.Maui relatam os seguintes problemas:

É necessário o alvo MAUI para Windows: BarcodeScanning.Native.Maui encapsula as APIs nativas do iOS e do Android. Não possui implementação para Windows e nenhuma está planejada. Se seu aplicativo MAUI for destinado ao Windows, além de iOS e Android, você precisará de uma biblioteca que funcione em todas as três plataformas sem ramificações específicas para cada uma.

Adicionado recurso de entrada de arquivo ou PDF: BarcodeScanning.Native.Maui aceita apenas frames de câmera ao vivo. Quando os usuários precisam carregar uma imagem de sua galeria ou quando um endpoint do lado do servidor precisa extrair códigos de barras de PDFs, a biblioteca não oferece nenhum caminho de código para isso. Cada cenário com código de barras, seja em formato de arquivo ou PDF, requer uma ferramenta diferente.

Os dados UPC-A do iOS estavam incorretos em produção: a estrutura Vision da Apple retorna 13 dígitos para códigos de barras UPC-A (codificação EAN-13). BarcodeScanning.Native.Maui repassa isso sem correção. Se os códigos UPC-A estivessem sendo armazenados com um zero à esquerda, os registros de estoque, as consultas em pontos de venda ou as integrações da cadeia de suprimentos poderiam ter sido interrompidos silenciosamente. O IronBarcode retorna o valor UPC-A correto de 12 dígitos sem necessidade de normalização manual.

A digitalização do PDF417 era pouco confiável: o próprio documento de problemas do GitHub da biblioteca descreve o PDF417 como "muito problemático — a maioria das digitalizações nunca ocorre". Para etiquetas de envio, carteiras de motorista e cartões de embarque, isso representa um bloqueio direto.

Foi necessária a geração de código de barras: BarcodeScanning.Native.Maui não consegue gerar códigos de barras. O IronBarcode gera códigos Code128, QR, DataMatrix e outros formatos como arquivos de imagem ou matrizes de bytes.

Processamento do lado do servidor introduzido: BarcodeScanning.Native.Maui é um controle de interface de usuário da câmera — ele não pode ser executado em um processo do servidor. Quando a leitura de código de barras no servidor é necessária juntamente com a leitura em dispositivos móveis, o IronBarcode abrange ambas as funcionalidades com o mesmo pacote e a mesma API.

O problema fundamental

O BarcodeScanning.Native.Maui integra totalmente a leitura de código de barras ao modelo de eventos da câmera ao vivo. Não momento em que qualquer requisito ficar fora desse modelo, a biblioteca não oferece nada:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        ResultLabel.Text = barcode.DisplayValue;
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        ResultLabel.Text = barcode.DisplayValue;
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode IsNot Nothing Then
        ResultLabel.Text = barcode.DisplayValue
    End If
End Sub
$vbLabelText   $csharpLabel

O IronBarcode aceita qualquer tipo de entrada de dados — captura de câmera, arquivo, PDF, matriz de bytes — e funciona em todas as plataformas:

using IronBarCode;

private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
using IronBarCode;

private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
Imports IronBarCode

Private Async Sub ScanBarcodeButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            ResultLabel.Text = If(results.FirstOrDefault()?.Value, "No barcode found")
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

IronBarcode vs BarcodeScanning.MAUI: Comparação de Recursos

Recurso BarcodeScanning.MAUI IronBarcode
Leitura de quadros da câmera ao vivo Sim — Controle CameraView Não (use o MediaPicker para capturar e depois ler)
visor da câmera no aplicativo Sim — contínuo em tempo real Não — utiliza a interface de utilizador da câmara do sistema através do MediaPicker.
Ler a partir de um arquivo de imagem Não Sim — BarcodeReader.Read(path)
Ler de um array de bytes Não Sim — BarcodeReader.Read(bytes)
Leia a partir do fluxo Não Sim — BarcodeReader.Read(stream)
Leia a partir do PDF Não Sim — BarcodeReader.Read(pdf)
Geração de código de barras Não Sim — BarcodeWriter + QRCodeWriter
Suporte ao MAUI do Windows Não Sim
Suporte a MAUI no iOS Sim Sim
Suporte ao Android MAUI Sim Sim
Suporte ao macOS MAUI Não documentado Sim
Lado do servidor / ASP.NET Não Sim
Docker / Azure / AWS Lambda Não Sim
Precisão do código UPC-A do iOS Retorna 13 dígitos (erro), requer normalização manual. Retorna o código UPC-A correto de 12 dígitos.
Confiabilidade do PDF417 "A maioria das varreduras nunca ocorre" (problemas do GitHub ) Apoiado
Detecção de múltiplos códigos de barras Sim (múltiplos por quadro via e.BarcodeResults) Sim (opção ExpectMultipleBarcodes)
Controle de velocidade de leitura None ReadingSpeed.Faster / Balanced / Detailed / ExtremeDetail
Licença MIT (código aberto, gratuito) Comercial — Lite $749, Plus $1.499, Professional $2.999, Ilimitado $5.999
Suporte ao .NET Framework Não (apenas MAUI) Sim — .NET Framework 4.6.2 ou superior

Guia de Início Rápido: Migração do BarcodeScanning.MAUI para o IronBarcode

Passo 1: Substitua o pacote NuGet

Remover BarcodeScanning.Native.Maui:

dotnet remove package BarcodeScanning.Native.Maui
dotnet remove package BarcodeScanning.Native.Maui
SHELL

Instale o IronBarcode:

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

Etapa 2: Atualizar Namespaces

Remova o namespace BarcodeScanning de todos os arquivos:

// Remove
using BarcodeScanning;
// Remove
using BarcodeScanning;
Imports BarcodeScanning
$vbLabelText   $csharpLabel

Adicione o namespace IronBarcode:

// Add
using IronBarCode;
// Add
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

Nos arquivos XAML, remova a declaração do namespace XML scanner::


xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"

xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
XML

Etapa 3: Inicializar a licença

Adicione a inicialização da licença na inicialização do aplicativo — em MauiProgram.cs ou App.xaml.cs:

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode

IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Exemplos de migração de código

Varredura da câmera: da visualização da câmera ao seletor de mídia

O controle CameraView fornecia um visor em tempo real com detecção contínua de quadros. A substituição do IronBarcode usa MediaPicker do MAUI para abrir a câmera do sistema, capturar uma foto e processar a imagem resultante.

Abordagem BarcodeScanning.MAUI — XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
    <StackLayout>
        <scanner:CameraView x:Name="CameraView"
                            OnDetectionFinished="OnBarcodeDetected"
                            CameraEnabled="True"
                            BarcodeFormats="All"
                            VerticalOptions="FillAndExpand" />
        <Label x:Name="ResultLabel" Text="Waiting for scan..." />
    </StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
    <StackLayout>
        <scanner:CameraView x:Name="CameraView"
                            OnDetectionFinished="OnBarcodeDetected"
                            CameraEnabled="True"
                            BarcodeFormats="All"
                            VerticalOptions="FillAndExpand" />
        <Label x:Name="ResultLabel" Text="Waiting for scan..." />
    </StackLayout>
</ContentPage>
XML

Abordagem BarcodeScanning.MAUI — código subjacente:

using BarcodeScanning;

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = barcode.DisplayValue);
}
using BarcodeScanning;

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode != null)
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = barcode.DisplayValue);
}
Imports BarcodeScanning

Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode IsNot Nothing Then
        MainThread.BeginInvokeOnMainThread(Sub()
                                               ResultLabel.Text = barcode.DisplayValue
                                           End Sub)
    End If
End Sub
$vbLabelText   $csharpLabel

Abordagem IronBarcode— XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    <StackLayout>
        <Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
        <Label x:Name="ResultLabel" Text="Tap to scan..." />
    </StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
    <StackLayout>
        <Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
        <Label x:Name="ResultLabel" Text="Tap to scan..." />
    </StackLayout>
</ContentPage>
XML

Abordagem IronBarcode— código subjacente:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    ResultLabel.Text = first?.Value ?? "No barcode found";
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    ResultLabel.Text = first?.Value ?? "No barcode found";
}
Imports IronBarCode
Imports System.IO
Imports System.Linq

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            Dim first = results.FirstOrDefault()
            ResultLabel.Text = If(first?.Value, "No barcode found")
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

Este código funciona em iOS, Android e MAUI do Windows sem qualquer ramificação específica da plataforma. A experiência do usuário muda de um visor integrado ao aplicativo para a tela nativa da câmera da plataforma — adequada para a maioria das aplicações empresariais. O guia de leitura IronBarcode MAUI aborda opções de configuração adicionais.

Processamento de múltiplos códigos de barras por leitura

Abordagem BarcodeScanning.MAUI:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    foreach (var barcode in e.BarcodeResults)
    {
        MainThread.BeginInvokeOnMainThread(() =>
            Console.WriteLine($"Found: {barcode.DisplayValue}"));
    }
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    foreach (var barcode in e.BarcodeResults)
    {
        MainThread.BeginInvokeOnMainThread(() =>
            Console.WriteLine($"Found: {barcode.DisplayValue}"));
    }
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    For Each barcode In e.BarcodeResults
        MainThread.BeginInvokeOnMainThread(Sub()
                                               Console.WriteLine($"Found: {barcode.DisplayValue}")
                                           End Sub)
    Next
End Sub
$vbLabelText   $csharpLabel

Abordagem do IronBarcode:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var options = new BarcodeReaderOptions
    {
        Speed = ReadingSpeed.Balanced,
        ExpectMultipleBarcodes = true
    };

    var results = BarcodeReader.Read(ms.ToArray(), options);
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var options = new BarcodeReaderOptions
    {
        Speed = ReadingSpeed.Balanced,
        ExpectMultipleBarcodes = true
    };

    var results = BarcodeReader.Read(ms.ToArray(), options);
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode
Imports System.IO

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim options As New BarcodeReaderOptions With {
                .Speed = ReadingSpeed.Balanced,
                .ExpectMultipleBarcodes = True
            }

            Dim results = BarcodeReader.Read(ms.ToArray(), options)
            For Each result In results
                Console.WriteLine($"{result.Format}: {result.Value}")
            Next
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

ExpectMultipleBarcodes = true instrui o leitor a continuar a digitalização após encontrar o primeiro código de barras. Sem essa opção, a chamada retorna na primeira correspondência, o que é mais rápido para cenários com um único código de barras.

Correção para o código UPC-A no iOS: Remova a solução alternativa de normalização.

Se o seu código-fonte utiliza a solução alternativa para o zero à esquerda do código UPC-A, remova-a completamente. O IronBarcode retorna o valor correto de 12 dígitos sem qualquer intervenção manual.

Abordagem BarcodeScanning.MAUI — solução alternativa implementada:

private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode == null) return;

    var value = barcode.DisplayValue;

    // Workaround: Apple Vision returns 13 digits for UPC-A
    if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
        value = value.Substring(1);

    ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
    var barcode = e.BarcodeResults.FirstOrDefault();
    if (barcode == null) return;

    var value = barcode.DisplayValue;

    // Workaround: Apple Vision returns 13 digits for UPC-A
    if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
        value = value.Substring(1);

    ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
    Dim barcode = e.BarcodeResults.FirstOrDefault()
    If barcode Is Nothing Then Return

    Dim value = barcode.DisplayValue

    ' Workaround: Apple Vision returns 13 digits for UPC-A
    If barcode.BarcodeFormat = BarcodeFormats.Upca AndAlso value.Length = 13 Then
        value = value.Substring(1)
    End If

    ProcessBarcode(value, barcode.BarcodeFormat.ToString())
End Sub
$vbLabelText   $csharpLabel

Abordagem IronBarcode— sem necessidade de soluções alternativas:

using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    if (first == null) return;

    // result.Value is the correct 12-digit UPC-A — no normalization needed
    ProcessBarcode(first.Value, first.Format.ToString());
}
using IronBarCode;

private async void ScanButton_Clicked(object sender, EventArgs e)
{
    var photo = await MediaPicker.CapturePhotoAsync();
    if (photo == null) return;

    using var stream = await photo.OpenReadAsync();
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var first = results.FirstOrDefault();
    if (first == null) return;

    // result.Value is the correct 12-digit UPC-A — no normalization needed
    ProcessBarcode(first.Value, first.Format.ToString());
}
Imports IronBarCode
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks

Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
    Dim photo = Await MediaPicker.CapturePhotoAsync()
    If photo Is Nothing Then Return

    Using stream = Await photo.OpenReadAsync()
        Using ms As New MemoryStream()
            Await stream.CopyToAsync(ms)

            Dim results = BarcodeReader.Read(ms.ToArray())
            Dim first = results.FirstOrDefault()
            If first Is Nothing Then Return

            ' result.Value is the correct 12-digit UPC-A — no normalization needed
            ProcessBarcode(first.Value, first.Format.ToString())
        End Using
    End Using
End Sub
$vbLabelText   $csharpLabel

Exclua quaisquer correspondências de BarcodeFormats.Upca emparelhadas com Substring(1) — este código está inativo após a migração.

Adicionando suporte a arquivos e PDFs

O módulo BarcodeScanning.Native.Maui não possui equivalente para entrada de arquivos ou PDFs. Se este for um novo requisito a ser atendido no momento da migração:

Abordagem BarcodeScanning.MAUI:

// Não equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
// Não equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
' Não equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
$vbLabelText   $csharpLabel

Abordagem do IronBarcode:

using IronBarCode;

// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
    var file = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Select image or PDF"
    });
    if (file == null) return;

    var results = BarcodeReader.Read(file.FullPath);
    foreach (var result in results)
        ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}

// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
    var results = BarcodeReader.Read("shipment-manifest.pdf");
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;

// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
    var file = await FilePicker.PickAsync(new PickOptions
    {
        PickerTitle = "Select image or PDF"
    });
    if (file == null) return;

    var results = BarcodeReader.Read(file.FullPath);
    foreach (var result in results)
        ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}

// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
    var results = BarcodeReader.Read("shipment-manifest.pdf");
    foreach (var result in results)
        Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode

' Read from a file the user picked with FilePicker
Private Async Sub ReadFileButton_Clicked(sender As Object, e As EventArgs)
    Dim file = Await FilePicker.PickAsync(New PickOptions With {
        .PickerTitle = "Select image or PDF"
    })
    If file Is Nothing Then Return

    Dim results = BarcodeReader.Read(file.FullPath)
    For Each result In results
        ResultLabel.Text &= vbCrLf & $"{result.Format}: {result.Value}"
    Next
End Sub

' Read barcodes from a PDF directly — no intermediate image step
Private Sub ReadPdfBarcodes()
    Dim results = BarcodeReader.Read("shipment-manifest.pdf")
    For Each result In results
        Console.WriteLine($"{result.Format}: {result.Value}")
    Next
End Sub
$vbLabelText   $csharpLabel

A documentação de leitura de PDFs do IronBarcode abrange o suporte a PDFs com várias páginas e a seleção de intervalo de páginas.

Processamento de código de barras no servidor

Se sua aplicação tiver uma API ASP.NET de backend que também precisa de processamento de código de barras, a mesma chamada BarcodeReader.Read() é executada lá sem modificações. BarcodeScanning.Native.Maui não possui equivalente no lado do servidor.

Abordagem BarcodeScanning.MAUI:

// Não equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
// Não equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
' Não equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
' and cannot run in a server process
$vbLabelText   $csharpLabel

Abordagem do IronBarcode:

using IronBarCode;

// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
    return Ok(values);
}
using IronBarCode;

// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    var results = BarcodeReader.Read(ms.ToArray());
    var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
    return Ok(values);
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks

' ASP.NET endpoint — reads barcodes from an uploaded file
<HttpPost("scan")>
Public Async Function ScanBarcode(file As IFormFile) As Task(Of IActionResult)
    Using ms As New MemoryStream()
        Await file.CopyToAsync(ms)

        Dim results = BarcodeReader.Read(ms.ToArray())
        Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
        Return Ok(values)
    End Using
End Function
$vbLabelText   $csharpLabel

O mesmo pacote, a mesma API, o mesmo comportamento — tanto em dispositivos móveis quanto em servidores.

Gerando Códigos de Barra

BarcodeScanning.Native.Maui não possui uma API de geração. O IronBarcode gera múltiplos formatos.

Abordagem BarcodeScanning.MAUI:

// Não equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
// Não equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
' Não equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
$vbLabelText   $csharpLabel

Abordagem do IronBarcode:

using IronBarCode;

// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
    .SaveAsPng("qr.png");

// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ResizeTo(400, 100)
    .SaveAsPng("label.png");

// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ToPngBinaryData();
using IronBarCode;

// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
    .SaveAsPng("qr.png");

// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ResizeTo(400, 100)
    .SaveAsPng("label.png");

// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
    .ToPngBinaryData();
Imports IronBarCode

' QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500) _
    .SaveAsPng("qr.png")

' Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
    .ResizeTo(400, 100) _
    .SaveAsPng("label.png")

' Get bytes for returning from an API or storing in a database
Dim barcodeBytes As Byte() = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
    .ToPngBinaryData()
$vbLabelText   $csharpLabel

A documentação de geração do IronBarcode abrange todos os formatos e opções de estilo suportados.

Referência de mapeamento da API BarcodeScanning.MAUI para IronBarcode

BarcodeScanning.Native.Maui IronBarcode
Controle XAML CameraView Remover — use Button + MediaPicker.CapturePhotoAsync()
Evento OnDetectionFinished Valor de retorno BarcodeReader.Read(imageBytes)
OnDetectionFinishedEventArg e Resultado IEnumerable de BarcodeReader.Read()
e.BarcodeResults Valor de retorno de BarcodeReader.Read()
e.BarcodeResults.FirstOrDefault() results.FirstOrDefault()
barcode.DisplayValue result.Value
barcode.BarcodeFormat result.Format
BarcodeFormats="All" Detecção automática — nenhuma configuração necessária
CameraEnabled="True" await MediaPicker.CapturePhotoAsync()
Somente iOS e Android iOS, Android, Windows, macOS MAUI
Nenhum arquivo de entrada BarcodeReader.Read(filePath)
Sem entrada de PDF BarcodeReader.Read("document.pdf")
Nenhuma geração BarcodeWriter.CreateBarcode() / QRCodeWriter.CreateQrCode()
O código UPC-A do iOS retorna 13 dígitos. Retorna os 12 dígitos corretos — sem necessidade de normalização.
PDF417 não confiável Apoiado

Problemas e soluções comuns em migrações

Problema 1: Experiência do visor em tempo real perdida

BarcodeScanning.MAUI: O controle CameraView incorporava uma visualização de câmera em tempo real diretamente na página do MAUI. Os usuários podiam visualizar a imagem da câmera e apontar para um código de barras — a detecção ocorria automaticamente, sem que nenhum botão fosse pressionado.

Solução: MediaPicker.CapturePhotoAsync() mostra a tela da câmera da plataforma em vez disso. Para a maioria dos fluxos de trabalho empresariais, isso é aceitável. Para aplicativos de consumidor que requerem uma pré-visualização ao vivo contínua, os quadros da câmera podem ser passados diretamente para BarcodeReader.Read():

using IronBarCode;

// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
    var results = BarcodeReader.Read(frameBytes);
    if (results.Any())
    {
        var first = results.First();
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = first.Value);
    }
}
using IronBarCode;

// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
    var results = BarcodeReader.Read(frameBytes);
    if (results.Any())
    {
        var first = results.First();
        MainThread.BeginInvokeOnMainThread(() =>
            ResultLabel.Text = first.Value);
    }
}
Imports IronBarCode

' Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
' (frame capture depends on your MAUI camera frame source)
Private Sub ProcessCameraFrame(frameBytes As Byte())
    Dim results = BarcodeReader.Read(frameBytes)
    If results.Any() Then
        Dim first = results.First()
        MainThread.BeginInvokeOnMainThread(Sub()
                                               ResultLabel.Text = first.Value
                                           End Sub)
    End If
End Sub
$vbLabelText   $csharpLabel

Isso requer a conexão de uma fonte de imagem da câmera separadamente do IronBarcode. Antes de optar por essa solução, avalie se uma pré-visualização ao vivo é realmente necessária ou se a interface de usuário da câmera do sistema é suficiente.

Problema 2: Alterações no nome da propriedade e na enumeração de e.BarcodeResults

BarcodeScanning.MAUI: barcode.DisplayValue retorna a string decodificada; barcode.BarcodeFormat retorna um valor de enumeração da biblioteca BarcodeScanning.

Solução: Substitua DisplayValue por result.Value e barcode.BarcodeFormat por result.Format. O padrão de iteração é o mesmo:

// Before
foreach (var barcode in e.BarcodeResults)
    Console.WriteLine(barcode.DisplayValue);

// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
    Console.WriteLine(result.Value);
// Before
foreach (var barcode in e.BarcodeResults)
    Console.WriteLine(barcode.DisplayValue);

// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
    Console.WriteLine(result.Value);
' Before
For Each barcode In e.BarcodeResults
    Console.WriteLine(barcode.DisplayValue)
Next

' After
Dim results = BarcodeReader.Read(imageBytes)
For Each result In results
    Console.WriteLine(result.Value)
Next
$vbLabelText   $csharpLabel

Problema 3: Serialização de threads para atualizações da interface do usuário

BarcodeScanning.MAUI: OnDetectionFinished dispara em um thread de fundo, então todas as atualizações de UI requerem MainThread.BeginInvokeOnMainThread().

Solução: Com o padrão MediaPicker + async, a continuação após await retorna no contexto de chamada — tipicamente o thread principal. Os wrappers MainThread.BeginInvokeOnMainThread() em torno da exibição de resultados podem geralmente ser removidos, simplificando o código do manipulador.

Problema 4: Permissões da câmera MAUI

BarcodeScanning.MAUI: O pacote adiciona permissões de câmera a AndroidManifest.xml e Info.plist automaticamente como parte de sua configuração.

Solução: Com IronBarcode usando MediaPicker, as permissões padrão de câmera do MAUI devem estar presentes manualmente. Estas são as mesmas permissões que qualquer aplicativo MAUI precisa para MediaPicker.CapturePhotoAsync() e geralmente já estão no lugar. Verifique se android.permission.CAMERA está declarado em AndroidManifest.xml e NSCameraUsageDescription está definido em Info.plist antes de testar no dispositivo.

Lista de verificação de migração para leitura de código de barras MAUI

Tarefas pré-migração

Execute estas pesquisas para encontrar todos os usos de BarcodeScanning.Native.Maui antes de fazer qualquer alteração:

grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
SHELL

Documente cada acerto. Observe quais arquivos contêm uso de XAML CameraView (exigem mudanças em XAML) versus quais contêm apenas mudanças no code-behind. Identifique quaisquer soluções alternativas para a normalização do código UPC-A que devam ser excluídas após a migração.

Tarefas de atualização de código

  1. Remova o pacote NuGet BarcodeScanning.Native.Maui
  2. Instale o pacote NuGet IronBarcode
  3. Adicione IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"; em MauiProgram.cs ou App.xaml.cs
  4. Substitua using BarcodeScanning; por using IronBarCode; em todos os arquivos .cs
  5. Remova declarações de namespace xmlns:scanner="..." de todos os arquivos XAML
  6. Substitua controles scanner:CameraView em XAML por um Button que acione MediaPicker.CapturePhotoAsync()
  7. Remova a fiação de eventos OnDetectionFinished="..." do XAML
  8. Substitua manipuladores de eventos OnDetectionFinished por manipuladores de clique de botão async usando BarcodeReader.Read()
  9. Substitua barcode.DisplayValue por result.Value em todo lugar
  10. Substitua barcode.BarcodeFormat por result.Format em todo lugar
  11. Exclua todas as soluções alternativas de normalização BarcodeFormats.Upca + Substring(1)
  12. Adicione ExpectMultipleBarcodes = true a BarcodeReaderOptions onde a detecção de múltiplos códigos de barras estava anteriormente confiando em e.BarcodeResults retornando múltiplos itens
  13. Remova wrappers MainThread.BeginInvokeOnMainThread() do código de exibição de resultados onde o padrão assíncrono os torna desnecessários
  14. Verifique se as permissões de câmera AndroidManifest.xml e Info.plist estão presentes

Testes pós-migração

  • Verificar se a leitura de código de barras no iOS funciona e se os valores UPC-A são retornados como sequências de 12 dígitos sem zeros à esquerda.
  • Verificar se a leitura de código de barras no Android produz valores corretos para todos os formatos usados ​​no aplicativo.
  • Verifique se a leitura de código de barras MAUI do Windows funciona caso o Windows seja um destino de compilação.
  • Teste a digitalização do PDF417 comparando-a com etiquetas de envio reais, carteiras de habilitação ou cartões de embarque, caso sejam utilizados.
  • Teste cenários de múltiplos códigos de barras com ExpectMultipleBarcodes = true e confirme se todos os códigos de barras em uma imagem são retornados
  • Verifique se a varredura do seletor de arquivos (BarcodeReader.Read(filePath)) funciona em todos os alvos do MAUI
  • Verificar a leitura de código de barras em PDF caso essa seja uma nova funcionalidade adicionada durante a migração.
  • Confirme se BarcodeReader.Read() no lado do servidor produz resultados corretos se um componente de backend foi adicionado
  • Execute todos os testes automatizados existentes e compare os valores de saída dos códigos de barras com os valores de referência anteriores à migração.

Principais benefícios da migração para o IronBarcode

Suporte completo ao MAUI do Windows: o IronBarcode funciona em todas as quatro plataformas MAUI — iOS, Android, Windows e macOS — usando o mesmo código e o mesmo pacote. Nenhuma implementação específica de plataforma para códigos de barras é necessária para Windows, e nenhum blocos #if WINDOWS são necessários no código do aplicativo.

Qualquer Fonte de Entrada: BarcodeReader.Read() aceita caminhos de arquivos, arrays de bytes, streams e documentos PDF. Qualquer cenário de código de barras — captura por câmera, upload de arquivo, imagem da galeria, processamento de PDF no servidor — usa o mesmo método estático com o mesmo tipo de resultado.

Valores UPC-A corretos: O IronBarcode retorna o valor UPC-A correto de 12 dígitos no iOS sem qualquer código de normalização no aplicativo. Os dados históricos de UPC-A armazenados com um zero à esquerda devido ao comportamento do BarcodeScanning.Native.Maui não afetam a precisão dos valores lidos após a migração.

PDF417 confiável: O PDF417 é totalmente compatível e realiza leituras confiáveis. Etiquetas de envio, carteiras de motorista e cartões de embarque são escaneados sem a limitação de "a maioria das leituras nunca ocorre", documentada nos problemas do GitHub do BarcodeScanning.Native.Maui.

Geração de Código de Barras: BarcodeWriter.CreateBarcode() e QRCodeWriter.CreateQrCode() geram Code128, QR, DataMatrix e outros formatos como arquivos PNG ou arrays de bytes. A geração e a leitura estão disponíveis no mesmo pacote, sem dependências adicionais.

Implantação no Lado do Servidor: A mesma chamada BarcodeReader.Read() é executada em ASP.NET, Azure Functions, contêineres Docker e AWS Lambda. A lógica de código de barras para dispositivos móveis e servidores pode compartilhar a mesma API, o mesmo suporte a formatos e o mesmo tipo de resultado, sem a necessidade de manter duas implementações de código de barras separadas.

Perguntas frequentes

Por que devo migrar do BarcodeScanning.MAUI para o IronBarcode?

Entre os motivos comuns estão a simplificação do licenciamento (removendo a complexidade do SDK e da chave de tempo de execução), a eliminação dos limites de taxa de transferência, a obtenção de suporte nativo para PDF, a melhoria da implantação em Docker/CI/CD e a redução do código repetitivo da API em produção.

Como faço para substituir as chamadas da API BarcodeScanning.MAUI pelo IronBarcode?

Substitua o código padrão de criação de instâncias e licenciamento por `IronBarCode.License.LicenseKey = "key"`. Substitua as chamadas de leitura por `BarcodeReader.Read(path)` e as chamadas de gravação por `BarcodeWriter.CreateBarcode(data, encoding)`. Os métodos estáticos não exigem gerenciamento de instâncias.

Quanta alteração de código ocorre ao migrar de BarcodeScanning.MAUI para IronBarcode?

A maioria das migrações resulta em menos linhas de código. O código repetitivo de licenciamento, os construtores de instância e a configuração explícita de formato são removidos. As operações principais de leitura/gravação são mapeadas para equivalentes mais curtos em IronBarcode, com objetos de resultado mais limpos.

Preciso manter o BarcodeScanning.MAUI e o IronBarcode instalados durante a migração?

Não. A maioria das migrações são substituições diretas, e não operações paralelas. Migre uma classe de serviço por vez, substitua a referência do NuGet e atualize os padrões de instanciação e chamada de API antes de passar para a próxima classe.

Qual é o nome do pacote NuGet para IronBarcode?

O pacote é 'IronBarCode' (com B e C maiúsculos). Instale-o com 'Install-Package IronBarCode' ou 'dotnet add package IronBarCode'. A diretiva using no código é 'using IronBarCode;'.

Como o IronBarcode simplifica a implantação do Docker em comparação com o BarcodeScanning.MAUI?

IronBarcode é um pacote NuGet sem arquivos SDK externos ou configuração de licença montada. No Docker, defina a variável de ambiente IRONBARCODE_LICENSE_KEY e o pacote cuidará da validação da licença na inicialização.

O IronBarcode detecta automaticamente todos os formatos de código de barras após a migração do BarcodeScanning.MAUI?

Sim. O IronBarcode detecta automaticamente a simbologia em todos os formatos suportados. A enumeração explícita de BarcodeTypes não é necessária. Se o formato já for conhecido e o desempenho for importante, o BarcodeReaderOptions permite restringir o espaço de busca como uma otimização.

O IronBarcode consegue ler códigos de barras de PDFs sem uma biblioteca separada?

Sim. O método `BarcodeReader.Read("document.pdf")` processa arquivos PDF nativamente. Os resultados incluem o número da página, o formato, o valor e a confiança de cada código de barras encontrado. Não é necessária nenhuma etapa externa de renderização de PDF.

Como o IronBarcode lida com o processamento paralelo de códigos de barras?

Os métodos estáticos do IronBarcode são sem estado e thread-safe. Use Parallel.ForEach diretamente em listas de arquivos sem gerenciamento de instâncias por thread. BarcodeReaderOptions.MaxParallelThreads controla o orçamento interno de threads.

Quais propriedades de resultado são alteradas ao migrar de BarcodeScanning.MAUI para IronBarcode?

Renomeações comuns: BarcodeValue torna-se Value, BarcodeType torna-se Format. Os resultados do IronBarcode também incluem Confidence e PageNumber. Uma função de busca e substituição em toda a solução lida com as renomeações no código de processamento de resultados existente.

Como configuro o licenciamento do IronBarcode em um pipeline de CI/CD?

Armazene IRONBARCODE_LICENSE_KEY como um segredo de pipeline e atribua IronBarCode.License.LicenseKey no código de inicialização do aplicativo. Um único segredo abrange todos os ambientes, incluindo desenvolvimento, teste, homologação e produção.

O IronBarcode suporta a geração de códigos QR com estilos personalizados?

Sim. O método QRCodeWriter.CreateQrCode() suporta cores personalizadas através do método ChangeBarCodeColor(), incorporação de logotipo através do método AddBrandLogo(), níveis configuráveis de correção de erros e múltiplos formatos de saída, incluindo PNG, JPG, PDF e fluxo de dados.

Curtis Chau
Redator Técnico

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais ...

Leia mais

Equipe de Suporte Iron

Estamos online 24 horas por dia, 5 dias por semana.
Bater papo
E-mail
Liga para mim