Scan-Scan-Write

RFID SDK For Android 2.0.4.192

Overview

This guide provides a walk-through for creating an application that uses barcode scanning and RFID APIs to implement a scan-scan-write workflow. The application allows users to:

  1. Scan a product barcode
  2. Convert that barcode to a SGTIN-96 format EPC
  3. Scan a RFID tag with barcode
  4. Write the converted EPC to the scanned RFID tag

Note: The demo app in this guide is intended for tutorial purposes only and should not be used in production environments.


Prerequisites

  1. Developer machine with latest Android studio

  2. Developer machine with Zebra Android device USB driver installed

  3. Zebra Android device with developer mode turned on

  4. Reader regulatory is configured as per norms using RFID Manager or Zebra RFID Demo application

  5. DataWedge profile configured for barcode scanning

Create The Project

Start by creating a new project in Android Studio. Call it Scan-Scan-Write to match later references in this guide. For help, see the Android Studio tutorial.

Adding essentials

Modify the application's MainActivity.java file to use the RFID SDK library.

  1. Declare RFID readers fields:

    
        private static Readers readers;`
        private static ArrayList availableRFIDReaderList;
        private static ReaderDevice readerDevice;
        private static RFIDReader reader;
        private static String TAG = "DEMO";
    
  2. Create SDK Readers instance

    
        // SDK
        if (readers == null) {
            readers = new Readers(this, ENUM_TRANSPORT.SERVICE_SERIAL);
        }
    

    Note : For RFD40XX USB connectivity create reader instance with

    
        readers = new Readers(this, ENUM_TRANSPORT.SERVICE_USB)
    

    Note : For Bluetooth instance

    
        readers = new Readers(this, ENUM_TRANSPORT.BLUETOOTH)
    

    Note : For TC53E/EM45/ET6x device

    
        readers = new Readers(this, ENUM_TRANSPORT.RE_SERIAL)
    
  3. Create AsyncTask to retrieve available readers using GetAvailableRFIDReaderList

    
        new AsyncTask() {
            @Override
            protected Boolean doInBackground(Void... voids) {
                try {
                    if (readers != null) {
                        if (readers.GetAvailableRFIDReaderList() != null) {
                            availableRFIDReaderList = readers.GetAvailableRFIDReaderList();
                            if (availableRFIDReaderList.size() != 0) {
                                // get first reader from list
                                readerDevice = availableRFIDReaderList.get(0);
                                reader = readerDevice.getRFIDReader();
                                if (!reader.isConnected()) {
                                    // Establish connection to the RFID Reader
                                    reader.connect();
                                    ConfigureReader();
                                    return true;
                                }
                            }
                        }
                    }
                } catch (InvalidUsageException e) {
                    e.printStackTrace();
                } catch (OperationFailureException e) {
                    e.printStackTrace();
                    Log.d(TAG, "OperationFailureException " + e.getVendorMessage());
                }
                return false;
            }
    
            @Override
            protected void onPostExecute(Boolean aBoolean) {
                super.onPostExecute(aBoolean);
                if (aBoolean) {
                    Toast.makeText(getApplicationContext(), "Reader Connected", Toast.LENGTH_LONG).show();
                    //textView.setText("Reader connected");
                }
            }
        }.execute();
    
  4. Add ConfigureReader method to configure the reader for trigger type and adding event handler / listener addEventsListener

    
        private void ConfigureReader() {
            if (reader.isConnected()) {
                TriggerInfo triggerInfo = new TriggerInfo();
                triggerInfo.StartTrigger.setTriggerType(START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE);
                triggerInfo.StopTrigger.setTriggerType(STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_IMMEDIATE);
                try {
                    // receive events from reader
                    if (eventHandler == null)
                        eventHandler = new EventHandler();
                    reader.Events.addEventsListener(eventHandler);
                    // HH event
                    reader.Events.setHandheldEvent(true);
                    // tag event with tag data
                    reader.Events.setTagReadEvent(true);
                    // application will collect tag using getReadTags API
                    reader.Events.setAttachTagDataWithReadEvent(false);
                    // set trigger mode as rfid so scanner beam will not come
                    reader.Config.setTriggerMode(ENUM_TRIGGER_MODE.RFID_MODE, true);
                    // set start and stop triggers
                    reader.Config.setStartTrigger(triggerInfo.StartTrigger);
                    reader.Config.setStopTrigger(triggerInfo.StopTrigger);
                } catch (InvalidUsageException e) {
                    e.printStackTrace();
                } catch (OperationFailureException e) {
                    e.printStackTrace();
                }
            }
        }
    
  5. Add EventHandler class to handle Reader operation events - eventReadNotify and Reader status events - eventStatusNotify

    
        // Read/Status Notify handler
        // Implement the RfidEventsListener class to receive event notifications
        public class EventHandler implements RfidEventsListener {
            // Read Event Notification
            public void eventReadNotify(RfidReadEvents e) {
                TagData[] tags = reader.Actions.getReadTags(100);
                int accessSuccess = 0;
                int accessFailure = 0;
                
                if (tags != null && currentState == WorkflowState.WRITING) {
                    for (TagData tag : tags) {
                        Log.d(TAG, tag.getTagID() + " :: " + tag.getOpCode() + " :: " + tag.getOpStatus());
                        
                        if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "LOCK SUCCESS");
                            }
                        } else if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "WRITE SUCCESS");
                            }
                        } else if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "READ SUCCESS");
                            }
                        }
                        
                        if (tag.getOpStatus() != ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                            accessFailure++;
                            try {
                                reader.Actions.TagAccess.OperationSequence.deleteAll();
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                        
                        if (accessSuccess == 4) {
                            System.out.println(tag.getTagID() + " ALL Encoding Success ");
                            try {
                                reader.Actions.TagAccess.OperationSequence.deleteAll();
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                    
                    // Update UI based on operation results
                    final int finalAccessSuccess = accessSuccess;
                    runOnUiThread(() -> {
                        if (finalAccessSuccess == 4) {
                            Toast.makeText(MainActivity.this,
                            "Tag written successfully!", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(MainActivity.this,
                            "Tag operation failed. Only " + finalAccessSuccess + " of 4 operations succeeded",
                            Toast.LENGTH_LONG).show();
                        }
                        currentState = WorkflowState.IDLE;
                        updateStatusDisplay();
                    });
                }
            }
         
            // Status Event Notification
            public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) {
                Log.d(TAG, "Status Notification: " + rfidStatusEvents.StatusEventData.getStatusEventType());
            }
         
        }
        
    

Running the application

Connection with device

  1. Connect any android terminal with PC over USB

  2. Make sure project is already built successfully

  3. Click on Run app (shift+F10) from top right corner

  4. Now Application should be launched on Zebra Android device.

  5. Application should be showing Reader connected toast message on screen

  6. img

    img

    img

Programming tips

  1. GetAvailableRFIDReaderList must be called from background thread, in current example uses AsyncTask for same purpose

  2. At time of exit, application shounld disconnect with reader using Disconnect API and free up SDK instance. Refer MainActivity OnDestroy method

  3. In case of failures or exceptions, refer messages returned by API call to get more details

What's Next

Add code to perfrom Scan-Scan-Write.

  1. Create states to track the multi-step operation.

    
        // State tracking for scan-scan-write workflow
        private enum WorkflowState {
            IDLE,              // Waiting to start
            FIRST_BARCODE_SCANNED, // First barcode scanned, waiting for RFID tag barcode
            SECOND_BARCODE_SCANNED, // Tag ID scanned, ready to write
            WRITING            // Writing in progress
        }
    
        private WorkflowState currentState = WorkflowState.IDLE;
        private String scannedBarcode = null;
        private String scannedTagId = null;
        private EPC encodedEpc = null;
        private TextView statusTextView;
        private final String ACCESS_PASSWORD = "00000000";
    
    
  2. Initialize Components

    Set up the required components in the onCreate() method

    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        
            // Initialize the status TextView
            statusTextView = findViewById(R.id.statusTextView);
        
            // Initialize RFID reader
            if (readers == null) {
                readers = new Readers(this, ENUM_TRANSPORT.SERVICE_USB);
            }
            // Connect to the RFID reader
            new ConnectionTask().execute();
        
            // Initialize barcode to RFID conversion API
            BarcodeToRfidApi.initialize(this);
        
            // Register the barcode receiver
            IntentFilter filter = new IntentFilter();
            filter.addAction(DataWedge.INTENT_NAME);
            filter.addCategory(Intent.CATEGORY_DEFAULT);
            registerReceiver(barcodeReceiver, filter, Context.RECEIVER_EXPORTED);
        
            // Set up scan-scan-write button
            Button btnScanScanWrite = findViewById(R.id.btnScanScanWrite);
            btnScanScanWrite.setOnClickListener(v -> {
                if (reader != null && reader.isConnected()) {
                    // Reset the workflow
                    currentState = WorkflowState.IDLE;
                    scannedBarcode = null;
                    scannedTagId = null;
                    encodedEpc = null;
                    updateStatusDisplay();
                    // Start the workflow - trigger barcode scanner
                    startBarcodeScanning();
                } else {
                    Toast.makeText(this, "RFID Reader not connected", Toast.LENGTH_SHORT).show();
                }
            });
        }
    
  3. Barcode Scanning

    Trigger the barcode scanner using DataWedge

    
        private void startBarcodeScanning() {
            // Trigger DataWedge scanner
            Intent dwIntent = new Intent();
            dwIntent.setAction("com.symbol.datawedge.api.ACTION");
            dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "START_SCANNING");
            sendBroadcast(dwIntent);
            Toast.makeText(this, "Please scan a barcode", Toast.LENGTH_SHORT).show();
        }    
    
  4. Processing Barcode Scans

    Create a BroadcastReceiver to handle barcode scan results

    
        private final BroadcastReceiver barcodeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
        
                if (action != null && action.equals(DataWedge.INTENT_NAME)) {
                    // Barcode scan from DataWedge
                    String barcode = intent.getStringExtra(DataWedge.DATAWEDGE_EXTRA);
        
                    if (barcode != null && !barcode.isEmpty()) {
                       Log.d(TAG, "Scanned barcode: " + barcode);
        
                        // Stop barcode scanner
                        Intent dwIntent = new Intent();
                        dwIntent.setAction("com.symbol.datawedge.api.ACTION");
                        dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "STOP_SCANNING");
                        context.sendBroadcast(dwIntent);
        
                        // Process based on current state
                        if (currentState == WorkflowState.IDLE) {
                            // First barcode scan - product barcode
                            try {
                                // Process the barcode with BarcodeToRfidApi
                                encodedEpc = BarcodeToRfidApi.encodeBarcodeToRfid(barcode, "1234567890");
                                Log.d(TAG, "Encoded EPC: " + encodedEpc.toString());
        
                                // Store barcode and update state
                                scannedBarcode = barcode;
                                currentState = WorkflowState.FIRST_BARCODE_SCANNED;
                                updateStatusDisplay();
        
                                // Start second barcode scan after a short delay
                                new Handler().postDelayed(() -> startBarcodeScanning(), 1000);
                            } catch (Exception e) {
                                Log.e(TAG, "Error processing barcode", e);
                                Toast.makeText(context, "Error processing barcode: " + e.getMessage(),
                                        Toast.LENGTH_SHORT).show();
                                currentState = WorkflowState.IDLE;
                                updateStatusDisplay();
                            }
                        }
                        else if (currentState == WorkflowState.FIRST_BARCODE_SCANNED) {
                            // Second barcode scan - RFID tag ID
                            scannedTagId = barcode;
                            currentState = WorkflowState.SECOND_BARCODE_SCANNED;
                            updateStatusDisplay();
        
                            // Ask user to confirm write
                            runOnUiThread(() -> {
                                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                                builder.setTitle("Confirm Write");
                                builder.setMessage("Write EPC " + encodedEpc.toString() + " to tag " + scannedTagId + "?");
                                builder.setPositiveButton("Write", (dialog, which) -> {
                                    unlockAndWriteEpcToTag(scannedTagId, encodedEpc);
                                });
                                builder.setNegativeButton("Cancel", (dialog, which) -> {
                                    currentState = WorkflowState.IDLE;
                                    updateStatusDisplay();
                                });
                                builder.show();
                            });
                        }
                    }
                }
            }
        };       
    
  5. Converting Barcode to RFID EPC Format

    The BarcodeToRfidApi class provides the interface between barcode data and RFID EPC format

    
        public class BarcodeToRfidApi {
            public static void initialize(Context context) {
                EPCConverter.initEpcConverter(context);
                DataWedge.setDWProfile(context);
            }
        
            public static EPC encodeBarcodeToRfid(String scannedUpc, String serialNumber) {
                EPC epc = EPCConverter.encodeSGTIN96(scannedUpc, serialNumber);
                return epc;
            }
        }
    
  6. 
        package com.zebra.ssw.EncodeBarcodeToRFID;
    
        import androidx.annotation.NonNull;
        import java.io.Serializable;
    
        public class EPC implements Serializable {
    
            public static final EPC DEFAULT = new EPC("0000000000000");
    
            private final String content;
    
            public EPC(String s) {
                content = s.toUpperCase();
            }
        }
    
  7. Create a filter to specify which tags should be operated on

    
        private AccessFilter setAccessFilter(String tagID) {
            int len = tagID.length()/2;
            AccessFilter accessFilter = new AccessFilter();
            byte[] tagMask = new byte[len];
            byte[] tagData = hexStringToByteArray(tagID);
            for(int i= 0; i < len; i++){
                tagMask[i] = (byte)0xff;
            }
        
            // Tag Pattern A
            accessFilter.TagPatternA.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC);
            accessFilter.TagPatternA.setTagPattern(tagData);
            accessFilter.TagPatternA.setTagPatternBitCount(len*8);
            accessFilter.TagPatternA.setBitOffset(32);
            accessFilter.TagPatternA.setTagMask(tagMask);
            accessFilter.TagPatternA.setTagMaskBitCount(tagMask.length*8);
            accessFilter.setAccessFilterMatchPattern(FILTER_MATCH_PATTERN.A);
            return accessFilter;
        }
    
  8. Writing to RFID Tag

    Perform the write operation using a sequence of RFID tag access operations

    
        private void unlockAndWriteEpcToTag(String tagId, EPC newEpc) {
            currentState = WorkflowState.WRITING;
            updateStatusDisplay();
        
            try {
                //operation sequence for unlock-write-lock
                performTagOperationSequence(tagId, newEpc.toString());
                Log.d(TAG, "Tag operation sequence started successfully");
        
            } catch (InvalidUsageException | OperationFailureException e) {
                Log.e(TAG, "Error in tag operation sequence", e);
                runOnUiThread(() -> Toast.makeText(MainActivity.this,
                        "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
                currentState = WorkflowState.IDLE;
                updateStatusDisplay();
            }
        }    
    
  9. RFID Access Sequence Operation

    Define the sequence of operations to unlock, write, and lock the RFID tag

    
        private void performTagOperationSequence(String tagId, String epcData)
            throws OperationFailureException, InvalidUsageException {
    
            Log.d(TAG, "Starting operation sequence for tag: " + tagId);
            long accessPassword = Long.parseLong(ACCESS_PASSWORD, 16);
    
            try {
                reader.Actions.TagAccess.OperationSequence.deleteAll();
            } catch (Exception e) {
                Log.w(TAG, "Error clearing operation sequence", e);
            }
    
            TagAccess tagAccess = reader.Actions.TagAccess;
            TagAccess.Sequence opSequence = tagAccess.new Sequence(tagAccess);
    
            // Operation 1: Read TID memory bank
            TagAccess.Sequence.Operation op1 = opSequence.new Operation();
            op1.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ);
            op1.ReadAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_TID);
            op1.ReadAccessParams.setCount(1);
            op1.ReadAccessParams.setOffset(0);
            reader.Actions.TagAccess.OperationSequence.add(op1);
    
            // Operation 2: Unlock the EPC Memory
            TagAccess.Sequence.Operation unlockOp = opSequence.new Operation();
            unlockOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK);
            unlockOp.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY,
                    LOCK_PRIVILEGE.LOCK_PRIVILEGE_UNLOCK);
            unlockOp.LockAccessParams.setAccessPassword(Long.decode("0X" + accessPassword));
            reader.Actions.TagAccess.OperationSequence.add(unlockOp);
    
            // Operation 3: Write EPC to tag
            TagAccess.Sequence.Operation writeOp = opSequence.new Operation();
            writeOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE);
            writeOp.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC);
            writeOp.WriteAccessParams.setOffset(2);
            writeOp.WriteAccessParams.setWriteData(epcData);
            writeOp.WriteAccessParams.setWriteDataLength(epcData.length()/4);
            reader.Actions.TagAccess.OperationSequence.add(writeOp);
    
            // Operation 4: Lock the EPC Memory
            TagAccess.Sequence.Operation lockOp = opSequence.new Operation();
            lockOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK);
            lockOp.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY,
                    LOCK_PRIVILEGE.LOCK_PRIVILEGE_READ_WRITE);
            lockOp.LockAccessParams.setAccessPassword(Long.decode("0X" + accessPassword));
            reader.Actions.TagAccess.OperationSequence.add(lockOp);
    
            // Execute the sequence on the specific tag
            reader.Actions.TagAccess.OperationSequence.performSequence(setAccessFilter(tagId), null, null);
        }
    

Complete Implementation

Below is the complete implementation which combines all the code snippets discussed earlier. This class handles RFID reader initialization, connection, configuration, event handling, and performs scan-scan-write. Key features include:

  • MainActivity: Manages the workflow and RFID operations. Controls the UI state transitions and implements the scan-scan-write process flow. Handles RFID reader connections and events, including tag access operations.
  • EPCConverter: Converts barcode formats to RFID EPC format. Contains algorithms to properly encode UPC product codes into standardized SGTIN-96 EPC format following GS1 specifications.
  • DataWedge: Handles barcode scanning integration. Provides constants and methods to communicate with Zebra's DataWedge service for triggering barcode scans and receiving scan results.
  • EPC: Represents an Electronic Product Code used in RFID tags. Contains the data structure and formatting rules for EPCs, supporting different encoding schemes and providing string representation methods for display and debugging.

Complete MainActivity.java Implementation


    package com.zebra.ssw;

    import androidx.appcompat.app.AppCompatActivity;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import com.zebra.ssw.EncodeBarcodeToRFID.DataWedge;
    import com.zebra.ssw.EncodeBarcodeToRFID.EPC;
    import com.zebra.rfid.api3.ACCESS_OPERATION_CODE;
    import com.zebra.rfid.api3.ACCESS_OPERATION_STATUS;
    import com.zebra.rfid.api3.AccessFilter;
    import com.zebra.rfid.api3.ENUM_TRANSPORT;
    import com.zebra.rfid.api3.FILTER_MATCH_PATTERN;
    import com.zebra.rfid.api3.InvalidUsageException;
    import com.zebra.rfid.api3.LOCK_DATA_FIELD;
    import com.zebra.rfid.api3.LOCK_PRIVILEGE;
    import com.zebra.rfid.api3.MEMORY_BANK;
    import com.zebra.rfid.api3.OperationFailureException;
    import com.zebra.rfid.api3.RFIDReader;
    import com.zebra.rfid.api3.ReaderDevice;
    import com.zebra.rfid.api3.Readers;
    import com.zebra.rfid.api3.RfidEventsListener;
    import com.zebra.rfid.api3.RfidReadEvents;
    import com.zebra.rfid.api3.RfidStatusEvents;
    import com.zebra.rfid.api3.TagAccess;
    import com.zebra.rfid.api3.TagData;
    import java.security.InvalidParameterException;
    import java.util.ArrayList;
    import android.app.AlertDialog;
    import android.os.Handler;
    
    public class MainActivity extends AppCompatActivity {
    
        private  final String TAG = "sswApp";
        private Readers readers;
        private ReaderDevice readerDevice;
        private EventHandler eventHandler;
    
    
        // State tracking for scan-scan-write workflow
        private enum WorkflowState {
            IDLE,              // Waiting to start
            FIRST_BARCODE_SCANNED, // First barcode scanned, waiting for RFID tag barcode
            SECOND_BARCODE_SCANNED, // Tag ID scanned, ready to write
            WRITING            // Writing in progress
        }
    
        private WorkflowState currentState = WorkflowState.IDLE;
        private String scannedBarcode = null;
        private String scannedTagId = null;
        private EPC encodedEpc = null;
        private TextView statusTextView;
        private final String ACCESS_PASSWORD = "00000000";
    
        static RFIDReader reader;
        private ArrayList availableRFIDReaderList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Initialize the status TextView
            statusTextView = findViewById(R.id.statusTextView);
    
            if (readers == null) {
                readers = new Readers(this, ENUM_TRANSPORT.SERVICE_USB);
            }
            System.out.println("Connection BEGINS");
            new ConnectionTask().execute();
    
    
            BarcodeToRfidApi.initialize(this);
    
            // Register the barcode receiver
            IntentFilter filter = new IntentFilter();
            filter.addAction(DataWedge.INTENT_NAME);
            filter.addCategory(Intent.CATEGORY_DEFAULT);
            registerReceiver(barcodeReceiver, filter, Context.RECEIVER_EXPORTED);
    
    
            //scan-scan-write button
            Button btnScanScanWrite = findViewById(R.id.btnScanScanWrite);
            btnScanScanWrite.setOnClickListener(v -> {
                if (reader != null && reader.isConnected()) {
                    // Reset the workflow
                    currentState = WorkflowState.IDLE;
                    scannedBarcode = null;
                    scannedTagId = null;
                    encodedEpc = null;
                    updateStatusDisplay();
                    // Start the workflow - trigger barcode scanner
                    startBarcodeScanning();
                } else {
                    Toast.makeText(this, "RFID Reader not connected", Toast.LENGTH_SHORT).show();
                }
            });
        }
    
    
        @Override
        protected void onPause() {
            super.onPause();
            // Unregister barcode receiver
            try {
                unregisterReceiver(barcodeReceiver);
            } catch (IllegalArgumentException e) {
                // Receiver not registered
            }
        }
    
        private void updateStatusDisplay() {
            runOnUiThread(() -> {
                // Null check to avoid crashes
                if (statusTextView == null) {
                    Log.e(TAG, "Status TextView not initialized!");
                    return;
                }
    
                switch (currentState) {
                    case IDLE:
                        statusTextView.setText("Ready to scan product barcode");
                        break;
                    case FIRST_BARCODE_SCANNED:
                        statusTextView.setText("Product barcode scanned: " + scannedBarcode +
                                "\nNow scan RFID tag barcode");
                        break;
                    case SECOND_BARCODE_SCANNED:
                        statusTextView.setText("Product barcode: " + scannedBarcode +
                                "\nTag ID: " + scannedTagId +
                                "\nReady to write");
                        break;
                    case WRITING:
                        statusTextView.setText("Writing to tag...");
                        break;
                }
            });
        }
    
    
        private void startBarcodeScanning() {
            // Trigger DataWedge scanner
            Intent dwIntent = new Intent();
            dwIntent.setAction("com.symbol.datawedge.api.ACTION");
            dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "START_SCANNING");
            sendBroadcast(dwIntent);
            Toast.makeText(this, "Please scan a barcode", Toast.LENGTH_SHORT).show();
        }
    
        private final BroadcastReceiver barcodeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
    
                if (action != null && action.equals(DataWedge.INTENT_NAME)) {
                    // Barcode scan from DataWedge
                    String barcode = intent.getStringExtra(DataWedge.DATAWEDGE_EXTRA);
    
                    if (barcode != null && !barcode.isEmpty()) {
                        Log.d(TAG, "Scanned barcode: " + barcode);
    
                        // Stop barcode scanner
                        Intent dwIntent = new Intent();
                        dwIntent.setAction("com.symbol.datawedge.api.ACTION");
                        dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "STOP_SCANNING");
                        context.sendBroadcast(dwIntent);
    
                        // Process based on current state
                        if (currentState == WorkflowState.IDLE) {
                            // First barcode scan - product barcode
                            try {
                                // Process the barcode with BarcodeToRfidApi
                                encodedEpc = BarcodeToRfidApi.encodeBarcodeToRfid(barcode, "1234567890");
                                Log.d(TAG, "Encoded EPC: " + encodedEpc.toString());
    
                                // Store barcode and update state
                                scannedBarcode = barcode;
                                currentState = WorkflowState.FIRST_BARCODE_SCANNED;
                                updateStatusDisplay();
    
                                // Start second barcode scan after a short delay
                                new Handler().postDelayed(() -> startBarcodeScanning(), 1000);
                            } catch (Exception e) {
                                Log.e(TAG, "Error processing barcode", e);
                                Toast.makeText(context, "Error processing barcode: " + e.getMessage(),
                                        Toast.LENGTH_SHORT).show();
                                currentState = WorkflowState.IDLE;
                                updateStatusDisplay();
                            }
                        }
                        else if (currentState == WorkflowState.FIRST_BARCODE_SCANNED) {
                            // Second barcode scan - RFID tag ID
                            scannedTagId = barcode;
                            currentState = WorkflowState.SECOND_BARCODE_SCANNED;
                            updateStatusDisplay();
    
                            // Ask user to confirm write
                            runOnUiThread(() -> {
                                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                                builder.setTitle("Confirm Write");
                                builder.setMessage("Write EPC " + encodedEpc.toString() + " to tag " + scannedTagId + "?");
                                builder.setPositiveButton("Write", (dialog, which) -> {
                                    unlockAndWriteEpcToTag(scannedTagId, encodedEpc);
                                });
                                builder.setNegativeButton("Cancel", (dialog, which) -> {
                                    currentState = WorkflowState.IDLE;
                                    updateStatusDisplay();
                                });
                                builder.show();
                            });
                        }
                    }
                }
            }
        };
    
    
        private void unlockAndWriteEpcToTag(String tagId, EPC newEpc) {
            currentState = WorkflowState.WRITING;
            updateStatusDisplay();
    
            try {
                //operation sequence for unlock-write-lock
                performTagOperationSequence(tagId, newEpc.toString());
                Log.d(TAG, "Tag operation sequence started successfully");
    
            } catch (InvalidUsageException | OperationFailureException e) {
                Log.e(TAG, "Error in tag operation sequence", e);
                runOnUiThread(() -> Toast.makeText(MainActivity.this,
                        "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
                currentState = WorkflowState.IDLE;
                updateStatusDisplay();
            }
        }
    
        private void performTagOperationSequence(String tagId, String epcData)
                throws OperationFailureException, InvalidUsageException {
    
            Log.d(TAG, "Starting operation sequence for tag: " + tagId);
            long accessPassword = Long.parseLong(ACCESS_PASSWORD, 16);
    
            try {
                reader.Actions.TagAccess.OperationSequence.deleteAll();
            } catch (Exception e) {
                Log.w(TAG, "Error clearing operation sequence", e);
            }
    
            TagAccess tagAccess = reader.Actions.TagAccess;
            TagAccess.Sequence opSequence = tagAccess.new Sequence(tagAccess);
    
            TagAccess.Sequence.Operation op1 = opSequence.new Operation();
            op1.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ);
            op1.ReadAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_TID);
            op1.ReadAccessParams.setCount(1);
            op1.ReadAccessParams.setOffset(0);
            reader.Actions.TagAccess.OperationSequence.add(op1);
    
            //operation 1: Unlock the EPC Memory
            TagAccess.Sequence.Operation unlockOp = opSequence.new Operation();
            unlockOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK);
            unlockOp.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY,
                    LOCK_PRIVILEGE.LOCK_PRIVILEGE_UNLOCK);
            unlockOp.LockAccessParams.setAccessPassword(Long.decode("0X" + accessPassword));
            reader.Actions.TagAccess.OperationSequence.add(unlockOp);
    
            //operation 2: Write EPC to tag
            TagAccess.Sequence.Operation writeOp = opSequence.new Operation();
            writeOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE);
            writeOp.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC);
            writeOp.WriteAccessParams.setOffset(2);
            writeOp.WriteAccessParams.setWriteData(epcData);
            writeOp.WriteAccessParams.setWriteDataLength(epcData.length()/4);
            reader.Actions.TagAccess.OperationSequence.add(writeOp);
    
            //operation 3: Lock the EPC Memory
            TagAccess.Sequence.Operation lockOp = opSequence.new Operation();
            lockOp.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK);
            lockOp.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY,
                    LOCK_PRIVILEGE.LOCK_PRIVILEGE_READ_WRITE);
            lockOp.LockAccessParams.setAccessPassword(Long.decode("0X" + accessPassword));
            reader.Actions.TagAccess.OperationSequence.add(lockOp);
    
            // Execute the sequence on the specific tag
            reader.Actions.TagAccess.OperationSequence.performSequence(setAccessFilter(tagId), null, null);
        }
    
    
        //Utility functions
        private AccessFilter setAccessFilter(String tagID) {
            int len = tagID.length()/2;
            AccessFilter accessFilter = new AccessFilter();
            byte[] tagMask = new byte[len];
            byte[] tagData = hexStringToByteArray(tagID);
            for(int i= 0; i < len; i++){
                tagMask[i] = (byte)0xff;
            }
    
            // Tag Pattern A
            accessFilter.TagPatternA.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC);
            accessFilter.TagPatternA.setTagPattern(tagData);
            accessFilter.TagPatternA.setTagPatternBitCount(len*8);
            accessFilter.TagPatternA.setBitOffset(32);
            accessFilter.TagPatternA.setTagMask(tagMask);
            accessFilter.TagPatternA.setTagMaskBitCount(tagMask.length*8);
            accessFilter.setAccessFilterMatchPattern(FILTER_MATCH_PATTERN.A);
            return accessFilter;
        }
    
        public static byte[] hexStringToByteArray(String hexString) {
            int length = hexString.length();
            byte[] buffer = new byte[length / 2];
    
            for (int i = 0; i < length; i += 2) {
                buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString
                        .charAt(i + 1)));
            }
    
            return buffer;
        }
        private static int toByte(char c) {
            if (c >= '0' && c <= '9')
                return (c - '0');
            if (c >= 'A' && c <= 'F')
                return (c - 'A' + 10);
            if (c >= 'a' && c <= 'f')
                return (c - 'a' + 10);
    
            throw new InvalidParameterException("Invalid hex char '" + c + "'");
        }
    
        private class ConnectionTask extends AsyncTask {
            protected Boolean doInBackground(Void... voids) {
                try {
                    if (readers != null) {
                        System.out.println("Connection start");
                        if (readers.GetAvailableRFIDReaderList() != null) {
                            availableRFIDReaderList = readers.GetAvailableRFIDReaderList();
                            if (availableRFIDReaderList.size() != 0) {
                                // get first reader from list
                                readerDevice = availableRFIDReaderList.get(0);
                                reader = readerDevice.getRFIDReader();
                                if (!reader.isConnected()) {
                                    reader.connect();
                                    ConfigureReader();
    
                                    System.out.println("Reader Capabilities = "+ reader.ReaderCapabilities.getFirwareVersion());
    
    
                                    return true;
                                }
                            }
                        }
                    }
                } catch (InvalidUsageException e) {
                    e.printStackTrace();
                } catch (OperationFailureException e) {
                    e.printStackTrace();
                    Log.d("Demo", "OperationFailureException " + e.getVendorMessage());
                }
                return false;
            }
    
            protected void onPostExecute(Boolean aBoolean) {
                super.onPostExecute(aBoolean);
                if (aBoolean) {
                    Toast.makeText(getApplicationContext(), "Reader Connected", Toast.LENGTH_LONG).show();
                }
            }
        }
    
        private void ConfigureReader() {
            if (reader.isConnected()) {
    
                try {
                    if (eventHandler == null)
                        eventHandler = new EventHandler();
                    reader.Events.addEventsListener(eventHandler);
                    reader.Events.setHandheldEvent(true);
                    reader.Events.setTagReadEvent(true);
                    reader.Events.setReaderDisconnectEvent(true);
                    reader.Events.setInventoryStartEvent(true);
                    reader.Events.setInventoryStopEvent(true);
                    reader.Events.setAttachTagDataWithReadEvent(false);
                } catch (InvalidUsageException e) {
                    e.printStackTrace();
                } catch (OperationFailureException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        class EventHandler implements RfidEventsListener {
            public void eventReadNotify(RfidReadEvents e) {
                TagData[] tags = reader.Actions.getReadTags(100);
                int accessSuccess = 0;
                int accessFailure = 0;
    
                if (tags != null && currentState == WorkflowState.WRITING) {
                    for (TagData tag : tags) {
                        Log.d(TAG, tag.getTagID() + " :: " + tag.getOpCode() + " :: " + tag.getOpStatus());
    
                        if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "LOCK SUCCESS");
                            }
                        } else if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "WRITE SUCCESS");
                            }
                        } else if (tag.getOpCode() == ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ) {
                            if (tag.getOpStatus() == ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                                accessSuccess++;
                                Log.d(TAG, "READ SUCCESS");
                            }
                        }
    
                        if (tag.getOpStatus() != ACCESS_OPERATION_STATUS.ACCESS_SUCCESS) {
                            accessFailure++;
                            try {
                                reader.Actions.TagAccess.OperationSequence.deleteAll();
                            } catch (InvalidUsageException ex) {
                                ex.printStackTrace();
                            } catch (final OperationFailureException ex) {
                                ex.printStackTrace();
                            }
                        }
    
                        if (accessSuccess == 4) {
                            System.out.println(tag.getTagID() + " ALL Encoding Success ");
                            try {
                                reader.Actions.TagAccess.OperationSequence.deleteAll();
                            } catch (InvalidUsageException ex) {
                                ex.printStackTrace();
                            } catch (final OperationFailureException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
    
                    Log.d(TAG, "ACCESS SUCCESS: " + accessSuccess);
                    Log.d(TAG, "NOT ACCESS SUCCESS: " + accessFailure);
    
                    // Update UI based on operation results
                    final int finalAccessSuccess = accessSuccess;
                    runOnUiThread(() -> {
                        if (finalAccessSuccess == 4) {
                            Toast.makeText(MainActivity.this,
                                    "Tag written successfully!", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(MainActivity.this,
                                    "Tag operation failed. Only " + finalAccessSuccess + " of 4 operations succeeded",
                                    Toast.LENGTH_LONG).show();
                        }
                        currentState = WorkflowState.IDLE;
                        updateStatusDisplay();
                    });
                }
            }
    
            public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) {
                Log.d(TAG, "Status Notification: " + rfidStatusEvents.StatusEventData.getStatusEventType());
            }
        }
    
    
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // Unregister barcode receiver
            try {
                unregisterReceiver(barcodeReceiver);
            } catch (IllegalArgumentException e) {
                // Receiver not registered, ignore
            }
    
            // Disconnect RFID reader
            if (reader != null && reader.isConnected()) {
                try {
                    reader.disconnect();
                } catch (Exception e) {
                    Log.e(TAG, "Error disconnecting reader", e);
                }
            }
        }
    }

Complete EPCConverter.java Implementation



    package com.zebra.ssw.EncodeBarcodeToRFID;

    import android.content.Context;
    import android.util.Log;
    import org.json.JSONArray;
    import org.json.JSONObject;
    import java.io.IOException;
    import java.io.InputStream;
    import java.math.BigInteger;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.CompletableFuture;

    public class EPCConverter {

        //Note: This may only be valid for the SGTIN-96 scheme

        // The number of bits used to store the company prefix in the EPC depending on the partition value
        private static final int[] COMPANY_PREFIX_BITS = {40, 37, 34, 30, 27, 24, 20};

        // The number of digits in the company prefix depending on the partition value
        private static final int[] COMPANY_PREFIX_DIGITS = {12, 11, 10, 9, 8, 7, 6};

        // The number of bits used to store the item reference in the EPC depending on the partition value
        private static final int[] ITEM_REF_BITS = {4, 7, 10, 14, 17, 20, 24};

        // Header
        private static final String SGTIN96_HEADER = "00110000"; // SGTIN-96 Header
        // Filter Value
        private static final String FILTER = "001"; // POS Item Filter Value

        private static Map prefixMap;

        private static final Object usageLock = new Object();

        private EPCConverter() {}

        public static void initEpcConverter(Context context) {
            // Do this synchronously instead of async
            synchronized (usageLock) {
                String jsonData = loadJSONFromAsset(context);
                prefixMap = buildPrefixMap(jsonData);
                Log.d("EPCConverter", "Prefix map initialized with " +
                        (prefixMap != null ? prefixMap.size() : 0) + " entries");
            }
        }

        /**
        * This method encodes the given GTIN (Global Trade Item Number) and serial number into SGTIN-96 format.
        *
        * @param gtin - The Global Trade Item Number.
        * @param serialNumber - The serial number.
        * @return The encoded SGTIN-96 in hexadecimal format.
        */
        public static EPC encodeSGTIN96(String gtin, String serialNumber){
            synchronized (usageLock) {
                if (gtin.length() < 14) { // Pad gtin string to 14 characters
                    gtin = new String(new char[14 - gtin.length()]).replace('\0', '0').concat(gtin);
                }

                Log.v("EPCConverter", "GTIN: " + gtin);

                try {

                    // Get the length of the prefix in the GTIN
                    int gcpLength = getPrefixLength(prefixMap, gtin);
                    Log.d("EPCConverter", "GCP Len: " + gcpLength);

                    // Get the partition value which is dependent on the length of the prefix
                    int partitionValue = getPartition(gcpLength);
                    Log.d("EPCConverter", "Partition Val: " + partitionValue);

                    // Extract the company prefix from the GTIN
                    String companyPrefix = gtin.substring(1, gcpLength + 1);

                    // Extract the item reference from the GTIN
                    String itemReference = gtin.charAt(0) + gtin.substring(gcpLength + 1, 13);
                    Log.d("EPCConverter", companyPrefix + "    " + itemReference);

                    // Convert the partition value to binary format
                    String partitionBinary = String.format("%3s", Integer.toBinaryString(partitionValue)).replace(' ', '0');

                    // Convert the company prefix to binary format
                    String companyPrefixBinary = String.format("%" + getCompanyPrefixBits(partitionValue) + "s", Long.toBinaryString(Long.parseLong(companyPrefix))).replace(' ', '0');

                    // Convert the item reference to binary format
                    String itemReferenceBinary = String.format("%" + getItemReferenceBits(partitionValue) + "s", Long.toBinaryString(Long.parseLong(itemReference))).replace(' ', '0');

                    // Convert the serial number to binary format
                    String serialNumberBinary = String.format("%38s", Long.toBinaryString(Long.parseLong(serialNumber))).replace(' ', '0');

                    // Combine all the binary strings to form the complete SGTIN-96 binary string
                    String sgtin96Binary = SGTIN96_HEADER + FILTER + partitionBinary + companyPrefixBinary + itemReferenceBinary + serialNumberBinary;

                    // Convert the binary string to hexadecimal format
                    StringBuilder hex = new StringBuilder();
                    for (int i = 0; i < sgtin96Binary.length(); i += 4) {
                        String chunk = sgtin96Binary.substring(i, i + 4);
                        hex.append(Integer.toString(Byte.parseByte(chunk, 2), 16));
                    }

                    // Return the hexadecimal string in uppercase
                    EPC epc = new EPC(hex.toString().toUpperCase());
                    return epc;
                } catch (Exception e) {
                    Log.d("ENCODE", e.getMessage());
                    return EPC.DEFAULT;
                }
            }
        }

        /**
        * This method returns the partition value which is dependent on the prefix length.
        *
        * @param prefixLength - The length of the prefix in the GTIN.
        * @return The partition value.
        */
        public static int getPartition(int prefixLength){
            switch (prefixLength) {
                case 12: return 0;
                case 11: return 1;
                case 10: return 2;
                case 9: return 3;
                case 8: return 4;
                case 7: return 5;
                case 6: return 6;
                default: throw new IllegalArgumentException("Invalid GS1 Company Prefix Length");
            }
        }

        /**
        * This method returns the number of bits that should be used for the company prefix based on the partition value.
        *
        * @param partitionValue - The partition value.
        * @return The number of bits for the company prefix.
        */
        private static int getCompanyPrefixBits(int partitionValue) {
            switch (partitionValue) {
                case 0: return 40;
                case 1: return 37;
                case 2: return 34;
                case 3: return 30;
                case 4: return 27;
                case 5: return 24;
                case 6: return 20;
                default: throw new IllegalArgumentException("Invalid Partition Value");
            }
        }

        /**
        * This method returns the number of bits that should be used for the item reference based on the partition value.
        *
        * @param partitionValue - The partition value.
        * @return The number of bits for the item reference.
        */
        private static int getItemReferenceBits(int partitionValue) {
            switch (partitionValue) {
                case 0: return 4;
                case 1: return 7;
                case 2: return 10;
                case 3: return 14;
                case 4: return 17;
                case 5: return 20;
                case 6: return 24;
                default: throw new IllegalArgumentException("Invalid Partition Value");
            }
        }

        /**
        * This method gets the prefix length by checking the given GTIN against a map of known prefixes.
        *
        * @param prefixMap - The map of known prefixes.
        * @param gtin - The Global Trade Item Number.
        * @return The length of the prefix.
        */
        private static int getPrefixLength(Map prefixMap, String gtin) {
            for (int i = 4; i <= 12; i++){
                String prefix = gtin.substring(1,i);
                Integer gcpLength = prefixMap.get(prefix);
                if(gcpLength != null){
                    return gcpLength;
                }
            }
            throw new IllegalArgumentException("prefix not found");
        }

        //GCPMap Builder Functions:

        /**
        * This method loads a JSON file from the app's assets folder.
        *
        * @param context - The context of the calling activity.
        * @return The JSON data in string format.
        */
        private static String loadJSONFromAsset(Context context){
            String json;
            try {
                InputStream is = context.getAssets().open("gcpprefixformatlist.json");
                int size = is.available();
                byte[] buffer = new byte[size];
                is.read(buffer);
                is.close();
                json = new String(buffer, "UTF-8");
            } catch(IOException e){
                e.printStackTrace();
                return null;
            }
            return json;
        }

        /**
        * This method builds a map from the loaded JSON data where the keys are prefixes and the values are prefix lengths.
        *
        * @param jsonData - The JSON data in string format.
        * @return The map of prefixes and their lengths.
        */
        private static Map buildPrefixMap(String jsonData){
            Map prefixMap = new HashMap<>();
            try{
                JSONObject obj = new JSONObject(jsonData);
                JSONArray entries = obj.getJSONObject("GCPPrefixFormatList").getJSONArray("entry");
                for (int i = 0; i < entries.length(); i++){
                    JSONObject entry = entries.getJSONObject(i);
                    prefixMap.put(entry.getString("prefix"), entry.getInt("gcpLength"));
                }

            }catch (Exception e){
                e.printStackTrace();
            }
            return prefixMap;
        }
    }

Complete DataWedge.java Implementation



    package com.zebra.ssw.EncodeBarcodeToRFID;

    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import java.util.ArrayList;
    import com.zebra.ssw.R;

    public class DataWedge {
        private static final String APPLICATION_ID          =   "com.zebra.ssw";
        public static final String INTENT_NAME              =   APPLICATION_ID + ".BARCODE";
        public static final String DATAWEDGE_EXTRA          =   "com.symbol.datawedge.data_string";
        private static final String ACTION_DATAWEDGE        =   "com.symbol.datawedge.api.ACTION";
        private static final String EXTRA_SET_CONFIG        =   "com.symbol.datawedge.api.SET_CONFIG";

        /**
        * Setup the datawedge profile for application
        * @param context Application Context
        */
        public static void setDWProfile(Context context) {
            //Main
            Bundle bMain = new Bundle();
            bMain.putString("PROFILE_NAME", context.getString(R.string.app_name));
            bMain.putString("PROFILE_ENABLED","true");
            bMain.putString("CONFIG_MODE","CREATE_IF_NOT_EXIST");

            // Create APP_LIST bundle to associate app with profile
            Bundle appConfig = new Bundle();
            appConfig.putString("PACKAGE_NAME", context.getPackageName());
            appConfig.putStringArray("ACTIVITY_LIST", new String[]{"*"});
            bMain.putParcelableArray("APP_LIST", new Bundle[]{appConfig});
            Intent dwIntent = new Intent();
            dwIntent.setAction(ACTION_DATAWEDGE);
            dwIntent.putExtra(EXTRA_SET_CONFIG, bMain);
            context.sendBroadcast(dwIntent);

            //PLUGIN_CONFIG
            Bundle bConfig = new Bundle();
            bConfig.putString("PLUGIN_NAME","INTENT");
            bConfig.putString("RESET_CONFIG","true");

            //PARAM_LIST
            Bundle bParams = new Bundle();
            bParams.putString("intent_output_enabled","true");
            bParams.putString("intent_action",INTENT_NAME);
            bParams.putString("intent_category", Intent.CATEGORY_DEFAULT);
            bParams.putInt("intent_delivery",2);                                                        //Use "0" for Start Activity, "1" for Start Service, "2" for Broadcast
            bConfig.putBundle("PARAM_LIST", bParams);
            bMain.putBundle("PLUGIN_CONFIG", bConfig);

            // APP_LIST
            Bundle bundleApp1 = new Bundle();
            bundleApp1.putStringArray("ACTIVITY_LIST", new String[]{ "com.zebra.findit.*" });
            bMain.putParcelableArray("APP_LIST", new Bundle[] { bundleApp1 });

            //Send Intent to add Config
            Intent i = new Intent();
            i.setAction("com.symbol.datawedge.api.ACTION");
            i.putExtra("com.symbol.datawedge.api.SET_CONFIG", bMain);
            context.sendBroadcast(i);

            //****************** Turn Off Keystroke and RFID *****************************
            bMain = new Bundle();
            bMain.putString("PROFILE_NAME",context.getString(R.string.app_name));
            bMain.putString("PROFILE_ENABLED","true");
            bMain.putString("CONFIG_MODE","UPDATE");

            ArrayList plugins = new ArrayList<>();

            //KEYSTROKE PLUGIN_CONFIG
            bConfig = new Bundle();
            bConfig.putString("PLUGIN_NAME","KEYSTROKE");
            bConfig.putString("RESET_CONFIG","true");

            bParams = new Bundle();
            bParams.putString("keystroke_output_enabled","false");

            bConfig.putBundle("PARAM_LIST", bParams);
            plugins.add(bConfig);

            //RFID PLUGIN_CONFIG
            bConfig = new Bundle();
            bConfig.putString("PLUGIN_NAME","RFID");
            bConfig.putString("RESET_CONFIG","true");

            bParams = new Bundle();
            bParams.putString("rfid_input_enabled", "false");

            bConfig.putBundle("PARAM_LIST", bParams);
            plugins.add(bConfig);

            bMain.putParcelableArrayList("PLUGIN_CONFIG", plugins);
            i.setAction("com.symbol.datawedge.api.ACTION");
            i.putExtra("com.symbol.datawedge.api.SET_CONFIG", bMain);
            context.sendBroadcast(i);

            // Register this
            registerProfile(context);
        }

        public static void registerProfile(Context context) {
            Bundle bMain = new Bundle();
            bMain.putString("com.symbol.datawedge.api.APPLICATION_NAME", APPLICATION_ID);
            bMain.putString("com.symbol.datawedge.api.NOTIFICATION_TYPE", "PROFILE_SWITCH");

            Bundle bParams = new Bundle();
            bParams.putString("PROFILE_IMPORTED", "FULL_DB_IMPORTED");
            bParams.putString("PROFILE_NAME", context.getString(R.string.app_name));
            bMain.putBundle("com.symbol.datawedge.api.NOTIFICATION", bParams);

            Intent i = new Intent();
            i.setAction("com.symbol.datawedge.api.ACTION");
            i.putExtra("com.symbol.datawedge.api.REGISTER_FOR_NOTIFICATION", bMain);
            context.sendBroadcast(i);
        }
    }

Complete BarcodeToRfidApi.java Implementation



    package com.zebra.ssw;

    import android.content.Context;
    import android.content.Intent;
    import com.zebra.ssw.EncodeBarcodeToRFID.DataWedge;
    import com.zebra.ssw.EncodeBarcodeToRFID.EPC;
    import com.zebra.ssw.EncodeBarcodeToRFID.EPCConverter;

    public class BarcodeToRfidApi {
        public static void initialize(Context context) {
            EPCConverter.initEpcConverter(context);
            DataWedge.setDWProfile(context);
        }

        public static EPC encodeBarcodeToRfid(String scannedUpc, String serialNumber) {
            EPC epc = EPCConverter.encodeSGTIN96(scannedUpc, serialNumber);
            return epc;
        }
    }