Skip to content

About

Handle Zebra DataWedge broadcast intents to receive and parse barcode data on Android.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

tauri-plugin-dwrecv

Handle Zebra DataWedge broadcast intents to receive and parse barcode data on Android.

Platform support

Register the plugin on every platform. Android intent reception is available on Android; other platforms provide status reporting and reject scan operations. Native Android registration remains internal to the plugin.

checkStatus() returns { isAvailable: true } on Android and { isAvailable: false, reason: "unsupportedPlatform" } elsewhere. This checks only platform support, not DataWedge, intent senders, hardware, or configuration. Missing plugin registration and permission failures reject the call.

import { checkStatus, onScan } from "tauri-plugin-dwrecv-api";

const status = await checkStatus();
if (status.isAvailable) {
  const unlisten = await onScan((barcode) => console.log(barcode.data));
  // Call await unlisten() when disposing the listener.
} else {
  console.log("Scanning is not supported on this platform.");
}

Usage

  • Create a new project: Tauri Guide.
  • Add tauri-plugin-dwrecv to your project's [src-tauri/Cargo.toml].
[dependencies]
tauri-plugin-dwrecv = { git = "https://github.com/benditorok/tauri-plugin-dwrecv.git", tag = "dwrecv-v0.4.0" }
  • Install the JavaScript/TypeScript API package.

For development/testing, install the plugin and React example together from the repository root. Use pnpm 12.8.1 and Node.js 22.13 or newer; .node-version pins the tested Node.js version for version managers.

pnpm install

For production (install from GitHub):

pnpm add github:benditorok/tauri-plugin-dwrecv --allow-build='tauri-plugin-dwrecv-api@git+https://github.com/benditorok/tauri-plugin-dwrecv.git'

Git installs build the API from source, so pnpm needs permission to run this repository's build script.

Or add to your package.json:

{
  "dependencies": {
    "tauri-plugin-dwrecv-api": "github:benditorok/tauri-plugin-dwrecv"
  }
}

For a manual Git dependency, also add this to your application's pnpm-workspace.yaml, then run pnpm install:

allowBuilds:
  'tauri-plugin-dwrecv-api@git+https://github.com/benditorok/tauri-plugin-dwrecv.git': true
  • Configure [src-tauri/tauri.conf.json].

    • intentCategory is optional.
{
  "build": {},
  "app": {},
  "bundle": {},
  "plugins": {
    "dwrecv": {
      "intentAction": "com.your.intentName",
      "intentCategory": "android.intent.category.DEFAULT"
    }
  }
}
  • Enable dwrecv:allow-status in [src-tauri/capabilities/default.json] so that availability can be checked on every platform. The scan operations also need dwrecv:default in [src-tauri/capabilities/mobile.json].
{
    "$schema": "../gen/schemas/mobile-schema.json",
    "identifier": "mobile-capability",
    "description": "Extra capability for the main window on mobile devices",
    "windows": [
        "main"
    ],
    "platforms": [
        "android"
    ],
    "permissions": [
        "dwrecv:default"
    ]
}
  • Initialize the plugin in [src-tauri/src/lib.rs].
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .plugin(tauri_plugin_dwrecv::init()) // Add this line
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

React

You can find an example project under [examples/react-scanner].

  • Import and use the onScan function from tauri-plugin-dwrecv-api.
import { useEffect } from "react";
import { checkStatus, onScan } from "tauri-plugin-dwrecv-api";

function App() {
  useEffect(() => {
    let unlisten: (() => Promise<void>) | undefined;

    const setupListener = async () => {
      try {
        const status = await checkStatus();
        if (!status.isAvailable) {
          console.log("Scanning is not supported on this platform.");
          return;
        }
        unlisten = await onScan(
          (barcode) => console.log("Barcode received:", barcode.data),
          (error) => console.error("Scan error:", error),
        );
        console.log("Scan listener registered successfully");
      } catch (e) {
        console.error("Failed to register scan listener:", e);
      }
    };

    setupListener();

    return () => {
      if (unlisten) {
        unlisten();
      }
    };
  }, []);

  return (
    <main>
      <p>Scan a barcode to see the results in the console.</p>
    </main>
  );
}

export default App;

Blazor

You can find an example project under [examples/BlazorScanner].

  • Create a new javascript file [src/wwwroot/scripts/tauriEvents.js] that implements the onScan helper using Tauri's core API.

Note: Blazor doesn't support ES module imports at runtime, so we use the Tauri core API directly instead of importing the npm package.

// Blazor-compatible wrapper for tauri-plugin-dwrecv
const { invoke, addPluginListener } = window.__TAURI__.core;

window.checkScanStatus = () => invoke("plugin:dwrecv|status");

async function onScan(onBarcode, onError) {
  const status = await window.checkScanStatus();
  if (!status.isAvailable) {
    throw new Error("Scanning is not supported on this platform.");
  }
  const listener = await addPluginListener("dwrecv", "dw-scan", (payload) => {
    if ("data" in payload) {
      onBarcode(payload);
    } else if ("errorMessage" in payload) {
      if (onError) {
        onError(payload.errorMessage);
      } else {
        console.error("Scan error:", payload.errorMessage);
      }
    }
  });

  return async () => {
    await listener.unregister();
  };
}

