You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Flutter Android应用配置Zebra MC3300R实现RFID扫描

Zebra MC3300R RFID扫描配置问题

我正在为Flutter Android应用配置Zebra MC3300R设备以实现RFID标签扫描,此前已成功配置RFD8500且运行正常。我能在Zebra MC3300R移动计算机上运行Flutter应用(使用.aar文件,也可通过USB连接运行),但配置MC3300R时出现以下错误日志:

I/flutter ( 8933): Bluetooth permissions granted.
D/RFIDAPI3Error( 8933): RfidUsbMgr: connection failed: device not found
E/MainActivity( 8933): Number of available RFID readers: 0

请问是否有针对MC3300R的不同配置方式?


针对MC3300R的配置调整建议

MC3300R是集成式RFID阅读器(而非RFD8500这类外接蓝牙阅读器),不能沿用蓝牙传输的初始化逻辑,需做以下调整:

  • 修改阅读器传输类型
    初始化Readers时,将ENUM_TRANSPORT.BLUETOOTH改为ENUM_TRANSPORT.SERVICE,因为MC3300R的RFID模块是设备内置的,通过系统服务通信:

    readers = new Readers(this, ENUM_TRANSPORT.SERVICE);
    
  • 添加必要权限
    在AndroidManifest.xml中补充内置阅读器所需权限:

    <uses-permission android:name="com.zebra.rfid.api3.permission.ACCESS_RFID_SERVICE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- Android 12+ 蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    
  • 修正触发配置逻辑
    原代码中重复设置了StopTrigger类型,需保留唯一配置以适配设备物理按键:

    TriggerInfo triggerInfo = new TriggerInfo();
    triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_HANDHELD);
    triggerInfo.StartTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED);
    // 仅保留一个StopTrigger配置
    triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_HANDHELD_WITH_TIMEOUT);
    triggerInfo.StopTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED);
    triggerInfo.StopTrigger.Handheld.setHandheldTriggerTimeout(0);
    
  • 检查设备RFID服务状态
    确保MC3300R设备上的RFID服务已启用:

    • 打开设备设置,找到"RFID"选项
    • 确认RFID模块处于开启状态
    • 将"RFID Mode"设置为"Application Controlled"

修改后的完整代码

package com.apptricity.asset_mobile;

import android.os.Bundle;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
import com.zebra.rfid.api3.*;
import android.util.Log;
import java.util.ArrayList;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.apptricity.asset_mobile/zebra_rfid";
    private Readers readers;
    private RFIDReader rfidReader;
    private EventHandler eventHandler;
    private static final String TAG = "MainActivity";
    private MethodChannel channel;

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        
        channel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
        channel.setMethodCallHandler(
            (call, result) -> {
                switch (call.method) {
                    case "initializeAndConnect":
                        initializeAndConnect(result);
                        break;
                    case "startInventory":
                        startInventory();
                        result.success(null);
                        break;
                    case "stopInventory":
                        stopInventory();
                        result.success(null);
                        break;
                    default:
                        result.notImplemented();
                        break;
                }
            }
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (rfidReader != null) {
                rfidReader.Events.removeEventsListener(eventHandler);
                rfidReader.disconnect();
                rfidReader = null;
                readers.Dispose();
                readers = null;
            }
        } catch (InvalidUsageException e) {
            e.printStackTrace();
        } catch (OperationFailureException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initializeAndConnect(MethodChannel.Result result) {
        try {
            // 修改传输类型为SERVICE
            readers = new Readers(this, ENUM_TRANSPORT.SERVICE);
            ArrayList<ReaderDevice> availableRFIDReaderList = readers.GetAvailableRFIDReaderList();
                Log.e(TAG, "Number of available RFID readers: " + availableRFIDReaderList.size());
        
        // 打印可用阅读器详情
        for (ReaderDevice readerDevice : availableRFIDReaderList) {
            String deviceInfo = "Reader Device: " + readerDevice.getName() + ", Address: " + readerDevice.getAddress();
            Log.e(TAG, deviceInfo);
        }

            if (!availableRFIDReaderList.isEmpty()) {
                ReaderDevice readerDevice = availableRFIDReaderList.get(0);
                
                // 连接第一个可用阅读器
                rfidReader = readerDevice.getRFIDReader();
                if (!rfidReader.isConnected()) {
                    rfidReader.connect();
                    ConfigureReader();
                    result.success(true); 
                    
                } else {
                    result.success(true);
                }
            } else {
            // 无可用阅读器
            result.success(false); // 返回失败标识
        }

        } catch (Exception e) {
            Log.e(TAG, "Error initializing RFID reader", e);
        }
    }

    private void ConfigureReader() {
        if (rfidReader.isConnected()) {
            TriggerInfo triggerInfo = new TriggerInfo();
            triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_HANDHELD);
            triggerInfo.StartTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED);
            // 修正重复设置StopTrigger的问题
            triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_HANDHELD_WITH_TIMEOUT);
            triggerInfo.StopTrigger.Handheld.setHandheldTriggerEvent(HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED);
            triggerInfo.StopTrigger.Handheld.setHandheldTriggerTimeout(0);
            try {
                if (eventHandler == null) {
                    eventHandler = new EventHandler(channel, rfidReader);
                }
                rfidReader.Events.addEventsListener(eventHandler);
                rfidReader.Events.setHandheldEvent(true);
                rfidReader.Events.setTagReadEvent(true);
                rfidReader.Events.setAttachTagDataWithReadEvent(false);
                rfidReader.Config.setTriggerMode(ENUM_TRIGGER_MODE.RFID_MODE, true);
                rfidReader.Config.setStartTrigger(triggerInfo.StartTrigger);
                rfidReader.Config.setStopTrigger(triggerInfo.StopTrigger);
            } catch (InvalidUsageException | OperationFailureException e) {
                Log.e(TAG, "Error configuring RFID reader", e);
            }
        }
    }

