Zebra TC22 DataWedge-Integration mit Flutter: Probleme und Lösungen

·

·


Der Zebra TC22 ist ein leistungsstarkes Barcode-Scanner-Gerät, das häufig in Branchen wie Logistik, Einzelhandel und Gesundheitswesen verwendet wird. Dank der DataWedge-API können Barcode-Scanning-Funktionen einfach in Anwendungen integriert werden. In diesem Artikel erfahren Sie Schritt für Schritt, wie Sie den Zebra TC22 mit Flutter integrieren können, welche häufigen Probleme auftreten und wie Sie diese lösen können.

Was ist DataWedge und warum wird es verwendet?

DataWedge ist eine API, die es Zebra-Geräten ermöglicht, Barcodedaten zu erfassen und an Anwendungen weiterzuleiten. Bei der Verwendung von Frameworks wie Flutter müssen Sie DataWedge über Plattformkanäle in der nativen Android-Ebene implementieren.

Schritt-für-Schritt-Integration von Zebra TC22 mit Flutter

1. Projektvorbereitung mit Flutter und Android

Erstellen Sie zunächst ein neues Flutter-Projekt:

flutter create zebra_scanner_app
cd zebra_scanner_app


Verwenden Sie Flutter-Android-Plattformkanäle, um die Kommunikation mit der DataWedge-API zu ermöglichen.

2. Native Android-Programmierung

Die Integration von DataWedge erfolgt in der nativen Android-Ebene. Fügen Sie den folgenden Code zu Ihrer MainActivity.kt hinzu.

Code für MainActivity.kt:

package com.example.zebra_scanner_app

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import android.util.Log

class MainActivity : FlutterActivity() {
private val CHANNEL = "zebra_scanner_channel"
private lateinit var broadcastReceiver: BroadcastReceiver override fun configureFlutterEngine() {
    super.configureFlutterEngine()

    // Kommunikation zwischen Flutter und Android mit MethodChannel
    MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
        when (call.method) {
            "configureScanner" -> {
                configureScanner()
                result.success("Scanner konfiguriert")
            }
            else -> result.notImplemented()
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // BroadcastReceiver für Barcode-Daten
    broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.action
            if (action == "com.symbol.datawedge.api.ACTION") {
                val scannedData = intent.getStringExtra("com.symbol.datawedge.data_string") ?: ""
                Log.d("ZebraScanner", "Scanned Data: $scannedData")

                // Weiterleitung der Daten an Flutter
                flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger ->
                    MethodChannel(messenger, CHANNEL).invokeMethod("onScannedData", scannedData)
                }
            }
        }
    }

    // Registrierung des BroadcastReceivers
    val filter = IntentFilter().apply {
        addAction("com.symbol.datawedge.api.ACTION")
    }
    registerReceiver(broadcastReceiver, filter)
}

private fun configureScanner() {
    // Intent zur Konfiguration des DataWedge-Profils senden
    val intent = Intent("com.symbol.datawedge.api.ACTION").apply {
        putExtra("com.symbol.datawedge.api.SET_CONFIG", Bundle().apply {
            putString("PROFILE_NAME", "FlutterProfile")
            putString("PROFILE_ENABLED", "true")
            putString("CONFIG_MODE", "CREATE_IF_NOT_EXIST")
            putParcelableArray("APP_LIST", arrayOf(Bundle().apply {
                putString("PACKAGE_NAME", packageName)
                putStringArray("ACTIVITY_LIST", arrayOf("*"))
            }))
            putParcelableArray("PLUGIN_CONFIG", arrayOf(Bundle().apply {
                putString("PLUGIN_NAME", "BARCODE")
                putString("RESET_CONFIG", "true")
                putParcelable("PARAM_LIST", Bundle().apply {
                    putString("scanner_input_enabled", "true")
                })
            }))
        })
    }
    sendBroadcast(intent)
}

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(broadcastReceiver)
}
}


Dieser Code konfiguriert den Scanner über die DataWedge-API und leitet gescannte Daten an die Flutter-App weiter.

3. Flutter-Seite: UI und Plattformkanal-Kommunikation

Auf der Flutter-Seite wird die Kommunikation mit der Android-Ebene über MethodChannel hergestellt. Hier ist der Code für die Benutzeroberfläche:

Code für main.dart:


import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {

  runApp(const ZebraScannerApp());

}

class ZebraScannerApp extends StatelessWidget {

  const ZebraScannerApp({Key? key}) : super(key: key);

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'Zebra Scanner',

      theme: ThemeData(primarySwatch: Colors.blue),

      home: const ZebraScannerScreen(),

    );

  }

}

class ZebraScannerScreen extends StatefulWidget {

  const ZebraScannerScreen({Key? key}) : super(key: key);

  @override

  _ZebraScannerScreenState createState() => _ZebraScannerScreenState();

}

class _ZebraScannerScreenState extends State {

  static const platform = MethodChannel('zebra_scanner_channel');

  String _scannedData = 'Warten auf Scan...';

  @override

  void initState() {

    super.initState();

    configureScanner();

    platform.setMethodCallHandler((call) async {

      if (call.method == "onScannedData") {

        setState(() {

          _scannedData = call.arguments ?? "Keine Daten erhalten";

        });

      }

    });

  }

  Future configureScanner() async {

    try {

      await platform.invokeMethod('configureScanner');

    } catch (e) {

      setState(() {

        _scannedData = 'Scanner-Konfiguration fehlgeschlagen: $e';

      });

    }

  }

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: const Text('Zebra Scanner')),

      body: Column(

        mainAxisAlignment: MainAxisAlignment.center,

        crossAxisAlignment: CrossAxisAlignment.center,

        children: [

          // Anzeige der gescannten Daten

          Text(

            _scannedData,

            style: const TextStyle(fontSize: 18),

            textAlign: TextAlign.center,

          ),

          const SizedBox(height: 20),

          ElevatedButton(

            onPressed: () {

              setState(() {

                _scannedData = "Test-Barcode-Daten";

              });

            },

            child: const Text('Test Barcode Scan'),

          ),

        ],

      ),

    );

  }

}

Häufige Probleme und Lösungen

1. Jetpack Compose Referenzfehler

Fehlermeldung:

Unresolved reference: compose

Lösung:

Jetpack Compose wird für native Android-Apps verwendet. Da Flutter seine eigene UI-Bibliothek hat, entfernen Sie alle Jetpack Compose-Referenzen aus Ihrer MainActivity.kt.

2. Kommunikationsprobleme zwischen Flutter und Android

Fehlermeldung:

MethodChannel.invokeMethod not found.

Lösung:

• Überprüfen Sie, ob die Kanalnamen (zebra_scanner_channel) in Flutter und Kotlin identisch sind.

• Stellen Sie sicher, dass die Methode configureFlutterEngine korrekt implementiert ist.

3. DataWedge-Konfiguration funktioniert nicht

Lösung:

• Stellen Sie sicher, dass die DataWedge-App auf dem Zebra-Gerät installiert und aktiviert ist.

• Überprüfen Sie die manuelle Konfiguration der Benutzerprofile in DataWedge.