Migrating fromGoogle ML KitBarcode Scanning to IronBarcode
Ten przewodnik jest przeznaczony dla zespołów znajdujących się w jednej z dwóch sytuacji: przenosicie aplikację na Androida do środowiska .NET MAUI lub .NET 9 i musicie zastąpić skaner kodów kreskowych ML Kit zarządzaną alternatywą, albo podczas dyskusji na temat skanowania kodów kreskowych na różnych platformach polecono wam Google ML Kit, a kiedy chcieliście dodać pakiet NuGet, okazało się, że on nie istnieje.
Google ML Kit BarCode Scanning to natywna biblioteka dla systemów Android i iOS. Jest dostarczany jako zależność Maven (com.google.mlkit:barcode-scanning:17.3.0 opakowana lub com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 nieopakowana) dla Kotlin/Java oraz jako CocoaPod (GoogleMLKit/BarcodeScanning) dla Swift. ML Kit od czerwca 2020 jest samodzielnym produktem i nie wymaga już Firebase, ale nie ma oficjalnego SDK dla .NET, nie ma dotnet add package google-mlkit-barcode ani API C# od Google. Społeczność tworzyła przez lata powiązania Xamarin/MAUI, ale łamią się one, gdy ML Kit aktualizuje swoje podłoże SDK.
IronBarcode to natywna biblioteka .NET, którą instaluje się z NuGet, integruje ze standardowymi wzorcami .NET i uruchamia na systemach Windows, Linux, macOS, Docker, Azure oraz AWS. Ten przewodnik pokazuje, jak przetłumaczyć wzorce napisane w Kotlinie lub Javie na równoważny kod w języku C#.
Kontekst przeniesienia
Podczas przenoszenia z ML Kit do IronBarcode zmienia się kilka elementów strukturalnych — nie tylko syntaktycznych:
Funkcje zwrotne stają się wartościami zwracanymi. ML Kit używa Androidowego API Task z addOnSuccessListener i addOnFailureListener. Funkcja BarcodeReader.Read() w IronBarcode zwraca zbiór synchronicznie. Wykonujesz to bezpośrednio. Bez rejestracji wywołań zwrotnych, bez koordynacji wątków.
Brak obiektu skanera. ML Kit wymaga zbudowania obiektu BarcodeScannerOptions, wywołania BarcodeScanning.getClient(options), aby uzyskać instancję skanera, a następnie wywołania scanner.process(inputImage).IronBarcode używa metod statycznych — BarcodeReader.Read() jest punktem wejścia. Nie ma żadnych instancji do zarządzania ani usuwania.
Brak konstrukcji InputImage. InputImage ML Kit musi być skonstruowany z źródła specyficznego dla Androida: InputImage.fromFilePath(context, uri), InputImage.fromBitmap(bitmap, rotation) lub InputImage.fromMediaImage(image, rotation).IronBarcode akceptuje ścieżkę do pliku jako ciąg znaków, Stream, byte[] lub System.Drawing.Bitmap. Bez kontekstu Androida, bez URI, bez metadanych dotyczących rotacji.
Brak Google Play Services. Bezpakietowy model ML Kit działa przez Google Play Services. Wariant pakietowy dostarcza model wewnątrz APK (dodając około 2,4 MB) i unika sprawdzania Play Services, ale żaden z wariantów nie jest dostępny na .NET.IronBarcode nie ma takich zależności — działa identycznie na każdej platformie obsługiwanej przez .NET.
Szybka konfiguracja w .NET
Usuń wszelkie pakiety powiązane z Xamarin/MAUI ML Kit, jeśli występują w Twoim projekcie, a następnie zainstaluj IronBarcode:
Dodaj klucz licencyjny na początku działania aplikacji — w Program.cs, MauiProgram.cs lub Startup.cs, w zależności od typu aplikacji:
// NuGet: dotnet add package BarCode
using IronBarCode;
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"Licencję można ustawić w dowolnym momencie przed pierwszym wywołaniem BarcodeReader.Read() lub BarcodeWriter.CreateBarcode(). Dostępna jest bezpłatna wersja próbna; W trybie próbnym pojawiają się znaki wodne na wygenerowanych BARCODACH, ale nie ograniczają one możliwości odczytu.
Odczytywanie BarCodes: z Kotlin do C#
Podstawowy odczyt pojedynczego BARCODE-a
Oto typowy kod ML Kit napisany w języku Kotlin, skanujący pojedynczy kod QR z adresu URI pliku:
// Android Kotlin — ML Kit
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val scanner = BarcodeScanning.getClient(options)
val inputImage = InputImage.fromFilePath(context, imageUri)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
val barcode = barcodes.firstOrNull()
if (barcode != null) {
Log.d("MLKit", "Value: ${barcode.rawValue}")
Log.d("MLKit", "Format: ${barcode.format}")
}
}
.addOnFailureListener { e ->
Log.e("MLKit", "Scan failed: ${e.message}")
}
Odpowiednik w języku C# z wykorzystaniem IronBarcode:
using IronBarCode;
try
{
var results = BarcodeReader.Read("captured-image.jpg");
var barcode = results.FirstOrDefault();
if (barcode != null)
{
Console.WriteLine($"Value: {barcode.Value}");
Console.WriteLine($"Format: {barcode.Format}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Scan failed: {ex.Message}");
}Imports IronBarCode
Try
Dim results = BarcodeReader.Read("captured-image.jpg")
Dim barcode = results.FirstOrDefault()
If barcode IsNot Nothing Then
Console.WriteLine($"Value: {barcode.Value}")
Console.WriteLine($"Format: {barcode.Format}")
End If
Catch ex As Exception
Console.WriteLine($"Scan failed: {ex.Message}")
End TryWynik jest dostępny natychmiast jako wartość zwracana. barcode.Value odpowiada barcode.rawValue. barcode.Format odpowiada barcode.format. Obsługa błędów wykorzystuje standardowy mechanizm try/catch zamiast oddzielnego modułu obsługi błędów.
Odczyt wielu BarCodes
ML Kit skanuje pojedynczy InputImage i zwraca listę. Dla wielu kodów kreskowych na jednym obrazie iteruj listę słuchacza sukcesów:
// Android Kotlin — ML Kit, multiple barcodes
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
.build()
val scanner = BarcodeScanning.getClient(options)
val inputImage = InputImage.fromFilePath(context, imageUri)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
val rawValue = barcode.rawValue
val format = barcode.format
processBarcode(rawValue, format)
}
}
.addOnFailureListener { e -> Log.e("MLKit", e.message ?: "Unknown error") }
W IronBarcode ustaw ExpectMultipleBarcodes = true w BarcodeReaderOptions i iteruj nad zbiorem wyników:
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read("warehouse-shelf.jpg", options);
foreach (var barcode in results)
{
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}");
ProcessBarcode(barcode.Value, barcode.Format);
}Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read("warehouse-shelf.jpg", options)
For Each barcode In results
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}")
ProcessBarcode(barcode.Value, barcode.Format)
NextSpecyfikacja formatu: ustaw setBarcodeFormats na BarcodeReaderOptions
ML Kit wymaga, abyś określił, które formaty szukać, za pomocą setBarcodeFormats(). Jeśli to pominiesz, ML Kit przeszuka wszystkie formaty.IronBarcode działa w ten sam sposób — pominięcie ograniczeń formatowych powoduje przeszukiwanie wszystkich danych, ale określenie oczekiwanych typów poprawia wydajność.
| ML Kit Kotlin | IronBarcode C# |
|---|---|
Barcode.FORMAT_QR_CODE | BarcodeEncoding.QRCode |
Barcode.FORMAT_CODE_128 | BarcodeEncoding.Code128 |
Barcode.FORMAT_CODE_39 | BarcodeEncoding.Code39 |
Barcode.FORMAT_CODE_93 | BarcodeEncoding.Code93 |
Barcode.FORMAT_EAN_13 | BarcodeEncoding.EAN13 |
Barcode.FORMAT_EAN_8 | BarcodeEncoding.EAN8 |
Barcode.FORMAT_UPC_A | BarcodeEncoding.UPCA |
Barcode.FORMAT_UPC_E | BarcodeEncoding.UPCE |
Barcode.FORMAT_PDF417 | BarcodeEncoding.PDF417 |
Barcode.FORMAT_DATA_MATRIX | BarcodeEncoding.DataMatrix |
Barcode.FORMAT_AZTEC | BarcodeEncoding.Aztec |
Barcode.FORMAT_ITF | BarcodeEncoding.ITF |
Barcode.FORMAT_CODABAR | BarcodeEncoding.Codabar |
Barcode.FORMAT_ALL_FORMATS | Pomiń ExpectBarcodeTypes |
Korzystanie z flag formatowania w IronBarcode:
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128 | BarcodeEncoding.EAN13
};
var results = BarcodeReader.Read("product-image.jpg", options);Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128 Or BarcodeEncoding.EAN13
}
Dim results = BarcodeReader.Read("product-image.jpg", options)Kombinacja bitowa OR działa tak samo jak lista formatów vararg w ML Kit.
Dostęp do wyników: rawValue i format
Obiekt wynikowy ML Kit udostępnia rawValue (jako String?) i format (jako stałą Int). Wynik IronBarcode udostępnia Value (jako string) i Format (jako wartość wyliczenia BarcodeEncoding).
//ML Kit Kotlin— result fields
val rawValue: String? = barcode.rawValue
val format: Int = barcode.format
val boundingBox: Rect? = barcode.boundingBox
val displayValue: String? = barcode.displayValue
//IronBarcode C#— result fields
string value = barcode.Value;
BarcodeEncoding format = barcode.Format;
int page = barcode.PageNumber; // populated for PDF / multi-page input
barcode.Value jest zawsze nienullowym ciągiem znaków w IronBarcode— jeśli odczyt się powiódł, wartość jest obecna. barcode.Format jest członkiem BarcodeEncoding enum, który można porównać bezpośrednio: if (barcode.Format == BarcodeEncoding.QRCode).
Czym wyróżnia się .NET
Synchroniczne API zamiast wywołań zwrotnych. Jest to najważniejsza zmiana strukturalna. scanner.process() ML Kit zwraca Task<List<Barcode>> w sensie Androida — należy łączyć słuchaczy. Wynik IronBarcode zwraca wynik w linii. Jeśli musisz uruchomić go poza wątkiem UI w aplikacji MAUI, opakuj go w Task.Run():
using IronBarCode;
// In a MAUI ViewModel or page code-behind
var results = await Task.Run(() => BarcodeReader.Read(imagePath));
foreach (var barcode in results)
{
// update UI on main thread
MainThread.BeginInvokeOnMainThread(() =>
{
ResultLabel.Text = barcode.Value;
});
}Imports IronBarCode
Imports System.Threading.Tasks
Imports Microsoft.Maui.Dispatching
' In a MAUI ViewModel or page code-behind
Dim results = Await Task.Run(Function() BarcodeReader.Read(imagePath))
For Each barcode In results
' update UI on main thread
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = barcode.Value
End Sub)
NextBrak parametru kontekstu. Każde wywołanie ML Kit, które tworzy InputImage, wymaga Androidowego Context.IronBarcode potrzebuje jedynie ścieżki do pliku lub strumienia. Usunięcie wątków kontekstowych z logiki BarCode znacznie upraszcza kod.
Brak usługi Google Play Services. Standardowy model ML Kit działa za pośrednictwem Play Services — BarcodeScanning.getClient() sprawdza dostępność Play Services w czasie rzeczywistym i zgłasza wyjątek, jeśli jest niedostępny.IronBarcode nie posiada funkcji sprawdzania usług w czasie wykonywania. Albo odczytuje obraz, albo zgłasza standardowy wyjątek.
Standardowe obsługiwanie wyjątków. addOnFailureListener ML Kit odbiera podklasę Java Exception. W .NET niepowodzenia pojawiają się jako standardowe wyjątki @@--CODE-1354@@, które można złapać za pomocą try/catch w normalny sposób.
Odczytywanie z dokumentów PDF
ML Kit nie obsługuje formatu PDF. InputImage.fromFilePath() z URI .pdf albo kończy się niepowodzeniem, albo odczytuje tylko pierwszą stronę jako rastryzowany obraz, w zależności od wersji Androida. Jeśli Twój scenariusz przenoszenia danych obejmuje dokumenty — przetwarzanie faktur, listy przewozowe, skanowanie formularzy —IronBarcode obsługuje pliki PDF natywnie:
using IronBarCode;
// Read all barcodes from all pages of a PDF
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read("invoice-batch.pdf", options);
foreach (var barcode in results)
{
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}");
}Imports IronBarCode
' Read all barcodes from all pages of a PDF
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read("invoice-batch.pdf", options)
For Each barcode In results
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}")
NextBez etapu wyodrębniania obrazów, bez biblioteki PDF innych firm, bez pętli iteracji stron z oddzielnym renderowaniem. Przekaż ścieżkę do pliku PDF, aby uzyskać wszystkie wartości BARCODE wraz z numerami stron.
Nowe możliwości: Generowanie
ML Kit nie generuje BARCODE-ów — jedynie je odczytuje. Jeśli przeniesiona aplikacja wymaga generowania etykiet, biletów lub kodów QR,IronBarcode obsługuje te funkcje w ramach tego samego pakietu.
Kod 128 dla etykiet wysyłkowych:
using IronBarCode;
BarcodeWriter.CreateBarcode("SHIP-2024-98341", BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.SaveAsPng("shipping-label.png");Imports IronBarCode
BarcodeWriter.CreateBarcode("SHIP-2024-98341", BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.SaveAsPng("shipping-label.png")Generowanie kodów QR:
using IronBarCode;
QRCodeWriter.CreateQrCode("https://example.com/track/98341", 500)
.SaveAsPng("tracking-qr.png");Imports IronBarCode
QRCodeWriter.CreateQrCode("https://example.com/track/98341", 500) _
.SaveAsPng("tracking-qr.png")Kod QR z logo i kolorem:
using IronBarCode;
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500)
.AddBrandLogo("company-logo.png")
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue)
.SaveAsPng("product-qr.png");Imports IronBarCode
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500) _
.AddBrandLogo("company-logo.png") _
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue) _
.SaveAsPng("product-qr.png")Zwróć BarCode jako tablicę bajtów w odpowiedzi HTTP:
using IronBarCode;
// In anASP.NET Corecontroller action
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ORDER-7734", BarcodeEncoding.QRCode)
.ToPngBinaryData();
return File(barcodeBytes, "image/png");
Żaden z tych wzorców nie ma odpowiednika w ML Kit. Są to nowe możliwości dostępne dzięki pracy w pełnej bibliotece BarCode .NET, a nie tylko w skanerze przeznaczonym wyłącznie dla urządzeń mobilnych.
Przetwarzanie wsadowe po stronie serwera
ML Kit przetwarza jeden obraz na wywołanie, wymaga środowiska uruchomieniowego Android/iOS i nie obsługuje wykonywania po stronie serwera.IronBarcode przetwarza pliki w pętli, działa w środowiskuASP.NET Corei skaluje się normalnie:
using IronBarCode;
// Process a folder of scanned document images
var imageFiles = Directory.GetFiles("/data/scans", "*.jpg");
var allResults = new List<(string File, string Value, BarcodeEncoding Format)>();
foreach (var file in imageFiles)
{
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Faster,
ExpectMultipleBarcodes = false
};
var results = BarcodeReader.Read(file, options);
foreach (var barcode in results)
{
allResults.Add((file, barcode.Value, barcode.Format));
}
}
// Write results to CSV, database, etc.
foreach (var (file, value, format) in allResults)
{
Console.WriteLine($"{file}: [{format}] {value}");
}Imports IronBarCode
Imports System.IO
' Process a folder of scanned document images
Dim imageFiles = Directory.GetFiles("/data/scans", "*.jpg")
Dim allResults = New List(Of (File As String, Value As String, Format As BarcodeEncoding))()
For Each file In imageFiles
Dim options = New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Faster,
.ExpectMultipleBarcodes = False
}
Dim results = BarcodeReader.Read(file, options)
For Each barcode In results
allResults.Add((file, barcode.Value, barcode.Format))
Next
Next
' Write results to CSV, database, etc.
For Each result In allResults
Console.WriteLine($"{result.File}: [{result.Format}] {result.Value}")
NextTen schemat — odczytanie folderu obrazów, wyodrębnienie BARCODE-ów, agregacja wyników — nie jest możliwy w ML Kit. Jest to standardowy proces IronBarcode.
Porównanie funkcji
| Funkcja | Google ML Kit | IronBarcode |
|---|---|---|
| Pakiet .NET NuGet | None | BarCode |
| API C# / .NET | None | Tak |
| Odczytywanie BarCode | Tak (Android/iOS) | Tak (wszystkie platformy) |
| Generowanie BarCode'ów | Nie | Tak |
| Generowanie kodów QR | Nie | Tak |
| Osadzanie logo QR | Nie | Tak |
| Plik wejściowy PDF | Nie | Tak |
| Obsługa dokumentów wielostronicowych | Nie | Tak |
| Wejście z kamery/klatki | Tak | Za pośrednictwem pliku graficznego |
| Wdrożenie po stronie serwera | Nie | Tak |
| ASP.NET Core | Nie | Tak |
| Azure Functions | Nie | Tak |
| Docker / Linux | Nie | Tak |
| Wymagane usługi Google Play | Tylko wariant bezpakietowy | Nie |
| Zależność Firebase | Nie (samodzielnie od czerwca 2020) | Nie |
| Synchroniczne API .NET | Nie | Tak |
| Obsługuje wstrzykiwanie zależności | Nie | Tak (statyczne API) |
ExpectMultipleBarcodes opcja | Poprzez listę wyników | BarcodeReaderOptions |
| Specyfikacja formatu | setBarcodeFormats() | ExpectBarcodeTypes |
| Kompromis między szybkością a dokładnością | Stałe (oparte na modelu) | ReadingSpeed enum |
| Ceny | Darmowe (na urządzaniu, tylko mobilne) | Od 749 dolarów (Lite) wieczysta |
| Platformy | Android, IOS | Windows, Linux, macOS, Docker, Azure, AWS |
Lista kontrolna migracji
Jeśli przenosisz kod źródłowy z Androida lub zastępujesz nieoficjalne powiązanie Xamarin ML Kit, przeszukaj swój projekt pod kątem tych wzorców i zastosuj powyższe tłumaczenia:
com.google.mlkit:barcode-scanningw plikach Gradle → usuń, dodajBarCodeNuGetBarcodeScannerOptions.Builder()→new BarcodeReaderOptions { }BarcodeScanning.getClient(options)→ usuń (brak instancji skanera w IronBarcode)InputImage.fromFilePath(context, uri)→ argument ścieżki do plikuInputImage.fromBitmap(bitmap, rotation)→BarcodeReader.Read(stream)lub przeciążenie tablicy bajtówscanner.process(inputImage)→BarcodeReader.Read(path, options).addOnSuccessListener { barcodes -> }→ iterują wartość zwracaną zRead().addOnFailureListener { e -> }→ try/catch wokółRead()barcode.rawValue→barcode.Valuebarcode.format→barcode.FormatBarcode.FORMAT_QR_CODE→BarcodeEncoding.QRCodeBarcode.FORMAT_CODE_128→BarcodeEncoding.Code128Barcode.FORMAT_ALL_FORMATS→ pomińExpectBarcodeTypesusing Google.MLKit.BarcodeScanning;(wiązanie Xamarin) →using IronBarCode;IronBarCode.License.LicenseKeypowinno być ustawione wMauiProgram.cs,Program.cslubStartup.cs
Głównym zadaniem jest zmiana struktury kodu z opartego na wywołaniach zwrotnych na synchroniczny. Stałe formatów i nazwy pól wynikowych są odwzorowaniami bezpośrednimi. Obsługa plików PDF i generowania jest czysto dodatkowa — nie wymaga migracji, a jedynie nowego kodu.

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podręczników.