feat(intial auth): intial auth setup for the scanner
Some checks failed
Build and Push LST Docker Image / docker (push) Has been cancelled
Some checks failed
Build and Push LST Docker Image / docker (push) Has been cancelled
This commit is contained in:
317
lstMobile/plugins/withZebraDataWedge.js
Normal file
317
lstMobile/plugins/withZebraDataWedge.js
Normal file
@@ -0,0 +1,317 @@
|
||||
const { withDangerousMod } = require("@expo/config-plugins");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// const packageName = "net.alpla.lst.mobile";
|
||||
// const packagePath = "com/alpla/lst/mobile";
|
||||
const packageName = "net.alpla.lst.mobile";
|
||||
const packagePath = "net/alpla/lst/mobile";
|
||||
// const packageName = config.android?.package;
|
||||
// const packagePath = packageName.replace(/\./g, "/");
|
||||
|
||||
const moduleCode = `package ${packageName}.scanner
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Bundle
|
||||
import com.facebook.react.bridge.*
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule
|
||||
|
||||
class ZebraScannerModule(
|
||||
private val reactContext: ReactApplicationContext
|
||||
) : ReactContextBaseJavaModule(reactContext) {
|
||||
|
||||
override fun getName(): String = "ZebraScanner"
|
||||
|
||||
private val scanAction = "com.lst.mobile.SCAN"
|
||||
private var receiverRegistered = false
|
||||
|
||||
private val scanReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
println("LST SCANNER: received intent -> \${intent?.action}")
|
||||
|
||||
if (intent?.action != scanAction) {
|
||||
println("LST SCANNER: wrong action")
|
||||
return
|
||||
}
|
||||
|
||||
val barcodeData: String? =
|
||||
intent.getStringExtra("com.symbol.datawedge.data_string")
|
||||
|
||||
val labelType: String? =
|
||||
intent.getStringExtra("com.symbol.datawedge.label_type")
|
||||
|
||||
val source: String? =
|
||||
intent.getStringExtra("com.symbol.datawedge.source")
|
||||
|
||||
println("LST SCANNER: data=$barcodeData label=$labelType source=$source")
|
||||
|
||||
if (barcodeData.isNullOrBlank()) {
|
||||
println("LST SCANNER: empty barcode")
|
||||
return
|
||||
}
|
||||
|
||||
val payload = Arguments.createMap().apply {
|
||||
putString("data", barcodeData)
|
||||
putString("labelType", labelType)
|
||||
putString("source", source)
|
||||
putDouble("timestamp", System.currentTimeMillis().toDouble())
|
||||
}
|
||||
|
||||
sendEvent("barcodeScanned", payload)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun startListening() {
|
||||
if (receiverRegistered) return
|
||||
|
||||
reactContext.registerReceiver(
|
||||
scanReceiver,
|
||||
IntentFilter(scanAction),
|
||||
Context.RECEIVER_EXPORTED
|
||||
)
|
||||
|
||||
receiverRegistered = true
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun stopListening() {
|
||||
if (!receiverRegistered) return
|
||||
|
||||
try {
|
||||
reactContext.unregisterReceiver(scanReceiver)
|
||||
} catch (_: Exception) {}
|
||||
|
||||
receiverRegistered = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Required for React Native NativeEventEmitter
|
||||
*/
|
||||
@ReactMethod
|
||||
fun addListener(eventName: String) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Required for React Native NativeEventEmitter
|
||||
*/
|
||||
@ReactMethod
|
||||
fun removeListeners(count: Int) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun triggerScan() {
|
||||
val intent = Intent().apply {
|
||||
action = "com.symbol.datawedge.api.ACTION"
|
||||
putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "TOGGLE_SCANNING")
|
||||
}
|
||||
|
||||
reactContext.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun sendCommand(command: String, value: Any) {
|
||||
val intent = Intent().apply {
|
||||
action = "com.symbol.datawedge.api.ACTION"
|
||||
|
||||
when (value) {
|
||||
is String -> putExtra(command, value)
|
||||
is Bundle -> putExtra(command, value)
|
||||
}
|
||||
}
|
||||
|
||||
reactContext.sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun sendEvent(eventName: String, payload: WritableMap) {
|
||||
reactContext
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit(eventName, payload)
|
||||
}
|
||||
|
||||
//
|
||||
@ReactMethod
|
||||
fun ensureProfile() {
|
||||
val profileName = "LST_MOBILE"
|
||||
|
||||
sendCommand(
|
||||
"com.symbol.datawedge.api.CREATE_PROFILE",
|
||||
profileName
|
||||
)
|
||||
|
||||
Thread.sleep(500)
|
||||
|
||||
val barcodeConfig = Bundle().apply {
|
||||
putString("PLUGIN_NAME", "BARCODE")
|
||||
putString("RESET_CONFIG", "true")
|
||||
|
||||
val props = Bundle().apply {
|
||||
putString("scanner_input_enabled", "true")
|
||||
|
||||
// Auto-select internal scanner
|
||||
putString("scanner_selection", "auto")
|
||||
putString("scanner_selection_by_identifier", "AUTO")
|
||||
|
||||
// Hardware trigger behavior
|
||||
putString("hardware_trigger_enabled", "true")
|
||||
putString("trigger_mode", "2") // 2 = HARD trigger
|
||||
|
||||
// Disable Zebra's loud initial decode feedback
|
||||
putString("decode_audio_feedback_uri", "")
|
||||
putString("decode_haptic_feedback", "false")
|
||||
putString("decode_led_feedback", "false")
|
||||
|
||||
// add in wake on trigger
|
||||
putString("trigger_wakeup_scan", "true");
|
||||
}
|
||||
|
||||
putBundle("PARAM_LIST", props)
|
||||
}
|
||||
|
||||
val intentConfig = Bundle().apply {
|
||||
putString("PLUGIN_NAME", "INTENT")
|
||||
putString("RESET_CONFIG", "true")
|
||||
|
||||
val props = Bundle().apply {
|
||||
putString("intent_output_enabled", "true")
|
||||
putString("intent_action", scanAction)
|
||||
putString("intent_delivery", "2") // broadcast
|
||||
putString("intent_use_content_provider", "false")
|
||||
}
|
||||
|
||||
putBundle("PARAM_LIST", props)
|
||||
}
|
||||
|
||||
val keystrokeConfig = Bundle().apply {
|
||||
putString("PLUGIN_NAME", "KEYSTROKE")
|
||||
putString("RESET_CONFIG", "true")
|
||||
|
||||
val props = Bundle().apply {
|
||||
putString("keystroke_output_enabled", "false")
|
||||
}
|
||||
|
||||
putBundle("PARAM_LIST", props)
|
||||
}
|
||||
|
||||
val profileConfig = Bundle().apply {
|
||||
putString("PROFILE_NAME", profileName)
|
||||
putString("PROFILE_ENABLED", "true")
|
||||
putString("CONFIG_MODE", "CREATE_IF_NOT_EXIST")
|
||||
|
||||
putParcelableArrayList(
|
||||
"PLUGIN_CONFIG",
|
||||
arrayListOf(barcodeConfig, intentConfig, keystrokeConfig)
|
||||
)
|
||||
}
|
||||
|
||||
sendCommand("com.symbol.datawedge.api.SET_CONFIG", profileConfig)
|
||||
|
||||
val appConfig = Bundle().apply {
|
||||
putString("PACKAGE_NAME", reactContext.packageName)
|
||||
putStringArray("ACTIVITY_LIST", arrayOf("*"))
|
||||
}
|
||||
|
||||
val associateConfig = Bundle().apply {
|
||||
putString("PROFILE_NAME", profileName)
|
||||
putString("CONFIG_MODE", "UPDATE")
|
||||
putParcelableArray("APP_LIST", arrayOf(appConfig))
|
||||
}
|
||||
|
||||
sendCommand("com.symbol.datawedge.api.SET_CONFIG", associateConfig)
|
||||
|
||||
// Runtime nudge: make sure scanner input is enabled for the active profile
|
||||
sendCommand(
|
||||
"com.symbol.datawedge.api.SCANNER_INPUT_PLUGIN",
|
||||
"ENABLE_PLUGIN"
|
||||
)
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const packageCode = `package ${packageName}.scanner
|
||||
|
||||
import com.facebook.react.ReactPackage
|
||||
import com.facebook.react.bridge.NativeModule
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.uimanager.ViewManager
|
||||
|
||||
class ZebraScannerPackage : ReactPackage {
|
||||
|
||||
override fun createNativeModules(
|
||||
reactContext: ReactApplicationContext
|
||||
): List<NativeModule> {
|
||||
return listOf(ZebraScannerModule(reactContext))
|
||||
}
|
||||
|
||||
override fun createViewManagers(
|
||||
reactContext: ReactApplicationContext
|
||||
): List<ViewManager<*, *>> {
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
function patchMainApplication(mainApplicationPath) {
|
||||
let contents = fs.readFileSync(mainApplicationPath, "utf8");
|
||||
|
||||
const importLine = `import ${packageName}.scanner.ZebraScannerPackage`;
|
||||
|
||||
if (!contents.includes(importLine)) {
|
||||
contents = contents.replace(
|
||||
/import com\.facebook\.react\.PackageList/,
|
||||
`import com.facebook.react.PackageList\n${importLine}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!contents.includes("add(ZebraScannerPackage())")) {
|
||||
contents = contents.replace(
|
||||
/PackageList\(this\)\.packages\.apply\s*\{/,
|
||||
`PackageList(this).packages.apply {\n add(ZebraScannerPackage())`,
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(mainApplicationPath, contents);
|
||||
}
|
||||
|
||||
module.exports = function withZebraScanner(config) {
|
||||
return withDangerousMod(config, [
|
||||
"android",
|
||||
async (config) => {
|
||||
const androidRoot = config.modRequest.platformProjectRoot;
|
||||
|
||||
const scannerDir = path.join(
|
||||
androidRoot,
|
||||
"app/src/main/java",
|
||||
packagePath,
|
||||
"scanner",
|
||||
);
|
||||
|
||||
fs.mkdirSync(scannerDir, { recursive: true });
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(scannerDir, "ZebraScannerModule.kt"),
|
||||
moduleCode,
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(scannerDir, "ZebraScannerPackage.kt"),
|
||||
packageCode,
|
||||
);
|
||||
|
||||
const mainApplicationPath = path.join(
|
||||
androidRoot,
|
||||
"app/src/main/java",
|
||||
packagePath,
|
||||
"MainApplication.kt",
|
||||
);
|
||||
|
||||
patchMainApplication(mainApplicationPath);
|
||||
|
||||
return config;
|
||||
},
|
||||
]);
|
||||
};
|
||||
Reference in New Issue
Block a user