Label Capture (Smart Label Capture) .NET for Android 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 Kotlin/Java native Android SDK. An agent that pattern-matches from the native Android (Kotlin) Label Capture docs will get nearly every call wrong, because the .NET binding does not use the Kotlin fluent settings builder — it builds each field with a per-field factory and assembles a list of definitions.
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 .NET-Android-specific facts most often gotten wrong by pattern-matching from the Kotlin/iOS SDK:
- This skill targets the non-MAUI .NET for Android workload (project
<TargetFramework>net10.0-android</TargetFramework>or similar, no<UseMaui>flag). For MAUI apps, theDataCaptureViewis hosted as a XAML element and wired through handlers — completely different. If you see<UseMaui>true</UseMaui>, stop and tell the user this skill does not apply. - There is NO
LabelCaptureSettings.builder()fluent chain. The Kotlin patternLabelCaptureSettings.builder().addLabel().addCustomBarcode().setSymbologies(...).buildFluent("x").buildFluent("label").build()does not exist in .NET. Instead you: (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"). The builder is shared-generic, soIsOptional(bool),SetValueRegex(es),SetNumberOfMandatoryInstances(int?)are available 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. They are not the Kotlin underscore style (EAN13_UPCA).Symbologylives inScandit.DataCapture.Barcode.Data. SetSymbologiestakes anIList<Symbology>(e.g.new List<Symbology> { ... }), not a vararg. For one symbology useSetSymbology(Symbology).- Only THREE NuGet packages, no separate text-models package.
Scandit.DataCapture.Core,Scandit.DataCapture.Barcode, andScandit.DataCapture.Label. Text fields (expiry date, price, weight, custom text) are bundled inScandit.DataCapture.Label— there is nolabel-text-modelsartifact like on native Android. (Barcodeis always required becauseSymbologyand the barcode field types live there.) - SDK 8.0+ requires explicit initialization with THREE initializers in a
[Application]subclass:ScanditCaptureCore.Initialize(),ScanditBarcodeCapture.Initialize(), andScanditLabelCapture.Initialize()inOnCreate(). Missing the Label one crashes the firstLabelCapture.Create(...)call. Label Capture is only available ondotnet.androidsince 8.1, so this initializer always applies. - The view is a generic
DataCaptureView, not a dedicated label view.DataCaptureView.Create(dataCaptureContext), add it to your layout withcontainer.AddView(...), thendataCaptureView.AddOverlay(overlay). The overlay is created withLabelCaptureBasicOverlay.Create(labelCapture)(single-arg; the constructor does not require the view). There is noLabelCaptureBasicOverlay.newInstance(mode, view)two-arg native shape — useCreate(labelCapture)thenAddOverlay. - You manage the camera yourself.
Camera.GetDefaultCamera(LabelCapture.RecommendedCameraSettings),dataCaptureContext.SetFrameSourceAsync(camera), thencamera.SwitchToDesiredStateAsync(FrameSourceState.On)/FrameSourceState.Offacross the lifecycle.RecommendedCameraSettingsis a static property onLabelCapture, not a method. ILabelCaptureListener.OnSessionUpdated(LabelCapture, LabelCaptureSession, IFrameData)is the result callback (plus optionalOnObservationStarted/OnObservationStopped). The idiomatic C# alternative is thelabelCapture.SessionUpdatedevent (EventHandler<LabelCaptureEventArgs>).OnSessionUpdatedruns on a background thread — dispatch UI work to the main thread, and setlabelCapture.Enabled = falseafter a successful capture to avoid re-capturing the same label.- Read field values via
LabelField:field.Name,field.Barcode?.Data(aBarcode?),field.Text(astring?),field.Date(aLabelDate?withYear/Month/Dayints and*Stringaccessors). Match fields by the exactNameyou passed to.Build("...").CapturedLabelexposesFields,Name,Complete,TrackingId.LabelCaptureSession.CapturedLabelsis anIList<CapturedLabel>. LabelCaptureFeedbackexposes a singleSuccessslot (Core.Common.Feedback.Feedback) plus the staticLabelCaptureFeedback.Default(a property). To customize:var fb = LabelCaptureFeedback.Default; fb.Success = new Feedback(Vibration.DefaultVibration, null); labelCapture.Feedback = fb;.- Android
SupportedOSPlatformVersionmust be ≥24; the activity must use aTheme.AppCompatdescendant (theCameraPermissionActivityhelper inherits fromAppCompatActivity); and do not declare<activity>for[Activity]-decorated classes inAndroidManifest.xml. Same Android plumbing as any Scandit .NET Android app — see references/integration.md.
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, hosting the
DataCaptureView+LabelCaptureBasicOverlay, wiring the camera lifecycle, handling captured labels, customizing feedback or brushes, or using prebuilt definitions (VIN / price label / 7-segment) (e.g. "add Smart Label Capture to my .NET Android app", "scan a barcode and an expiry date from a price tag in C#", "read the total price field", "use the recommended camera settings") → 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") → 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
Direct users to the right resource based on their question:
| Topic | Resource |
|---|---|
| Get Started | Get Started (.NET for Android) |
| Label Definitions (fields, regex, presets) | Label Definitions |
| Advanced topics (Validation Flow, adaptive recognition, advanced overlay) | Advanced Configurations |
| Full API reference | Label Capture API (.NET Android) |
API surface this skill covers
All classes documented with :available: dotnet.android 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 (a few symbols since 8.2).
LabelCapture— staticCreate(DataCaptureContext?, LabelCaptureSettings),Context(get),Enabled(get/set — settrueto 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).LabelCaptureEventArgs—Mode,Session,FrameData.LabelDefinition— staticCreate(string name, IList<LabelFieldDefinition>); prebuiltCreateVinLabelDefinition(name),CreatePriceCaptureDefinition(name),CreateSevenSegmentDisplayLabelDefinition(name)(8.2);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). (ValueTypeis iOS-only.)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.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).
Advanced topics (available on dotnet.android but intentionally deferred to the docs)
These are real dotnet.android symbols but out of scope for a first integration — don't invent their shapes; fetch the Advanced Configurations page if the user asks for them:
- Adaptive Recognition (cloud backup):
LabelCaptureAdaptiveRecognitionOverlay,LabelCaptureAdaptiveRecognitionSettings,ILabelCaptureAdaptiveRecognitionListener, and the result typesAdaptiveRecognitionResult/AdaptiveRecognitionResultType/ReceiptScanningResult/ReceiptScanningLineItem. Enabled per-definition viaAdaptiveRecognitionMode. - Advanced overlay (arbitrary Android views over labels):
LabelCaptureAdvancedOverlay,ILabelCaptureAdvancedOverlayListener. LabelFieldLocation/LabelFieldLocationType— used withSetLocation(...)on custom field builders to constrain where a field is expected on the label.
Documented for other platforms but NOT on dotnet.android — do not use
LabelField.ValueType/LabelFieldValueType— iOS-only (#if __IOS__in the binding). On .NET Android useType(LabelFieldType) plus the typed accessorsBarcode/Text/Date.- The Kotlin
LabelCaptureSettings.builder()/.addLabel()/.buildFluent(...)fluent API — not present in .NET. UseLabelDefinition.Create+LabelCaptureSettings.Create. - Native
LabelFieldDefinitionBuilderregex method names (setPattern,setDataTypePattern) — those are the old native names. In .NET useSetValueRegex(es)(value) andSetAnchorRegex(es)(anchor/context).