private void startInventory() {
    if (rfidReader != null) {
        Log.d(TAG, "RFIDReader is not null. Checking connection...");
        if (rfidReader.isConnected()) {
            Log.d(TAG, "RFIDReader is connected. Attempting to start inventory.");
            try {
                rfidReader.Actions.Inventory.perform();
            } catch (InvalidUsageException | OperationFailureException e) {
                Log.e(TAG, "Error starting inventory", e);
            }
        } else {
            Log.e(TAG, "RFIDReader is not initialized or connected.");
        }
    } else {
        Log.e(TAG, "RFIDReader is null.");
    }
}

    private void stopInventory() {
        try {
            rfidReader.Actions.Inventory.stop();
        } catch (InvalidUsageException | OperationFailureException e) {
            Log.e(TAG, "Error stopping inventory", e);
        }
    }

    public class EventHandler implements RfidEventsListener {
        private MethodChannel channel;
        private RFIDReader rfidReader;

        public EventHandler(MethodChannel channel, RFIDReader rfidReader) {
            this.channel = channel;
            this.rfidReader = rfidReader;
        }

        @Override
public void eventReadNotify(RfidReadEvents e) {
    TagData[] myTags = rfidReader.Actions.getReadTags(100);
    if (myTags != null && myTags.length > 0) {
        String firstTagId = myTags[0].getTagID();
            Log.d(TAG, "First read tag ID: " + firstTagId);
        
        ArrayList<String> tagIdList = new ArrayList<>();
        tagIdList.add(firstTagId);

        runOnUiThread(() -> channel.invokeMethod("onTagRead", tagIdList));
    }
}

        @Override
        public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) {
                Log.d(TAG, "Status Notification: " + rfidStatusEvents.StatusEventData.getStatusEventType());
        if (rfidStatusEvents.StatusEventData.getStatusEventType() == STATUS_EVENT_TYPE.HANDHELD_TRIGGER_EVENT) {
            HANDHELD_TRIGGER_EVENT_TYPE triggerType = rfidStatusEvents.StatusEventData.HandheldTriggerEventData.getHandheldEvent();
            if (triggerType == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED) {
                // 触发按下逻辑
            } else if (triggerType == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED) {
                // 触发松开逻辑
            }
        }
        }
    }
}

内容的提问来源于stack exchange,提问作者Anamika Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:05:54