Measure tire tread depth from a smartphone camera. The SDK captures frames on-device, uploads them to Anyline's servers, and returns per-region tread depth measurements.
- React Native 0.75+
- Node 18+
- Camera with autofocus and 1080p capability
- Stable internet connection
- Android 6.0+ (API 23)
- iOS 13.4+
yarn add @anyline/tire-tread-react-native-module
# or
npm install @anyline/tire-tread-react-native-moduleAdd the Anyline Maven repository to your project-level build.gradle (or settings.gradle for newer projects):
allprojects {
repositories {
maven { url "https://europe-maven.pkg.dev/anyline-ttr-sdk/maven" }
}
}cd ios && pod installThe scan UI requires camera access. Configure permissions before calling scan.
Android — add to AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />iOS — add to Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is needed to scan tire tread depth.</string>See the
example/app for a complete working integration.
Every API call returns a result object — promises never reject. Check ok to distinguish success from failure.
import {
initialize,
scan,
getResult,
sendCommentFeedback,
sendTreadDepthResultFeedback,
sendTireIdFeedback,
type TireTreadConfig,
type ScanOutcome,
type TreadDepthResult,
} from '@anyline/tire-tread-react-native-module';Call once at app startup. Requires a valid Anyline license key.
const init = await initialize('YOUR_LICENSE_KEY');
if (!init.ok) {
// init.error.type is the category (LICENSE_ERROR, CONFIG_ERROR, NETWORK_ERROR, ...)
// init.error.code is the specific detail (INVALID_LICENSE, NO_CONNECTION, ...)
console.error(init.error.type, init.error.code, init.error.message);
return;
}You can pass an optional InitOptions object as the second argument:
const init = await initialize('YOUR_LICENSE_KEY', {
customTag: 'warehouse-scanner-3', // optional tag to tell apart different devices (max 50 chars)
});Opens a full-screen camera UI. The user positions the phone near the tire and the SDK captures frames automatically.
const config: TireTreadConfig = {
uiConfig: {
measurementSystem: 'Metric',
},
};
const outcome: ScanOutcome = await scan(config);
switch (outcome.kind) {
case 'ScanCompleted':
console.log('Measurement UUID:', outcome.measurementUUID);
break;
case 'ScanAborted':
// User closed the scanner
return;
case 'ScanFailed':
console.error(outcome.error?.type, outcome.error?.code, outcome.error?.message);
return;
}kind |
Meaning | Fields |
|---|---|---|
ScanCompleted |
Frames captured and uploaded | measurementUUID |
ScanAborted |
User closed the scanner | measurementUUID? (present if session was created) |
ScanFailed |
Scan could not complete | error, measurementUUID? |
Poll the backend for tread depth measurements. You can pass an optional timeout override in seconds if needed.
const result = await getResult(outcome.measurementUUID!);
if (!result.ok) {
console.error(result.error.type, result.error.code, result.error.message);
return;
}
const { global, regions } = result.value;
console.log(`Global depth: ${global.value_mm} mm`);
for (const region of regions) {
if (region.available) {
console.log(` Region: ${region.value_mm} mm (${region.value_inch_32nds}/32")`);
}
}After reviewing results, you can submit corrections to improve future measurements.
// Attach a comment
await sendCommentFeedback(measurementUUID, 'Tire was wet during scan');
// Submit corrected tread depth values
await sendTreadDepthResultFeedback(measurementUUID, [
{ available: true, value_mm: 5.2 },
{ available: true, value_mm: 4.8 },
{ available: true, value_mm: 5.0 },
]);
// Submit a tire identifier
await sendTireIdFeedback(measurementUUID, 'FL-001');All feedback functions return SdkResult<MeasurementInfo>.
All functions are fully typed. Return types and error shapes are available via TypeScript autocompletion.
initialize(licenseKey, options?)— Initialize the SDKscan(config?, options?)— Open scanner, returnsScanOutcomegetResult(measurementUUID, timeout?)— Fetch tread depth results
sendCommentFeedback(measurementUUID, comment)— Attach a text comment to a measurementsendTreadDepthResultFeedback(measurementUUID, treadResultRegions)— Submit corrected tread depth valuessendTireIdFeedback(measurementUUID, tireId)— Submit a corrected tire identifier
getSdkVersion()— Native SDK versiongetWrapperVersion()— Module version
Pass a TireTreadConfig object to scan. All fields are optional.
const config: TireTreadConfig = {
scanConfig: {
// Only set tireWidth if you know the exact width in mm beforehand.
// If omitted, the SDK will prompt the user to enter it before scanning.
// Passing an incorrect value will reduce measurement accuracy.
tireWidth: 225,
},
uiConfig: {
measurementSystem: 'Metric', // 'Metric' | 'Imperial'
},
additionalContext: {
correlationId: 'fleet-inspection-42',
tirePosition: { axle: 1, positionOnAxle: 1, side: 'Left' },
},
};Full configuration reference: Scan Configuration | Default UI
All errors follow a structured format with a type category and a specific code:
interface SdkError {
type: ErrorType;
code: ErrorCode;
message: string;
debug?: Record<string, string>;
}LICENSE_ERROR — license validation failures
| Code | When |
|---|---|
INVALID_LICENSE |
License key is malformed or expired |
LICENSE_KEY_FORBIDDEN |
License not authorized for this app/bundle ID |
SDK_NOT_VERIFIED |
License verification failed (network or server issue) |
CONFIG_ERROR — invalid configuration
| Code | When |
|---|---|
INVALID_ARGUMENT |
Invalid config value passed to an API call |
NETWORK_ERROR — connectivity issues
| Code | When |
|---|---|
NO_CONNECTION |
Device is offline or cannot reach Anyline servers |
UPLOAD_FAILED |
Frame upload to backend failed |
TIMEOUT |
Server did not respond within the timeout period |
SCAN_ERROR — scan lifecycle failures
| Code | When |
|---|---|
SDK_NOT_INITIALIZED |
API called before initialize completed |
INITIALIZATION_FAILED |
SDK startup failed (missing permissions, resources) |
SESSION_CREATION_FAILED |
Backend rejected the scan session |
MEASUREMENT_ERROR |
Backend could not process the scan |
ALREADY_RUNNING |
A scan is already in progress |
INTERNAL_ERROR |
Unexpected native SDK error |
UNKNOWN_ERROR |
Unclassified error |
RESULT_ERROR — result retrieval failures
| Code | When |
|---|---|
INVALID_UUID |
Measurement UUID not found |
RESULT_ERROR |
Failed to retrieve tread depth results |
A successful getResult call returns a TreadDepthResult. Here's what you get back:
// result.value: TreadDepthResult
{
global: TreadResultRegion, // overall tire depth
regions: TreadResultRegion[], // per-region measurements (typically 3)
measurementInfo: {
measurementUUID: string,
status: MeasurementStatus, // see below
additionalContext?: { // echoes back what you passed to scan()
correlationId?: string,
tirePosition?: { axle, positionOnAxle, side },
},
},
measurementMetadata?: {
movementDirection?: 'LeftToRight' | 'RightToLeft' | 'Unknown',
},
}
// Each TreadResultRegion:
{
available: boolean, // false if this region couldn't be measured
value_mm: number, // depth in millimeters
value_inch: number, // depth in inches
value_inch_32nds: number, // depth in 32nds of an inch
}
// MeasurementStatus:
'Unknown' | 'WaitingForImages' | 'Processing'
| 'ResultReady' | 'ResultAndReportReady'
| 'Completed' | 'Aborted' | 'Failed'Camera permission denied at runtime
Request camera permission before calling scan. On iOS, the first call triggers the system prompt. On Android, use PermissionsAndroid.request() or a library like react-native-permissions.
Scan fails immediately with INITIALIZATION_FAILED
Ensure initialize completed with ok: true before scanning. Check that the device has autofocus — tablets and some low-end devices without autofocus are not supported.
NO_CONNECTION or TIMEOUT during result retrieval
The SDK uploads frames and retrieves results over HTTPS. Verify the device has a stable internet connection and can reach anyline.com endpoints. Increase the timeout if processing takes longer than expected.
LICENSE_KEY_FORBIDDEN on one platform but not the other
License keys are bound to app identifiers. Verify the bundle ID (iOS) and application ID (Android) match what was configured in your Anyline account.
Android build fails: "Could not resolve io.anyline.tiretread.sdk"
The Anyline Maven repository is not in your Gradle config. Add maven { url "https://europe-maven.pkg.dev/anyline-ttr-sdk/maven" } to your repositories block.
iOS build fails: pod not found
Run pod repo update then pod install again. Ensure your Podfile's platform is set to iOS 13.4 or higher.
This module includes an Expo config plugin that automatically:
- adds
NSCameraUsageDescriptionto your iOSInfo.plist - adds
CAMERApermission to your AndroidAndroidManifest.xml - adds the Anyline Android Maven repository to the project repositories
{
"plugins": [
"@anyline/tire-tread-react-native-module"
]
}Note: This module uses native code and is not compatible with Expo Go. You must use a development build (
npx expo run:android/npx expo run:ios).
For issues or questions, open a support request at the Anyline Helpdesk.
See LICENSE.md for licensing information.