class ScanListener {
  constructor(unlistenFn) {
    this.unlistenFn = unlistenFn;
  }

  async unregister() {
    if (this.unlistenFn) {
      await this.unlistenFn();
      console.log("Scan listener unregistered successfully");
    }
  }
}

window.registerScanListener = async function (dotnetRef) {
  try {
    const unlisten = await onScan(
      (barcode) => dotnetRef.invokeMethodAsync("OnScanReceived", barcode),
      (error) => dotnetRef.invokeMethodAsync("OnScanError", error),
    );

    console.log("Scan listener registered successfully");
    return new ScanListener(unlisten);
  } catch (e) {
    console.error("Failed to register scan listener:", e);
    return null;
  }
};

window.unregisterScanListener = async function (listener) {
  try {
    if (listener) {
      await listener.unregister();
    }
  } catch (e) {
    console.error("Failed to unregister scan listener:", e);
  }
};
  • Include it in [src/wwwroot/index.html].
<!-- -->
    <body>
        <script src="_framework/blazor.webassembly.js"></script>
        <!-- Initialize Tauri event listeners after Blazor is loaded -->
        <script src="scripts/tauriEvents.js"></script>
    </body>
<!-- -->
  • Define the callback methods in your Blazor component.
@using System.Text.Json
@using System.Text.Json.Serialization
@implements IAsyncDisposable

@page "/"

@inject IJSRuntime JsRuntime
@inject ILogger<Home> Logger

<p>Scan a barcode to see the results.</p>

@code {
    private class Barcode
    {
        [JsonPropertyName("data")] public string Data { get; set; }
        [JsonPropertyName("labelType")] public string LabelType { get; set; }
        [JsonPropertyName("source")] public string Source { get; set; }
    }
    
    private IJSObjectReference? _pluginListener;
    private DotNetObjectReference<Home>? _dotNetRef;
    
    protected override async Task OnInitializedAsync()
    {
        var status = await JsRuntime.InvokeAsync<JsonElement>("checkScanStatus");
        if (!status.GetProperty("isAvailable").GetBoolean())
        {
            Logger.LogInformation("Scanning is not supported on this platform.");
            return;
        }
        _dotNetRef = DotNetObjectReference.Create(this);
        _pluginListener = await JsRuntime.InvokeAsync<IJSObjectReference>("registerScanListener", _dotNetRef);
    }
    
    public async ValueTask DisposeAsync()
    {
        if (_pluginListener is not null)
        {
            await JsRuntime.InvokeVoidAsync("unregisterScanListener", _pluginListener);
            await _pluginListener.DisposeAsync();
        }
        
        _dotNetRef?.Dispose();
    }
    
    [JSInvokable]
    public Task OnScanReceived(Barcode barcode)
    {
        Logger.LogError($"Barcode received: {barcode.Data}");
        return Task.CompletedTask;
    }
    
    [JSInvokable]
    public Task OnScanError(string errorMessage)
    {
        Logger.LogError($"Scan error: {errorMessage}");
        return Task.CompletedTask;
    }
}

Other information

  • Your dev URL should be set to http://0.0.0.0 instead of http://localhost in:
    • [src/Properties/launchSettings.json]: "applicationUrl": "http://0.0.0.0:1420"

Testing

Rust and JavaScript checks

Run the Rust tests from the repository root:

cargo test

Run the JavaScript API tests from the repository root. The test command builds dist-js before running tests/api.test.mjs:

pnpm test

To run the test file directly after building:

pnpm build
node tests/api.test.mjs

For a reproducible install in CI, use pnpm install --frozen-lockfile.

Kotlin checks

With Java and the Android SDK configured, run these commands from the repository root. The Cargo check requires the aarch64-linux-android Rust target and generates the Tauri Android dependency in android/.tauri/tauri-api.

cargo check --target aarch64-linux-android
cd android
./gradlew :compileDebugKotlin :testDebugUnitTest

On Windows, use gradlew.bat instead of ./gradlew.

You can send intents using adb to your device. Make sure your device is connected with adb devices.

Check device logs:

  • Windows:
$ adb logcat | findstr DWIntent
  • Linux:
$ adb logcat | grep DWIntent

Broadcast intents:

  • The -c switch is optional.
  • Windows:
$ adb shell am broadcast `
  -a com.your.intentName `
  -c android.intent.category.DEFAULT `
  --es 'com.symbol.datawedge.label_type' 'CODE128' `
  --es 'com.symbol.datawedge.data_string' '1234567890123' `
  --es 'com.symbol.datawedge.source' 'test-scanner'
  • Linux:
$ adb shell am broadcast \
  -a com.your.intentName \
  -c android.intent.category.DEFAULT \
  --es 'com.symbol.datawedge.label_type' 'CODE128' \
  --es 'com.symbol.datawedge.data_string' '1234567890123' \
  --es 'com.symbol.datawedge.source' 'test-scanner'

License

MIT

Trademark Notice

Zebra and DataWedge are trademarks or registered trademarks of Zebra Technologies Corporation. This project is independent and is not affiliated with, endorsed by, or sponsored by Zebra Technologies Corporation.

About

Handle Zebra DataWedge broadcast intents to receive and parse barcode data on Android.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages