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.