anyline-tire-tread-react-native-module 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/LICENSE.md +11 -0
  2. package/README.md +157 -0
  3. package/android/build.gradle +150 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +22 -0
  6. package/android/src/main/AndroidManifestNew.xml +20 -0
  7. package/android/src/main/java/com/anyline/ttr/reactnative/CameraDirectionHelper.kt +32 -0
  8. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativeCallbackManager.kt +30 -0
  9. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativeCustomComposeContainer.kt +69 -0
  10. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativeModule.kt +441 -0
  11. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativePackage.kt +17 -0
  12. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativeScanActivity.kt +172 -0
  13. package/android/src/main/java/com/anyline/ttr/reactnative/TTRReactNativeViewManager.kt +17 -0
  14. package/android/src/main/res/values/styles.xml +11 -0
  15. package/anyline-tire-tread-react-native-module.podspec +44 -0
  16. package/ios/AnylineTtrMobileWrapperReactNative-Bridging-Header.h +3 -0
  17. package/ios/AnylineTtrMobileWrapperReactNative.mm +30 -0
  18. package/ios/AnylineTtrMobileWrapperReactNative.swift +130 -0
  19. package/ios/CameraDirectionHelper.swift +47 -0
  20. package/ios/ScanViewController.swift +211 -0
  21. package/lib/commonjs/index.js +98 -0
  22. package/lib/commonjs/index.js.map +1 -0
  23. package/lib/module/index.js +83 -0
  24. package/lib/module/index.js.map +1 -0
  25. package/lib/typescript/src/index.d.ts +28 -0
  26. package/lib/typescript/src/index.d.ts.map +1 -0
  27. package/package.json +153 -0
  28. package/src/index.tsx +155 -0
package/LICENSE.md ADDED
@@ -0,0 +1,11 @@
1
+ # Copyright © 2026 Anyline GmbH. All rights reserved.
2
+
3
+ ## License
4
+
5
+ The contents of this repository are the intellectual property of Anyline GmbH.
6
+
7
+ The use of the SDK and this app is subject to the most recent Master Subscription Terms of Anyline GmbH (or one of its subsidiaries), Terms of Use for the Anyline App and Anyline's Privacy Policies, available under Imprint & Legal of Anyline GmbH & Anyline Inc. | Anyline (or to a "Master Partner Agreement" if you are a partner of Anyline), and is only allowed if you have received a "Trial Access" (as defined in the Master Subscription Terms) or a license according to the Master Subscription Terms (or Master Partner Agreement).
8
+
9
+ ## Contact
10
+
11
+ For more information about the software development kit and licensing options, please contact Anyline GmbH at [anyline.com](https://anyline.com).
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # Anyline Tire Tread React Native SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/anyline-tire-tread-react-native-module.svg)](https://www.npmjs.com/package/anyline-tire-tread-react-native-module)
4
+ [![license](https://img.shields.io/npm/l/anyline-tire-tread-react-native-module.svg)](./LICENSE.md)
5
+
6
+ React Native SDK for Anyline Tire Tread scanning and depth measurement.
7
+
8
+ ## Getting Started
9
+
10
+ ### Requirements
11
+ - Stable internet connection
12
+ - Flash capability
13
+ - Camera functionality (required: 1080p with autofocus)
14
+
15
+ #### Android
16
+ - Android 6.0+ (Marshmallow) - API level 23+
17
+
18
+ #### iOS
19
+ - iOS 13+
20
+
21
+ Reference: [Anyline Tire Tread SDK documentation](https://documentation.anyline.com/tiretreadsdk-component/latest/index.html)
22
+
23
+ ### Installation
24
+
25
+ ```sh
26
+ yarn add anyline-tire-tread-react-native-module
27
+ # or
28
+ npm install anyline-tire-tread-react-native-module
29
+ ```
30
+
31
+ ### Android Setup
32
+
33
+ Add the custom maven repository to your `build.gradle`:
34
+
35
+ ```gradle
36
+ maven { url "https://europe-maven.pkg.dev/anyline-ttr-sdk/maven" }
37
+ ```
38
+
39
+ ### iOS Setup
40
+
41
+ Run `pod install` after installing the package:
42
+
43
+ ```sh
44
+ cd ios && pod install
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ### Importing
50
+
51
+ ```typescript
52
+ import {
53
+ initialize,
54
+ scanWithEvents,
55
+ getResult,
56
+ getHeatMap,
57
+ isDeviceSupported,
58
+ setOrientationLock,
59
+ OrientationLock,
60
+ } from 'anyline-tire-tread-react-native-module';
61
+ ```
62
+
63
+ ### Initialization
64
+
65
+ ```typescript
66
+ try {
67
+ const response = await initialize('your_license_key');
68
+ console.log('Initialization successful:', response);
69
+ } catch (error) {
70
+ console.error('Initialization failed:', error);
71
+ }
72
+ ```
73
+
74
+ ### Device Compatibility Check
75
+
76
+ ```typescript
77
+ const supported = await isDeviceSupported();
78
+ if (!supported) {
79
+ console.warn('Device not supported');
80
+ }
81
+ ```
82
+
83
+ ### Scanning
84
+
85
+ Use `scanWithEvents` to start a scan and receive real-time events:
86
+
87
+ ```typescript
88
+ const config = JSON.stringify(require('./assets/config/sample_config_default.json'));
89
+
90
+ try {
91
+ const { measurementUUID, cameraDirection } = await scanWithEvents(
92
+ config,
93
+ undefined,
94
+ (event) => {
95
+ console.log('Scan event:', event);
96
+ }
97
+ );
98
+ console.log('Scan complete:', measurementUUID, cameraDirection);
99
+ } catch (error) {
100
+ console.error('Scanning failed:', error);
101
+ }
102
+ ```
103
+
104
+ **Parameters:**
105
+ - `config` (string): JSON configuration for the scanning activity.
106
+ - `tireWidth` (number, optional): Tire width for improved accuracy.
107
+ - `onEvent` (function, optional): Callback for scan events (`scanStarted`, `scanStopped`, `imageUploaded`, `distanceChanged`).
108
+
109
+ **Returns:** `Promise<ScanResult>` with `measurementUUID` and `cameraDirection`.
110
+
111
+ ### Getting Results
112
+
113
+ ```typescript
114
+ try {
115
+ const result = await getResult(measurementUUID);
116
+ console.log('Report:', result);
117
+ } catch (error) {
118
+ console.error('Getting report failed:', error);
119
+ }
120
+ ```
121
+
122
+ ### Getting Heatmap
123
+
124
+ ```typescript
125
+ try {
126
+ const heatmapUrl = await getHeatMap(measurementUUID);
127
+ console.log('Heatmap URL:', heatmapUrl);
128
+ } catch (error) {
129
+ console.error('Getting heatmap failed:', error);
130
+ }
131
+ ```
132
+
133
+ ## Configuration
134
+
135
+ The scanning activity is configured via a JSON object. For complete documentation:
136
+ - [Scan Configuration](https://documentation.anyline.com/tiretreadsdk-component/latest/scan-configuration.html)
137
+ - [Default UI Overview](https://documentation.anyline.com/tiretreadsdk-component/latest/default-ui/overview.html)
138
+ - [Customizing the Default UI](https://documentation.anyline.com/tiretreadsdk-component/latest/default-ui/customizing.html)
139
+
140
+ ## Troubleshooting
141
+
142
+ ### Camera permissions not granted
143
+ Ensure your app requests camera permissions before starting a scan. On Android, add `android.permission.CAMERA` to your `AndroidManifest.xml`. On iOS, add `NSCameraUsageDescription` to your `Info.plist`.
144
+
145
+ ### Scan fails with autofocus error
146
+ The SDK requires a camera with autofocus capability. Devices without autofocus (e.g. some tablets) are not supported. Use `isDeviceSupported()` to check before scanning.
147
+
148
+ ### Network timeout during result retrieval
149
+ The SDK requires a stable internet connection to upload frames and retrieve results. Ensure the device has connectivity and can reach `anyline.com` endpoints.
150
+
151
+ ## Support
152
+
153
+ For issues or questions, please open a support request using the [Anyline Helpdesk](https://support.anyline.com).
154
+
155
+ ## License
156
+
157
+ See the [LICENSE.md](./LICENSE.md) file for licensing information.
@@ -0,0 +1,150 @@
1
+ buildscript {
2
+ def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["AnylineTtrMobileWrapperReactNative_kotlinVersion"]
3
+
4
+ repositories {
5
+ google()
6
+ mavenCentral()
7
+ maven { url "https://europe-maven.pkg.dev/anyline-ttr-sdk/maven" }
8
+ }
9
+
10
+ dependencies {
11
+ classpath "com.android.tools.build:gradle:7.2.1"
12
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13
+ }
14
+ }
15
+
16
+ plugins {
17
+ id 'com.android.library'
18
+ id 'kotlin-android'
19
+ }
20
+
21
+ allprojects {
22
+ repositories {
23
+ google()
24
+ mavenCentral()
25
+ maven { url "https://europe-maven.pkg.dev/anyline-ttr-sdk/maven" }
26
+ addReactNativeMavenRepo(delegate)
27
+ }
28
+ }
29
+
30
+ def isNewArchitectureEnabled() {
31
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
32
+ }
33
+
34
+ if (isNewArchitectureEnabled()) {
35
+ apply plugin: "com.facebook.react"
36
+ }
37
+
38
+ def getExtOrDefault(name) {
39
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["AnylineTtrMobileWrapperReactNative_" + name]
40
+ }
41
+
42
+ def getExtOrIntegerDefault(name) {
43
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["AnylineTtrMobileWrapperReactNative_" + name]).toInteger()
44
+ }
45
+
46
+ def supportsNamespace() {
47
+ def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
48
+ def major = parsed[0].toInteger()
49
+ def minor = parsed[1].toInteger()
50
+
51
+ return (major == 7 && minor >= 3) || major >= 8
52
+ }
53
+
54
+ def resolveReactNativeAndroidDir() {
55
+ if (rootProject.ext.has("reactNativeAndroidRoot")) {
56
+ def configuredDir = file(rootProject.ext.get("reactNativeAndroidRoot"))
57
+ if (configuredDir.exists()) {
58
+ return configuredDir
59
+ }
60
+ }
61
+
62
+ def currentDir = projectDir
63
+ 0.upto(5) {
64
+ if (currentDir == null) {
65
+ return null
66
+ }
67
+
68
+ def androidDir = new File(currentDir, "node_modules/react-native/android")
69
+ if (androidDir.exists()) {
70
+ return androidDir
71
+ }
72
+
73
+ def legacyDir = new File(currentDir, "node_modules/react-native")
74
+ if (legacyDir.exists()) {
75
+ return legacyDir
76
+ }
77
+
78
+ currentDir = currentDir.parentFile
79
+ }
80
+
81
+ return null
82
+ }
83
+
84
+ def addReactNativeMavenRepo(RepositoryHandler repositories) {
85
+ def reactNativeDir = resolveReactNativeAndroidDir()
86
+ if (reactNativeDir != null && reactNativeDir.exists()) {
87
+ repositories.maven {
88
+ url reactNativeDir.toString()
89
+ name "React Native sources"
90
+ }
91
+ } else {
92
+ logger.warn(":${project.name}: unable to locate React Native android sources; falling back to remote repositories")
93
+ }
94
+ }
95
+
96
+ android {
97
+ if (supportsNamespace()) {
98
+ namespace "com.anyline.ttr.reactnative"
99
+
100
+ sourceSets {
101
+ main {
102
+ manifest.srcFile "src/main/AndroidManifestNew.xml"
103
+ }
104
+ }
105
+ }
106
+
107
+ packagingOptions {
108
+ exclude 'META-INF/LICENSE.md'
109
+ }
110
+
111
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
112
+
113
+ defaultConfig {
114
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
115
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
116
+
117
+ }
118
+
119
+ buildTypes {
120
+ release {
121
+ minifyEnabled false
122
+ }
123
+ }
124
+
125
+ lintOptions {
126
+ disable "GradleCompatible"
127
+ }
128
+
129
+ compileOptions {
130
+ sourceCompatibility JavaVersion.VERSION_1_8
131
+ targetCompatibility JavaVersion.VERSION_1_8
132
+ }
133
+ }
134
+
135
+ def kotlin_version = getExtOrDefault("kotlinVersion")
136
+
137
+ dependencies {
138
+ implementation "com.facebook.react:react-native:+"
139
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
140
+
141
+ implementation "io.anyline.tiretread.sdk:shared:14.0.1"
142
+
143
+ implementation 'androidx.core:core-ktx:1.13.0'
144
+ implementation 'androidx.compose.ui:ui:1.6.6'
145
+ implementation 'androidx.compose.material:material:1.6.6'
146
+ implementation 'androidx.compose.ui:ui-tooling-preview:1.6.6'
147
+ implementation 'androidx.activity:activity-compose:1.9.0'
148
+ implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.0"
149
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
150
+ }
@@ -0,0 +1,5 @@
1
+ AnylineTtrMobileWrapperReactNative_kotlinVersion=1.9.24
2
+ AnylineTtrMobileWrapperReactNative_minSdkVersion=23
3
+ AnylineTtrMobileWrapperReactNative_targetSdkVersion=33
4
+ AnylineTtrMobileWrapperReactNative_compileSdkVersion=33
5
+ AnylineTtrMobileWrapperReactNative_ndkversion=21.4.7075529
@@ -0,0 +1,22 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.anyline.ttr.reactnative">
3
+
4
+ <uses-feature
5
+ android:name="android.hardware.camera"
6
+ android:required="true" />
7
+ <uses-feature
8
+ android:name="android.hardware.camera.autofocus"
9
+ android:required="true" />
10
+ <uses-feature
11
+ android:name="android.hardware.camera.flash"
12
+ android:required="false" />
13
+
14
+ <uses-permission android:name="android.permission.CAMERA" />
15
+ <uses-permission android:name="android.permission.INTERNET" />
16
+ <uses-permission android:name="android.permission.VIBRATE" />
17
+
18
+ <application>
19
+ <activity android:name="com.anyline.ttr.reactnative.TTRReactNativeScanActivity" android:theme="@style/AppTheme.FullScreen"/>
20
+ </application>
21
+
22
+ </manifest>
@@ -0,0 +1,20 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+
3
+ <uses-feature
4
+ android:name="android.hardware.camera"
5
+ android:required="true" />
6
+ <uses-feature
7
+ android:name="android.hardware.camera.autofocus"
8
+ android:required="true" />
9
+ <uses-feature
10
+ android:name="android.hardware.camera.flash"
11
+ android:required="false" />
12
+
13
+ <uses-permission android:name="android.permission.CAMERA" />
14
+ <uses-permission android:name="android.permission.INTERNET" />
15
+ <uses-permission android:name="android.permission.VIBRATE" />
16
+
17
+ <application>
18
+ <activity android:name="com.anyline.ttr.reactnative.TTRReactNativeScanActivity" android:theme="@style/AppTheme.FullScreen"/>
19
+ </application>
20
+ </manifest>
@@ -0,0 +1,32 @@
1
+ package com.anyline.ttr.reactnative
2
+
3
+ import android.app.Activity
4
+ import android.content.Context
5
+ import android.os.Build
6
+ import android.view.Surface
7
+
8
+ object CameraDirectionHelper {
9
+
10
+ enum class CameraDirection {
11
+ LEFT, RIGHT, UNKNOWN
12
+ }
13
+
14
+ /**
15
+ * Get current camera direction based on device orientation
16
+ * Returns: LEFT when camera points left, RIGHT when camera points right
17
+ */
18
+ fun getCameraDirection(context: Context): CameraDirection {
19
+ val rotation = if (Build.VERSION.SDK_INT >= 30) {
20
+ context.display?.rotation
21
+ } else {
22
+ @Suppress("DEPRECATION")
23
+ (context as? Activity)?.windowManager?.defaultDisplay?.rotation
24
+ } ?: return CameraDirection.UNKNOWN
25
+
26
+ return when (rotation) {
27
+ Surface.ROTATION_90 -> CameraDirection.LEFT // Camera points left
28
+ Surface.ROTATION_270 -> CameraDirection.RIGHT // Camera points right
29
+ else -> CameraDirection.UNKNOWN // Portrait or unknown
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,30 @@
1
+ package com.anyline.ttr.reactnative
2
+
3
+ interface TTRReactNativeResultCallback {
4
+ fun onResultSuccess(uuid: String, cameraDirection: String?)
5
+ fun onResultError(errorCode: String, errorMessage: String)
6
+ }
7
+
8
+ object TTRReactNativeCallbackManager {
9
+ private var callback: TTRReactNativeResultCallback? = null
10
+ private var lastCameraDirection: String? = null
11
+
12
+ fun registerCallback(cb: TTRReactNativeResultCallback) {
13
+ callback = cb
14
+ }
15
+
16
+ fun unregisterCallback(cb: TTRReactNativeResultCallback) {
17
+ if (callback == cb) {
18
+ callback = null
19
+ lastCameraDirection = null
20
+ }
21
+ }
22
+
23
+ fun getCallback(): TTRReactNativeResultCallback? = callback
24
+
25
+ fun setCameraDirection(direction: String) {
26
+ lastCameraDirection = direction
27
+ }
28
+
29
+ fun getCameraDirection(): String? = lastCameraDirection
30
+ }
@@ -0,0 +1,69 @@
1
+ package com.anyline.ttr.reactnative
2
+
3
+ import android.content.Context
4
+ import android.widget.FrameLayout
5
+ import androidx.compose.foundation.layout.fillMaxSize
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.Modifier
8
+ import androidx.compose.ui.platform.ComposeView
9
+ import androidx.compose.ui.viewinterop.AndroidView
10
+ import androidx.lifecycle.LifecycleOwner
11
+ import androidx.lifecycle.ViewModelStore
12
+ import androidx.lifecycle.ViewModelStoreOwner
13
+ import androidx.lifecycle.setViewTreeLifecycleOwner
14
+ import androidx.lifecycle.setViewTreeViewModelStoreOwner
15
+ import androidx.savedstate.SavedStateRegistryOwner
16
+ import androidx.savedstate.setViewTreeSavedStateRegistryOwner
17
+ import io.anyline.tiretread.sdk.scanner.TireTreadScanView
18
+
19
+ class TTRReactNativeCustomComposeContainer(context: Context) : FrameLayout(context) {
20
+ private val composeView = ComposeView(context).apply {
21
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
22
+ }
23
+
24
+ init {
25
+ addView(composeView)
26
+
27
+ // Ensure this container is associated with the necessary lifecycle owners
28
+ (context as? LifecycleOwner)?.let { owner ->
29
+ this.setViewTreeLifecycleOwner(owner)
30
+ this.setViewTreeViewModelStoreOwner(object : ViewModelStoreOwner {
31
+ override val viewModelStore: ViewModelStore
32
+ get() = ViewModelStore()
33
+ })
34
+ this.setViewTreeSavedStateRegistryOwner(owner as? SavedStateRegistryOwner)
35
+ }
36
+
37
+ // Set the content of your Compose view to include the TireTreadScanView
38
+ composeView.setContent {
39
+ AndroidView(
40
+ modifier = Modifier.fillMaxSize(),
41
+ factory = { ctx ->
42
+ // Creating an instance of TireTreadScanView
43
+ TireTreadScanView(ctx).apply {
44
+ // Initialize your view with necessary parameters
45
+ }
46
+ },
47
+ update = { view ->
48
+ // Update the view properties if needed when Compose recomposes
49
+ }
50
+ )
51
+ }
52
+ }
53
+ }
54
+
55
+ @Composable
56
+ fun TireTreadScanViewComposeAdapter(context: Context) {
57
+ // Assuming TireTreadScanView can be used directly as a composable.
58
+ // If not, additional integration may be required.
59
+ AndroidView(
60
+ factory = { ctx ->
61
+ TireTreadScanView(ctx).apply {
62
+ // configure your view if needed
63
+ }
64
+ },
65
+ update = { view ->
66
+ // Update the view during recompositions if necessary
67
+ }
68
+ )
69
+ }