使用IronBarcode的MAUI條碼掃描器:逐步指南
行動應用程式越來越依賴條碼掃描進行庫存管理、銷售點系統和產品追蹤。 建立一個MAUI條碼掃描器可讓您將條碼檢測直接整合到您的.NET MAUI應用程式中,結合攝影機影片流和影像檔處理以檢測QR碼、Data Matrix和其他條碼格式。 雖然許多程式庫專注於攝像頭預覽,IronBarcode 即便在條件不利的情況下仍能準確讀取條碼——扭曲的角度、光線不佳和受損的標籤都能無需額外配置地處理。
這份指南將帶您完成如何在.NET MAUI專案中使用IronBarcode實現條碼掃描的每一步。 到最後,您將能夠從單一影像檔掃描多個條碼,從裝置攝像頭擷取條碼,並自信地將此程式庫整合到您自己的跨平台專案中。
建立MAUI條碼掃描器的前提條件是什麼?
在開始之前,請確保您的開發環境已準備就緒:
- Visual Studio 2022(v17.8或更新版本)已安裝.NET MAUI工作負載
- .NET 10 SDK -- 從官方.NET網站下載
- C# 基礎知識 -- 熟悉async/await模式會有所幫助
- 已配置用於相機測試的實體裝置或模擬器
- IronBarcode 授權 -- 可用於評估的免費試用
在建立專案之前,確保Visual Studio已安裝MAUI工作負載,這可大大節省日後的故障排除時間。 您可以在Visual Studio Installer中的 "個別組件"下搜尋 ".NET多平台應用程式UI開發"來驗證這一點。
了解IronBarcode如何融入MAUI
.NET MAUI 為您提供一個可目標Android、iOS、macOS和Windows的單一程式碼庫。 在這個環境中進行條碼掃描的挑戰在於每個平台處理攝影機存取的方式不同。 IronBarcode通過在圖像處理層上工作來解決這個問題——您通過MAUI的MediaPicker擷取圖像,然後將字節交給IronBarcode進行分析。
這種關注點分離使您的程式碼保持乾淨,並避免平台專用的條碼SDK。 IronBarcode的離線處理模式也意味著條碼資料永遠不會離開裝置,這對於受監管行業的應用程式很重要。
支持的條碼格式
IronBarcode支援多種格式,包括:
| 格式類別 | 格式 | 常見用途 |
|---|---|---|
| 1D 線性 | Code 128、Code 39、EAN-13、UPC-A、ITF | 零售、物流、醫療保健 |
| 2D 矩陣 | QR碼、Data Matrix、Aztec、PDF417 | 行動支付、票務、製造 |
| 郵政 | USPS、Royal Mail、Deutsche Post | 運輸和郵政服務 |
| 專用 | MaxiCode、GS1、MicroPDF417 | 供應鏈、運輸、包裹 |
如何設定MAUI條碼掃描項目?
首先在Visual Studio 2022中建立一個新的.NET MAUI應用專案。將其命名為BarcodeScannerApp,並選擇.NET 10作為目標框架。 Visual Studio 生成了標準的MAUI項目結構,帶有適用於Android、iOS、macOS和Windows的平台特定文件夾。
透過NuGet安裝IronBarcode
打開NuGet套件管理器控制台並運行:
Install-Package BarCode
或者在解決方案總管中右鍵點擊您的專案,選擇 "管理NuGet套件",搜尋IronBarCode,並安裝最新的穩定版。 對於.NET MAUI專案專門來說,IronBarcode的NuGet套件包含所有必要的本機依賴項。
激活您的授權
安裝後,請儘早在應用程式生命週期中使用您的授權金鑰激活IronBarcode。 最佳位置是在應用程式構建器運行之前的MauiProgram.cs中:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
從Iron Software網站獲取免費試用授權金鑰。試用金鑰允許您在開發期間無時間限制地評估所有功能,儘管輸出可能會在您應用完整授權之前包含試用浮水印。
如何為Android和iOS配置相機權限?
平台特定的相機權限對於條形碼掃描功能至關重要。 在MediaPicker.CapturePhotoAsync()成功之前,每個平台都需要在其清單文件中進行特定配置。
Android權限
編輯Platforms/Android/AndroidManifest.xml以聲明攝影機存取:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
android.permission.CAMERA條目從使用者請求運行時權限。 uses-feature聲明告知Google Play商店您的應用程式需要相機硬體和自動對焦功能。 沒有這些,Android裝置可能會批准許可請求,但仍會在內部阻止相機進入。
對於Android 13及更新版本(API等級33+),您可能還需要在ActivityCompat.RequestPermissions來處理細化的媒體權限。 MAUI的MediaPicker抽象自動處理大部分這些問題,但建議在發布前進行實體裝置測試。
iOS權限
修改Platforms/iOS/Info.plist以包括相機使用說明:
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to scan barcodes</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to scan barcodes</string>
iOS要求每個涉及隱私的許可都有可讀的說明。 如果此說明遺漏或含糊不清,蘋果的應用程式商店審核過程將拒絕您的應用。 該文字將首次顯示在應用請求相機存取時顯示給使用者的系統權限對話框中。
對於iPadOS,如果您計劃允許使用者從儲存的照片中掃描條碼,除了現場攝影機之外,還需要考慮新增NSPhotoLibraryUsageDescription。
Windows和macOS
對於Windows桌面和macOS目標,攝影機存取權限分別通過應用程式清單和權利檔案進行管理。 MAUI框架在模板級別處理大部分這些問題,但請確認Windows上的Package.appxmanifest包括攝像頭裝置功能。
如何建立條碼掃描器介面?
在MainPage.xaml中設計使用者介面,讓使用者在掃描過程中獲得明確的反饋。 一個簡約但功能齊全的佈局包括圖像預覽、結果顯示區及一個掃描觸發按鈕:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BarcodeScannerApp.MainPage"
Title="Barcode Scanner">
<VerticalStackLayout Padding="20" Spacing="20">
<Label Text="Point the camera at a barcode"
FontSize="16"
HorizontalOptions="Center"
TextColor="#555555" />
<Image x:Name="CapturedImage"
HeightRequest="300"
Aspect="AspectFit"
BackgroundColor="#F0F0F0" />
<Label x:Name="ResultLabel"
Text="Tap Scan to begin"
FontSize="18"
HorizontalOptions="Center"
FontAttributes="Bold" />
<Label x:Name="FormatLabel"
Text=""
FontSize="13"
HorizontalOptions="Center"
TextColor="#888888" />
<Button Text="Scan Barcode"
Clicked="OnScanClicked"
BackgroundColor="#007ACC"
TextColor="White"
CornerRadius="8"
HeightRequest="50" />
<Button Text="Load from Gallery"
Clicked="OnPickFromGalleryClicked"
BackgroundColor="#5C5C5C"
TextColor="White"
CornerRadius="8"
HeightRequest="50" />
</VerticalStackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BarcodeScannerApp.MainPage"
Title="Barcode Scanner">
<VerticalStackLayout Padding="20" Spacing="20">
<Label Text="Point the camera at a barcode"
FontSize="16"
HorizontalOptions="Center"
TextColor="#555555" />
<Image x:Name="CapturedImage"
HeightRequest="300"
Aspect="AspectFit"
BackgroundColor="#F0F0F0" />
<Label x:Name="ResultLabel"
Text="Tap Scan to begin"
FontSize="18"
HorizontalOptions="Center"
FontAttributes="Bold" />
<Label x:Name="FormatLabel"
Text=""
FontSize="13"
HorizontalOptions="Center"
TextColor="#888888" />
<Button Text="Scan Barcode"
Clicked="OnScanClicked"
BackgroundColor="#007ACC"
TextColor="White"
CornerRadius="8"
HeightRequest="50" />
<Button Text="Load from Gallery"
Clicked="OnPickFromGalleryClicked"
BackgroundColor="#5C5C5C"
TextColor="White"
CornerRadius="8"
HeightRequest="50" />
</VerticalStackLayout>
</ContentPage>
該佈局提供兩條掃描路徑:用攝影機擷取新照片,或從畫廊中選擇現有圖像。 這對於使用者提前拍攝條碼照片或通過電子郵件接收影像的工作流程來說很重要。 FormatLabel顯示已檢測的條形碼格式以及解碼值,這在除錯和使用者驗證時有所幫助。
新增掃描狀態反饋
為獲得精緻的體驗,請考慮將掃描按鈕包裹在正在進行中的ActivityIndicator中顯示。 IronBarcode的異步API使這變得簡單—您可以在呼叫finally中重置。
如何實現條碼讀取功能?
在MainPage.xaml.cs中實現核心掃描邏輯。 以下程式碼同時處理攝影機擷取和畫廊選擇,並具有適當的異步模式和錯誤處理:
using IronBarCode;
using IronSoftware.Drawing;
namespace BarcodeScannerApp;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnScanClicked(object sender, EventArgs e)
{
await ScanFromSource(() => MediaPicker.Default.CapturePhotoAsync());
}
private async void OnPickFromGalleryClicked(object sender, EventArgs e)
{
await ScanFromSource(() => MediaPicker.Default.PickPhotoAsync());
}
private async Task ScanFromSource(Func<Task<FileResult?>> sourceFunc)
{
try
{
var photo = await sourceFunc();
if (photo is null) return;
using var stream = await photo.OpenReadAsync();
using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
var imageBytes = memoryStream.ToArray();
// Show the captured image in the UI
CapturedImage.Source = ImageSource.FromStream(() =>
new MemoryStream(imageBytes));
// Process with IronBarcode
var bitmap = AnyBitmap.FromBytes(imageBytes);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = false
};
var results = await BarcodeReader.ReadAsync(bitmap, options);
if (results.Any())
{
var first = results.First();
ResultLabel.Text = $"Value: {first.Value}";
FormatLabel.Text = $"Format: {first.BarcodeType}";
}
else
{
ResultLabel.Text = "No barcode detected";
FormatLabel.Text = string.Empty;
}
}
catch (FeatureNotSupportedException)
{
await DisplayAlert("Unsupported",
"Camera is not available on this device.", "OK");
}
catch (PermissionException)
{
await DisplayAlert("Permission Required",
"Please grant camera permission in Settings.", "OK");
}
catch (Exception ex)
{
await DisplayAlert("Error",
$"Scanning failed: {ex.Message}", "OK");
}
}
}
using IronBarCode;
using IronSoftware.Drawing;
namespace BarcodeScannerApp;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnScanClicked(object sender, EventArgs e)
{
await ScanFromSource(() => MediaPicker.Default.CapturePhotoAsync());
}
private async void OnPickFromGalleryClicked(object sender, EventArgs e)
{
await ScanFromSource(() => MediaPicker.Default.PickPhotoAsync());
}
private async Task ScanFromSource(Func<Task<FileResult?>> sourceFunc)
{
try
{
var photo = await sourceFunc();
if (photo is null) return;
using var stream = await photo.OpenReadAsync();
using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
var imageBytes = memoryStream.ToArray();
// Show the captured image in the UI
CapturedImage.Source = ImageSource.FromStream(() =>
new MemoryStream(imageBytes));
// Process with IronBarcode
var bitmap = AnyBitmap.FromBytes(imageBytes);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = false
};
var results = await BarcodeReader.ReadAsync(bitmap, options);
if (results.Any())
{
var first = results.First();
ResultLabel.Text = $"Value: {first.Value}";
FormatLabel.Text = $"Format: {first.BarcodeType}";
}
else
{
ResultLabel.Text = "No barcode detected";
FormatLabel.Text = string.Empty;
}
}
catch (FeatureNotSupportedException)
{
await DisplayAlert("Unsupported",
"Camera is not available on this device.", "OK");
}
catch (PermissionException)
{
await DisplayAlert("Permission Required",
"Please grant camera permission in Settings.", "OK");
}
catch (Exception ex)
{
await DisplayAlert("Error",
$"Scanning failed: {ex.Message}", "OK");
}
}
}
Imports IronBarCode
Imports IronSoftware.Drawing
Namespace BarcodeScannerApp
Public Partial Class MainPage
Inherits ContentPage
Public Sub New()
InitializeComponent()
End Sub
Private Async Sub OnScanClicked(sender As Object, e As EventArgs)
Await ScanFromSource(Function() MediaPicker.Default.CapturePhotoAsync())
End Sub
Private Async Sub OnPickFromGalleryClicked(sender As Object, e As EventArgs)
Await ScanFromSource(Function() MediaPicker.Default.PickPhotoAsync())
End Sub
Private Async Function ScanFromSource(sourceFunc As Func(Of Task(Of FileResult?))) As Task
Try
Dim photo = Await sourceFunc()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using memoryStream = New MemoryStream()
Await stream.CopyToAsync(memoryStream)
Dim imageBytes = memoryStream.ToArray()
' Show the captured image in the UI
CapturedImage.Source = ImageSource.FromStream(Function() New MemoryStream(imageBytes))
' Process with IronBarcode
Dim bitmap = AnyBitmap.FromBytes(imageBytes)
Dim options = New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = False
}
Dim results = Await BarcodeReader.ReadAsync(bitmap, options)
If results.Any() Then
Dim first = results.First()
ResultLabel.Text = $"Value: {first.Value}"
FormatLabel.Text = $"Format: {first.BarcodeType}"
Else
ResultLabel.Text = "No barcode detected"
FormatLabel.Text = String.Empty
End If
End Using
End Using
Catch ex As FeatureNotSupportedException
Await DisplayAlert("Unsupported", "Camera is not available on this device.", "OK")
Catch ex As PermissionException
Await DisplayAlert("Permission Required", "Please grant camera permission in Settings.", "OK")
Catch ex As Exception
Await DisplayAlert("Error", $"Scanning failed: {ex.Message}", "OK")
End Try
End Function
End Class
End Namespace
此實現使用共享的ScanFromSource輔助方法,以避免在攝影機和畫廊路徑之間重複圖像處理邏輯。 AnyBitmap.FromBytes方法自動處理JPEG、PNG、WebP及其他常見圖像格式—無需手動格式檢測。
結果物件暴露於first.BarcodeImage(已檢測條形碼區域的裁剪圖像)等屬性。 查看BarcodeResult類文件以獲取完整列表。
測試您的掃描實現
有了程式碼後,您可以對標準條碼進行測試:

掃描後,解碼值顯示在螢幕上:

如何配置高級掃描選項?
IronBarcode提供了BarcodeReaderOptions物件,讓您可以針對特定使用案例微調檢測行為。 了解這些選項可以幫助您根據應用需要在速度和準確性之間取得平衡。
針對特定條碼型別
指定您預期的精確條碼型別會大大減少處理時間,因為IronBarcode會跳過不需要的格式檢查:
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128
};
var results = await BarcodeReader.ReadAsync(bitmap, options);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128
};
var results = await BarcodeReader.ReadAsync(bitmap, options);
Imports System.Threading.Tasks
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128
}
Dim results = Await BarcodeReader.ReadAsync(bitmap, options)

設置ExpectMultipleBarcodes = true指示IronBarcode在找到第一個結果後繼續掃描,這對於單個包裹單可能包含數十個條碼的倉庫工作流程至關重要。
讀取速度選項
QuickScan。 在條碼乾淨且光線良好的高容量場景下使用QuickScan。 當從低解析度攝影機擷取或已部分受損的標籤掃描時,切換到ExtremeDetail。
有關調整BarcodeReaderOptions的更多資訊,包括圖像校正過濾器和置信度門檻,文件提供詳細範例。
圖像校正和預處理
IronBarcode包括內建的圖像校正,能夠自動處理旋轉、傾斜或光線不佳的條碼。 您還可以通過BarcodeReaderOptions.ImageFilters手動應用預處理濾鏡:
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Detailed,
ImageFilters = new ImageFilterCollection
{
new SharpenFilter(),
new ContrastFilter(1.2f)
}
};
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Detailed,
ImageFilters = new ImageFilterCollection
{
new SharpenFilter(),
new ContrastFilter(1.2f)
}
};
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Detailed,
.ImageFilters = New ImageFilterCollection From {
New SharpenFilter(),
New ContrastFilter(1.2F)
}
}
當應用程式針對具有較低品質攝影機傳感器的舊型Android裝置目標時,或當使用者可能在倉庫或戶外等光線不佳的環境中拍攝條碼照片時,預處理濾鏡尤其有用。
如何處理常見故障排除場景?
即使配置良好的MAUI條碼掃描器,也可能因裝置特定行為、圖像質量問題或平台限制而出現問題。
攝影機無法打開
如果相機未能啟動,請核實在AndroidManifest.xml 和Info.plist中的權限聲明正確與否。 然後從乾淨的構建重新部署該應用,而不是熱重載。 在Android上,還需要檢查您的測試裝置是否使用非標準攝影機配置—有些裝置帶有多個攝影機需要顯式鏡頭選擇。
在模擬器上,不支持MediaPicker.CapturePhotoAsync()。 始終在實體裝置上測試相機功能。模擬器確實支持PickPhotoAsync用於畫廊選擇,您可以使用預載圖片進行基本的UI測試。
掃描精確度差
如果IronBarcode未返回結果或錯誤值,請嘗試以下調整:
- 將
ExtremeDetail - 向圖像濾鏡管道新增
ContrastFilter - 確保擷取的影像解析度至少為720p;較低的解析度會導致像Data Matrix這樣的密集格式漏檢
- 檢查條形碼型別是否包含於
ExpectBarcodeTypes遮罩中
IronBarcode的故障排除指南覆蓋了更多針對特定格式問題的診斷步驟。
記憶體管理
當大型相機影像載入到MemoryStream中時會消耗大量記憶體。 在所有流物件上始終使用using語句以確保釋放。 對於使用者順序掃描多個項目的連續掃描流程,在處理後還要顯式呼叫bitmap.Dispose(),而不是等待垃圾回收器。
在具有有限堆空間的Android裝置上,考慮在將影像傳遞給IronBarcode之前對其進行下採樣,前提是掃描的是乾淨、高對比度的條碼且不需要完整解析度以準確解碼。
平台特定的iOS行為
在iOS上,您第一次要求應用請求相機權限時,系統會顯示一次性對話框。 如果使用者拒絕,隨後呼叫CapturePhotoAsync 將拋出PermissionException。 通過使用AppInfo.ShowSettingsUI()將使用者導向至設定來處理這種情況。
確認Info.plist中然後才提交至App Store。 缺少隱私字串會導致自動拒絕,而不會詳細說明審核小組。 查看Apple介面使用者設計指南中的攝影機存取以獲取權限請求時機和訊息顯示的最佳實踐。
您的下一步是什麼?
現在您擁有IronBarcode的運行良好的MAUI條形碼掃描器,根據應用需求有幾種路徑可選:
- 生成條碼 -- IronBarcode 包含一個條形碼生成API 用於從字串資料建立QR碼、Code 128標籤和其他格式
- 批次掃描 -- 使用
ExpectMultipleBarcodes = true在迴圈中處理多個圖像檔; 查看批量掃描範例 - PDF條碼提取 -- 使用相同的
BarcodeReader類, IronBarcode可讀取嵌入於PDF文件中的條碼; 探索PDF條形碼讀取文件 - 樣式和品牌 -- 通過顏色、徽標和注釋自定義所生成條形碼的視覺輸出; 查看條形碼樣式選項
- 其他 Iron Software 產品 -- 如果您的MAUI應用同樣需要PDF生成、OCR或電子表格支持,您可以探索完整的Iron Suite以獲得一致的跨平台功能
首先以免費試用授權進行部署,在評估期內無限制。 了解生產環節的授權選擇和批量定價,請存取IronBarcode價格頁面。 IronBarcode文件門戶和IronBarcode GitHub資料庫提供其他程式碼範例和社群支援。
常見問題
使用IronBarcode作為MAUI條碼掃描器有何優勢?
IronBarcode在圖像層處理條碼,支持離線,支持超過30種格式,處理加工挑戰性條件,如傾斜角度和惡劣光線,無需額外配置。
IronBarcode能否在一個圖像中檢測多個條碼?
可以。在BarcodeReaderOptions中設置ExpectMultipleBarcodes = true,並調用BarcodeReader.ReadAsync。IronBarcode將在結果集合中返回所有檢測到的條碼。
如何在MAUI中為Android和iOS配置相機權限?
對於Android,將CAMERA uses-permission和uses-feature元件新增到AndroidManifest.xml中。對於iOS,請在Info.plist中新增帶有人類可讀解釋的NSCameraUsageDescription。
IronBarcode是否支持離線條碼掃描?
支持。IronBarcode完全在裝置上處理圖像,不會將資料發送到外部伺服器,這對於隱私敏感應用很重要。
在MAUI中,IronBarcode支持哪些條碼格式?
IronBarcode支持QR Code、Code 128、Code 39、EAN-13、UPC-A、Data Matrix、PDF417、Aztec、MaxiCode等多種格式。您可以通過BarcodeEncoding標誌鎖定特定格式。
如何提高劣質圖像的掃描準確度?
將ReadingSpeed切換至詳盡或極端詳細模式,新增SharpenFilter和ContrastFilter到ImageFilters中,並確保捕獲的圖像至少有720p的解析度。
IronBarcode能否從MAUI應用中的PDF文件中讀取條碼?
可以。IronBarcode的BarcodeReader類能夠使用相同的ReadAsync API提取嵌入在PDF文件中的條碼。
當拒絕相機存取時如何處理PermissionException?
在try/catch塊中捕獲PermissionException,並調用AppInfo.ShowSettingsUI()引導使用者到裝置設置中重新啟用相機存取。




