Bulk Encoding

RFID SDK For Android 2.0.4.192

Overview

This section introduces the purpose and scope of the Bulk Encoding sample application. It outlines how the app demonstrates the use of Zebra's RFID3 API to perform bulk RFID tag encoding for retail inventory management.

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

Create The Project

Start by creating a new project in Android Studio. Call it Bulk Encoding 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) {
                    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 == 6){
                            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);
                }
            }
        
    
            // 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 on screen

  6. 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 bulk encoding.

  1. 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;
            }
    
            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;
        }
    
  2. Perform a sequence of operations to encode RFID tags

    
        public void bulkEncoding (String EpcID, String currentPassword) { 
            try 
            { 
                TagAccess tagAccess = new TagAccess(); 
                TagAccess.Sequence opSequence = tagAccess.new Sequence(tagAccess); 
    
                //Read EPC memory 
                TagAccess.Sequence.Operation op1 = opSequence.new Operation(); 
                op1.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ); 
                op1.ReadAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC); 
                op1.ReadAccessParams.setOffset(2); 
                op1.ReadAccessParams.setCount(6); 
                reader.Actions.TagAccess.OperationSequence.add(op1); 
    
                // Unlocking the EPC memory 
                TagAccess.Sequence.Operation op2 = opSequence.new Operation(); 
                op2.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK); 
                op2.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY, LOCK_PRIVILEGE.LOCK_PRIVILEGE_UNLOCK); 
                op2.LockAccessParams.setAccessPassword(Long.decode("0X" + currentPassword)); 
                reader.Actions.TagAccess.OperationSequence.add(op2); 
    
                // Write EPC ID 
                TagAccess.Sequence.Operation op3 = opSequence.new Operation(); 
                op3.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); 
                op3.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_EPC); 
                op3.WriteAccessParams.setOffset(2); 
                op3.WriteAccessParams.setWriteData(EpcID); 
                op3.WriteAccessParams.setWriteDataLength(EpcID.length()/4); 
                reader.Actions.TagAccess.OperationSequence.add(op3); 
    
                // Write to User memory bank 
                String userMemoryData = "7777"; 
                TagAccess.Sequence.Operation op4 = opSequence.new Operation(); 
                op4.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); 
                op4.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_USER); 
                op4.WriteAccessParams.setOffset(0); 
                op4.WriteAccessParams.setWriteData(userMemoryData); 
                op4.WriteAccessParams.setWriteDataLength(userMemoryData.length()/4); 
                reader.Actions.TagAccess.OperationSequence.add(op4); 
    
                // Write new access password to reserved memory bank 
                String newPassword = "AAAABBBB"; 
                TagAccess.Sequence.Operation op5 = opSequence.new Operation(); 
                op5.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE); 
                op5.WriteAccessParams.setMemoryBank(MEMORY_BANK.MEMORY_BANK_RESERVED); 
                op5.WriteAccessParams.setOffset(2); 
                op5.WriteAccessParams.setWriteData(newPassword); 
                op5.WriteAccessParams.setWriteDataLength(newPassword.length()/4); 
                reader.Actions.TagAccess.OperationSequence.add(op5); 
    
                //Lock the tag with the new access password 
                TagAccess.Sequence.Operation op6 = opSequence.new Operation(); 
                op6.setAccessOperationCode(ACCESS_OPERATION_CODE.ACCESS_OPERATION_LOCK); 
                op6.LockAccessParams.setLockPrivilege(LOCK_DATA_FIELD.LOCK_EPC_MEMORY, LOCK_PRIVILEGE.LOCK_PRIVILEGE_READ_WRITE); 
                op6.LockAccessParams.setAccessPassword(Long.decode("0X" + newPassword)); 
                reader.Actions.TagAccess.OperationSequence.add(op6); 
    
                reader.Actions.TagAccess.OperationSequence.performSequence(setAccessFilter(EpcID), null, null); 
            } 
            catch (InvalidUsageException e) { 
                e.printStackTrace(); 
            } catch (OperationFailureException e) { 
                e.printStackTrace(); 
            } 
        }
    
    

Complete MainActivity.java Implementation

Below is the complete implementation of MainActivity.java which combines all the code snippets discussed earlier. This class handles RFID reader initialization, connection, configuration, event handling, and performs the bulk encoding operations. Key features include:

  • Reader connection and configuration in an AsyncTask
  • Implementation of the EventHandler for processing RFID events
  • Setting up triggers for inventory operations
  • Proper resource cleanup in onDestroy()
  • The complete bulkEncoding() method to perform sequential tag operations

package com.zebra.demorfid.bulkEncoding;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.zebra.rfid.api3.*;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private static Readers readers;
    private static ArrayList availableRFIDReaderList;
    private static ReaderDevice readerDevice;
    private static RFIDReader reader;
    private static String TAG = "DEMO";
    TextView textView;
    private EventHandler eventHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        //
        // UI
        textView = (TextView) findViewById(R.id.TagText);
        // SDK
        if (readers == null) {
            readers = new Readers(this, ENUM_TRANSPORT.SERVICE_SERIAL);
        }
        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();
                                    // apply filter to specify which tags should be operated on. 
                                    setAccessFilter("E28011112222400F97D3DA44");
                                    // perform bulk encoding operation
                                    bulkEncoding("E28011112222400F97D3DA44", "11112222");
                                    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();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    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(false);
                // 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();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            if (reader != null) {
                reader.Events.removeEventsListener(eventHandler);
                reader.disconnect();
                Toast.makeText(getApplicationContext(), "Disconnecting reader", Toast.LENGTH_LONG).show();
                reader = null;
                readers.Dispose();
                readers = null;
            }
        } catch (InvalidUsageException e) {
            e.printStackTrace();
        } catch (OperationFailureException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Read/Status Notify handler
    // Implement the RfidEventsLister 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) {
                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 == 6){
                        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);
            }
        }
    

        // Status Event Notification
        public void eventStatusNotify(RfidStatusEvents rfidStatusEvents) {
            Log.d(TAG, "Status Notification: " + rfidStatusEvents.StatusEventData.getStatusEventType());
        }
    }
}