-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExpoUrovoScannerModule.kt
More file actions
160 lines (134 loc) · 5.51 KB
/
Copy pathExpoUrovoScannerModule.kt
File metadata and controls
160 lines (134 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package expo.modules.urovoscannermodule
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
// Import Urovo SDK classes (Java classes) in Kotlin
import android.device.ScanManager
// Attempt: Add Beep func
// import android.device.scanner.configuration.PropertyID
// Import Android framework classes
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
class ExpoUrovoScannerModule : Module() {
private var mReceiver: BroadcastReceiver? = null
private var mScanManager: ScanManager? = null
// Each module class must implement the definition function. The definition consists of components
// that describes the module's functionality and behavior.
// See https://docs.expo.dev/modules/module-api for more details about available components.
override fun definition() = ModuleDefinition {
// Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
// The module will be accessible from `requireNativeModule('ExpoUrovoScannerModule')` in JavaScript.
Name("ExpoUrovoScannerModule")
// Sets constant properties on the module. Can take a dictionary or a closure that returns a dictionary.
Constants(
"PI" to Math.PI
)
// Defines event names that the module can send to JavaScript.
Events("onChange")
// Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
Function("hello") {
"Hello world! 👋"
}
Function("scanner") {
if (mScanManager == null) {
try {
mScanManager = ScanManager()
var powerOn = mScanManager?.scannerState
mScanManager?.switchOutputMode(0) // DECODE_OUTPUT_MODE_INTENT = 0
// Attempt to add beep, uncommented it for now, not sure if it's working
// val index = intArrayOf(PropertyID.GOOD_READ_BEEP_ENABLE)
// val value = intArrayOf(1)
// mScanManager?.setParameterInts(index, value)
registerReceiver()
Log.d("ExpoUrovoScannerModule", "Scanner initialized successfully")
} catch (e: Exception) {
Log.e("ExpoUrovoScannerModule", "Failed to initialize scanner: ${e.message}")
throw e
}
} else {
Log.d("ExpoUrovoScannerModule", "Scanner already initialized")
}
}
Function("scan") {
try {
if (mScanManager == null) {
throw Exception("Scanner not initialized. Call scanner() first.")
}
mScanManager?.startDecode()
Log.d("ExpoUrovoScannerModule", "Scan started")
} catch (e: Exception) {
Log.e("ExpoUrovoScannerModule", "Failed to start decode: ${e.message}")
throw e
}
}
Function("stopScan") {
try {
if (mScanManager == null) {
throw Exception("Scanner not initialized. Call scanner() first.")
}
mScanManager?.stopDecode()
Log.d("ExpoUrovoScannerModule", "Scan stopped")
} catch (e: Exception) {
Log.e("ExpoUrovoScannerModule", "Failed to stop decode: ${e.message}")
throw e
}
}
// Defines a JavaScript function that always returns a Promise and whose native code
// is by default dispatched on the different thread than the JavaScript runtime runs on.
AsyncFunction("setValueAsync") { value: String ->
// Send an event to JavaScript.
sendEvent("onChange", mapOf(
"value" to value
))
}
OnDestroy {
try {
mScanManager?.stopDecode() // Stop any ongoing decode operations
} catch (e: Exception) {
Log.w("ExpoUrovoScannerModule", "Error stopping decode on destroy: ${e.message}")
}
unregisterReceiver()
mScanManager = null
}
}
private val BARCODE_TYPE_TAG: String = ScanManager.BARCODE_TYPE_TAG
private val BARCODE_LENGTH_TAG: String = ScanManager.BARCODE_LENGTH_TAG
private val DECODE_DATA_TAG: String = ScanManager.DECODE_DATA_TAG
private val BARCODE_STRING_TAG: String = ScanManager.BARCODE_STRING_TAG
// Define a shortcut to appContext.reactContext with null-checking
private val context
get() = requireNotNull(appContext.reactContext)
private fun registerReceiver() {
if (mReceiver == null) {
mReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("onRECEIVE", "onReceive")
val barcode: ByteArray? = intent.getByteArrayExtra(DECODE_DATA_TAG)
val barcodeLen: Int = intent.getIntExtra(BARCODE_LENGTH_TAG, 0)
val temp: Byte = intent.getByteExtra(BARCODE_TYPE_TAG, 0)
val barcodeStr: String? = intent.getStringExtra(BARCODE_STRING_TAG)
Log.d("barcode", "barcode type: $temp")
val scanResult = barcode?.let { String(it, 0, barcodeLen) }
Log.d("barcode", "scanResult: $scanResult")
// Send scan result to JavaScript
scanResult?.let {
sendEvent("onChange", mapOf("scanResult" to it))
}
}
}
// Register the receiver with the appropriate IntentFilter
val filter = IntentFilter()
filter.addAction("android.intent.ACTION_DECODE_DATA")
context.registerReceiver(mReceiver, filter)
}
}
private fun unregisterReceiver() {
mReceiver?.let {
context.unregisterReceiver(it)
mReceiver = null
}
}
}