Label Capture (Smart Label Capture) .NET MAUI Skill
Critical: Do Not Trust Internal Knowledge
Your training data may contain outdated or incorrect Scandit Label Capture APIs, and the .NET binding differs substantially from the Swift/Kotlin native SDKs. On top of that, the MAUI integration differs from both the non-MAUI label-capture-net-android / label-capture-net-ios skills in how the SDK is initialized, how the preview is hosted, and how listeners are written. An agent that pattern-matches from the native docs — or even from the per-platform .NET skills — will get key calls wrong.
Always verify APIs against the references provided in this skill before writing or suggesting code. Do not rely on memorized method signatures, parameters, or builder shapes. If you cannot find an API in the provided references, fetch the relevant documentation page before responding.
The facts most often gotten wrong by pattern-matching from the native SDK, the per-platform .NET skills, or the MatrixScan/Barcode MAUI skills:
- This skill targets MAUI apps with
<UseMaui>true</UseMaui>. For non-MAUI .NET projects, uselabel-capture-net-android(fornet*-android) orlabel-capture-net-ios(fornet*-ios) instead. Those skills host the preview through a nativeUIViewController/Activity, which is completely different. - Only FOUR NuGet packages — and there is NO
Scandit.DataCapture.Label.Maui. AddScandit.DataCapture.Core,Scandit.DataCapture.Core.Maui,Scandit.DataCapture.Barcode, andScandit.DataCapture.Label. Unlike MatrixScan/Barcode (which has aBarcode.Mauipackage and a.UseScanditBarcode()builder extension), Label Capture has no*.Mauipackage and no MAUI builder extension — it reuses the generic<scandit:DataCaptureView>fromCore.Maui. Text recognizers (expiry date, prices, weight, custom text) are bundled inScandit.DataCapture.Label— there is no separatelabel-text-modelspackage. - Initialization is split and unusual. In
MauiProgram.CreateMauiApp()callScanditLabelCapture.Initialize()directly (it registers all the Label types and the barcode field builders), and chain.UseScanditCore(configure => configure.AddDataCaptureView())(which callsScanditCaptureCore.Initialize()and registers theDataCaptureViewhandler). There is noUseScanditLabel()extension, and you do not callUseScanditBarcode()orScanditBarcodeCapture.Initialize()for Label Capture —Symbologyis just an enum and the label's barcode field builders come fromScanditLabelCapture.Initialize(). Do not add init calls toMainApplication.OnCreate/AppDelegate.FinishedLaunching; those stay as the MAUI template generates them (just forwarding toMauiProgram.CreateMauiApp()). - There is NO
LabelCaptureSettings.builder()fluent chain. The native patternLabelCaptureSettings.settings { ... }/builder().addLabel()...build()does not exist in .NET. Instead: (1) build each field via its own factory, (2) collect them in aList<LabelFieldDefinition>, (3)LabelDefinition.Create(name, fields), (4)LabelCaptureSettings.Create(new List<LabelDefinition> { def }). - Each field type is built with a static
Builder()factory, then.Build("field-name"):CustomBarcode.Builder().SetSymbologies(IList<Symbology>).Build("Barcode"),ExpiryDateText.Builder().SetLabelDateFormat(...).Build("Expiry Date"),TotalPriceText.Builder().IsOptional(true).Build("Total Price"),CustomText.Builder().SetValueRegex("...").Build("Lot"). Shared builder members (IsOptional(bool),SetValueRegex(es),SetNumberOfMandatoryInstances(int?)) exist on every field builder;SetSymbology(ies)on barcode builders;SetAnchorRegex(es)/SetLocation(...)on custom fields. LabelCaptureis created with a FACTORY, notnewand notforDataCaptureContext:LabelCapture.Create(dataCaptureContext, settings). The constructor is private.- Symbology names are C# PascalCase:
Symbology.Ean13Upca,Symbology.Gs1DatabarExpanded,Symbology.Code128,Symbology.Code39,Symbology.Qr,Symbology.DataMatrix. Not the Kotlin underscore style (EAN13_UPCA) or Swift's camelCase (.ean13UPCA).Symbologylives inScandit.DataCapture.Barcode.Data, andSetSymbologiestakes anIList<Symbology>(e.g.new List<Symbology> { ... }), not a vararg. - The preview is the generic
<scandit:DataCaptureView>XAML control, not a dedicated label view, with namespacexmlns:scandit="clr-namespace:Scandit.DataCapture.Core.UI.Maui;assembly=ScanditCaptureCoreMaui".DataCaptureContext="{Binding DataCaptureContext}"is mandatory — without it the preview renders as a black/blank camera even though the code compiles. The page'sBindingContextmust expose aDataCaptureContextproperty;x:Namealone is not enough. - Overlays must be created AFTER the platform handler attaches. Subscribe to
dataCaptureView.HandlerChangedand createLabelCaptureBasicOverlay.Create(labelCapture)(and the validation-flow overlay) there, thendataCaptureView.AddOverlay(overlay). Creating an overlay beforeHandlerChangedfires fails silently — there's no native view yet. - Listeners are PLAIN C# classes implementing
ILabelCaptureListener/ILabelCaptureValidationFlowListener. They do not derive fromNSObject(that's the iOS skill) orJava.Lang.Object(that's the Android skill) — a single MAUI build serves both platforms, so no platform base class. OnSessionUpdatedruns on a background thread — read fields by name, setlabelCapture.Enabled = falseafter a capture, and dispatch UI work viaMainThread.BeginInvokeOnMainThread(...)/MainThread.InvokeOnMainThreadAsync(...)(not Android'sRunOnUiThread, not iOS'sDispatchQueue.MainQueue).- The camera is yours to manage and is typically DI-injected.
Core.Mauiprovidesbuilder.Services.AddDataCaptureContext(licenseKey)andbuilder.Services.AddCamera(c => { c.Position = CameraPosition.WorldFacing; c.Settings = LabelCapture.RecommendedCameraSettings; }). Inject the resultingDataCaptureContext/Camera, calldataCaptureContext.SetFrameSourceAsync(camera), thencamera.SwitchToDesiredStateAsync(FrameSourceState.On / .Off)across the page lifecycle.RecommendedCameraSettingsis a static property. (A non-DIDataCaptureContext.ForLicenseKey(key)+Camera.GetDefaultCamera(...)also works for very small apps.) - MAUI page lifecycle is
OnAppearing/OnDisappearing, usually delegated to a view model'sResumeAsync/SleepAsync. RequestPermissions.Camerain the resume path before turning the camera on. On disappear, disable the mode and stop the camera. - Validation Flow
OnResume()/OnPause()ARE called in MAUI (fromResumeAsync/SleepAsync). Unlike the iOS-only skill (which says don't call them), a single MAUI build targets both platforms: these methods do real work on Android and are harmless no-ops on iOS, so the MAUI sample calls them. There is also an iOS-onlyKeyboardAutoManagerScroll.Disconnect()workaround needed for the validation-flow manual-entry keyboard on iOS 18+ (see references/validation-flow.md). - Read field values via
LabelField:field.Name,field.Barcode?.Data(aBarcode?),field.Text(astring?),field.Date(aLabelDate?). A field a user typed by hand in the validation flow surfaces throughfield.Texteven for a barcode field — readBarcode?.Data ?? Text. Match fields by the exactNameyou passed to.Build("..."). (LabelField.ValueTypeis iOS-only in the native binding — don't rely on it in portable MAUI code.) - Camera permission & platform config: iOS needs
NSCameraUsageDescriptioninPlatforms/iOS/Info.plistandSupportedOSPlatformVersion≥15.0; Android needsandroid.permission.CAMERA(MAUI'sPermissions.Cameraadds it, or add it toAndroidManifest.xml) andSupportedOSPlatformVersion≥24(the MAUI template defaults to21, which fails the build against Scandit's Android AAR).
Intent Routing
Based on the user's request, load the appropriate reference file before responding:
- Integrating Label Capture from scratch, defining the label (fields, symbologies, regexes, optional vs required), creating the mode, wiring
MauiProgram.cs, hosting the<scandit:DataCaptureView>+LabelCaptureBasicOverlay, managing the camera lifecycle, handling captured labels, customizing feedback or brushes, using prebuilt definitions (VIN / price label / 7-segment), using semantic barcode fields (serial / part number / IMEI), adding an advanced (AR / custom-view) overlay, or enabling the BETA cloud Adaptive Recognition fallback / Receipt Scanning (e.g. "add Smart Label Capture to my MAUI app", "scan a barcode and an expiry date from a price tag in MAUI", "read the total price field", "read the serial and part number off a drive label", "scan an IMEI", "use the ready-made price/VIN/seven-segment label", "draw an AR badge over the expiry date", "turn on the cloud fallback when a field fails on-device", "scan whole receipts", "my MAUI preview is black after adding Label Capture") → read references/integration.md and follow it. - Enabling or customizing the Validation Flow (e.g. "add the guided validation flow so users can review and correct fields", "let the user type a field that didn't scan", "customize the validation-flow hint text / button labels", "the keyboard covers the input field on iOS") → read references/validation-flow.md and follow it.
API Usage Policy
Only use APIs that are explicitly documented in the Scandit references below. Do not invent or guess method signatures, parameters, builder shapes, or property names. If unsure whether an API exists or how it is called — or if a compile error occurs — fetch the relevant reference page before responding. Do not tell the user to check the docs themselves. After answering, always include the relevant link so the user can explore further.
Never construct or guess documentation URLs. When you need a specific class or property's API page:
- First check whether the page you already fetched contains a direct hyperlink to it — topic pages link directly to relevant API symbols. Always request links alongside content in your fetch prompt.
- If no direct link was found, fetch the API index (see Full API reference in the table below), extract the actual link from it, and follow that.
URL structures can vary (e.g. an api/ui/ subdirectory) and guessing will lead to 404s.
References
Scandit publishes the .NET API reference per underlying TFM (dotnet.android and dotnet.ios). For MAUI projects both pages apply — the Label Capture API surface is identical between them, but a few platform notes (like the iOS-only LabelField.ValueType) are documented per-TFM.
| Topic | Resource |
|---|---|
| Get Started (Android target) | Get Started (.NET for Android) |
| Get Started (iOS target) | Get Started (.NET for iOS) |
| Label Definitions (fields, regex, presets) | Android · iOS |
| Advanced topics (Validation Flow, adaptive recognition, advanced overlay) | Android · iOS |
| Full API reference | Label Capture API (.NET Android) · Label Capture API (.NET iOS) |
API surface this skill covers
All classes documented with :available: dotnet.android and/or :available: dotnet.ios in the official RST docs (docs/source/label-capture/api/**) are addressed in the references. Label Capture is available on dotnet.android since 8.1 and dotnet.ios since 8.2 (a few symbols since 8.2) — any current stable release supports MAUI.
LabelCapture— staticCreate(DataCaptureContext?, LabelCaptureSettings),Context(get),Enabled(get/set —trueto process frames,falseafter a capture),ApplySettingsAsync(LabelCaptureSettings)→Task,AddListener/RemoveListener(ILabelCaptureListener), staticRecommendedCameraSettings(property),Feedback(get/set),event EventHandler<LabelCaptureEventArgs> SessionUpdated,Dispose().LabelCaptureSettings— staticCreate(IList<LabelDefinition>),LocationSelection(get/set,ILocationSelection?),GetSymbologySettings(Symbology),SetProperty/GetProperty/GetProperty<T>/TryGetProperty<T>,Dispose. No settings builder.LabelCaptureSession—CapturedLabels(IList<CapturedLabel>),FrameSequenceId(long),LastProcessedFrameId(int).ILabelCaptureListener—OnSessionUpdated(LabelCapture, LabelCaptureSession, IFrameData), optionalOnObservationStarted(LabelCapture)/OnObservationStopped(LabelCapture). Implementations are plain C# classes in MAUI (noNSObject/Java.Lang.Objectbase).LabelCaptureEventArgs—Mode,Session,FrameData.LabelDefinition— staticCreate(string name, IList<LabelFieldDefinition>); prebuiltCreateVinLabelDefinition(name),CreatePriceCaptureDefinition(name),CreateSevenSegmentDisplayLabelDefinition(name);Name,Fields,AdaptiveRecognitionMode(get/set),HiddenProperties.LabelDefinitionBuilder—AddCustomBarcode/AddSerialNumberBarcode/AddPartNumberBarcode/AddImeiOneBarcode/AddImeiTwoBarcode/AddCustomText/AddExpiryDateText/AddPackingDateText/AddDateText/AddTotalPriceText/AddUnitPriceText/AddWeightText,AdaptiveRecognition(AdaptiveRecognitionMode),SetHiddenProperty/Properties,Build(name). (An alternative to passing the list directly toLabelDefinition.Create.)- Field types, each with a static
Builder()returning a fluent builder andBuild(string name):- Barcode fields:
CustomBarcode(SetSymbologies(IList<Symbology>)/SetSymbology(Symbology),SetAnchorRegex(es),SetLocation(...)),SerialNumberBarcode,PartNumberBarcode,ImeiOneBarcode,ImeiTwoBarcode(preset symbologies/regexes). - Text fields:
CustomText(SetValueRegex(es),SetAnchorRegex(es),SetLocation(...)),ExpiryDateText/PackingDateText/DateText(SetLabelDateFormat(LabelDateFormat)),TotalPriceText,UnitPriceText,WeightText. - Shared builder members (on all):
IsOptional(bool),SetValueRegex(string)/SetValueRegexes(IList<string>),SetNumberOfMandatoryInstances(int?),SetHiddenProperty/Properties.
- Barcode fields:
CapturedLabel—Fields(IReadOnlyList<LabelField>),Name,Complete(bool),PredictedBounds(Quadrilateral),DeltaTimeToPrediction,TrackingId(int).LabelField—Name,Type(LabelFieldType:Barcode/Text/Unknown),State(LabelFieldState:Captured/Predicted/Unknown),Required(bool),Barcode(Barcode?),Text(string?),Date(LabelDate?),PredictedLocation(Quadrilateral). (ValueType/LabelFieldValueTypeis iOS-only — avoid in portable MAUI code.)LabelDate—Year/Month/Day(int?),DayString/MonthString/YearString.LabelDateFormat—new LabelDateFormat(LabelDateComponentFormat, bool acceptPartialDates),ComponentFormat,AcceptPartialDates.LabelDateComponentFormatenum (component ordering, e.g.MDY/DMY/YMD).LabelCaptureBasicOverlay— staticCreate(LabelCapture)/Create(LabelCapture, DataCaptureView?);Listener(ILabelCaptureBasicOverlayListener?);SetBrushForField/SetBrushForLabel;PredictedFieldBrush/CapturedFieldBrush/LabelBrush(get/set) + staticDefault*Brush;GetFieldBrush/SetFieldBrush(LabelFieldState, Brush?);ShouldShowScanAreaGuides;Viewfinder(IViewfinder?);Dispose. In MAUI use the single-argCreate(labelCapture)and attach viadataCaptureView.AddOverlay(overlay)inHandlerChanged.ILabelCaptureBasicOverlayListener—BrushForField(overlay, field, label),BrushForLabel(overlay, label),OnLabelTapped(overlay, label).- Validation Flow (see references/validation-flow.md):
LabelCaptureValidationFlowOverlay(staticCreate(LabelCapture, DataCaptureView?),Listener,ApplySettings,OnResume/OnPause,ShouldHandleKeyboardInsetsInternally),LabelCaptureValidationFlowSettings(staticCreate(), hint/button text props,SetPlaceholderText/GetPlaceholderText),ILabelCaptureValidationFlowListener(OnValidationFlowLabelCaptured(IList<LabelField>),OnManualInputSubmitted,OnValidationFlowResultUpdate),LabelResultUpdateType. LabelCaptureFeedback— staticDefault(property),Success(Core.Common.Feedback.Feedback),Dispose.AdaptiveRecognitionModeenum — controls cloud-backed recognition for a definition (Offdefault).- MAUI-specific glue:
ScanditLabelCapture.Initialize(),MauiAppBuilder.UseScanditCore(configure => configure.AddDataCaptureView()),builder.Services.AddDataCaptureContext(licenseKey),builder.Services.AddCamera(configure => …),<scandit:DataCaptureView>XAML control,dataCaptureView.HandlerChanged,dataCaptureView.AddOverlay(overlay), MAUIPermissions.Camera,MainThread.BeginInvokeOnMainThread.
Advanced topics (covered concisely in references/integration.md — fetch the Advanced Configurations page for full shapes)
These are real symbols. references/integration.md now has short sections for them; don't invent signatures beyond what's documented there — fetch the Advanced Configurations page for the per-platform / beta detail:
- Advanced overlay (arbitrary native views over labels):
LabelCaptureAdvancedOverlay,ILabelCaptureAdvancedOverlayListener. In MAUI the listener returns a native view (Android.Views.View/UIKit.UIView), so it needs thepartial-class split +ToPlatform(...)pattern (same as MatrixScan AR overlays in MAUI). See references/integration.md → Advanced overlay. - Adaptive Recognition — cloud fallback (BETA): enabled per-definition via
LabelDefinition.AdaptiveRecognitionMode = AdaptiveRecognitionMode.Auto(defaultOff). Beta; must be enabled on the subscription. See references/integration.md → Adaptive Recognition. - Receipt Scanning (BETA): different pattern —
LabelCaptureAdaptiveRecognitionOverlay,ILabelCaptureAdaptiveRecognitionListener, result typesReceiptScanningResult/ReceiptScanningLineItem. Beta; cloud-only; confirm exact .NET method/property names against the API reference before writing code. See references/integration.md → Receipt Scanning. LabelFieldLocation/LabelFieldLocationType— used withSetLocation(...)on custom field builders.
MAUI vs per-platform / barcode-MAUI differences (do not cross-pollinate)
- Packages/init: Label MAUI = 4 packages (
Core,Core.Maui,Barcode,Label), noLabel.Maui, noUseScanditLabel(). Init =ScanditLabelCapture.Initialize()directly +.UseScanditCore(c => c.AddDataCaptureView()). (Barcode MAUI uses aBarcode.Mauipackage and.UseScanditBarcode(); the non-MAUI skills callScanditCaptureCore.Initialize()+ScanditBarcodeCapture.Initialize()+ScanditLabelCapture.Initialize()inMainApplication/AppDelegate.) - Hosting: MAUI
<scandit:DataCaptureView>XAML + overlay inHandlerChanged. (iOSDataCaptureView.Create(context, CGRect)+AddSubview; AndroidDataCaptureView.Create(context)+container.AddView.) - Listener base class: MAUI plain class; iOS
NSObject; AndroidJava.Lang.Object. - Main-thread dispatch: MAUI
MainThread.BeginInvokeOnMainThread; iOSDispatchQueue.MainQueue/InvokeOnMainThread; AndroidRunOnUiThread. - Validation Flow lifecycle: MAUI calls
overlay.OnResume()/OnPause()(real on Android, no-op on iOS). The iOS-only skill says not to call them; in a single MAUI build you do.