IDTech Android SDK Guide  1.00.173
API reference for VP3300 AJ
Sample Project Tutorial Android Studio

Using Android Studio, we will create a sample project that will interface with the VP3300 and will perform the following activities:

  • Auto-Connect and display connection status
  • Get Device Firmware
  • Start/Stop Transaction Request for CTLS/MSR (tap/swipe)
  • Start/Cancel EMV Transaction
  • Show LCD Display for EMV transaction
  • Automatically select first AID or first Language if prompted

Listeners:

  • Listener to receive card swipes
  • Listener to detect device connected
  • Listener to detect device disconnected
  • Listener to receive EMV/CTLS tag data
  • Listener to receive LCD messages

Step 1: Create New Project

Create a new Android Application project in Android Studio as an Empty Activity

AS_NewProject1.JPG
AS_NewProject2.JPG
AS_NewProject3.JPG
AS_NewProject4.JPG
AS_NewProject5.JPG

Step 2: Import IDTechSDK for VP3300

Import the necessary libraries

Step 3: Design Interface

Design the User Interface by editing the main layout XML file
Open your layout and add items to so it contains the following buttons/fields (sample code provide at end of section):

  • Add a TextView to the top that will signify connection/disconnection status.
  • Add two TextViews to communicate data from the VP3300 and for EMV LCD display information. Remove the Editable behavior if you don't want the keyboard to pop up if you accidentally select it.
  • Add buttons to execute the following functions:
    • Get Firmware
    • Start MSR/ CTLS
    • Start ICC EMV
    • Complete ICC EMV
    • Cancel Transaction
AS_DesignInterface.JPG

Step 4: Configure Activity File

In the activity file, perform the following:

Layout Source Code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#aaaaaa"
android:orientation="vertical" >
<TextView
android:id="@+id/status_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000000"
android:gravity="center_vertical|center_horizontal"
android:text="VP3300 DISCONNECTED"
android:textColor="#FFFFFF" />
<LinearLayout
android:id="@+id/linearLayoutBottom2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/btn_StartEMV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.53"
android:gravity="center_vertical|center_horizontal"
android:text="Start EMV" />
<Button
android:id="@+id/btn_CancelEMV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.53"
android:text="Cancel EMV" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayoutEditText"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#dddddd"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:background="#ffffff" >
<TextView
android:id="@+id/lcdLog"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text=""
android:textColor="#000000"
android:textSize="12sp"
android:typeface="monospace" >
</TextView>
</ScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayoutEditText2"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#dddddd"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical" >
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:background="#ffffff" >
<TextView
android:id="@+id/textLog"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text=""
android:textColor="#000000"
android:textSize="12sp"
android:typeface="monospace" >
</TextView>
</ScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayoutBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/btn_getFirmware"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.53"
android:gravity="center_vertical|center_horizontal"
android:text="Get Firmware Version" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayoutBottom4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/btn_startSwipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.53"
android:text="Start Swipe/CTLS" />
<Button
android:id="@+id/btn_cancelSwipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.53"
android:text="Cancel Swipe/CTLS" />
</LinearLayout>
</LinearLayout>

Step 5: Configure Method File

In the activity file, perform the following:

// declaring the instance of the VP3300Reader;
private IDT_VP3300 myVP3300Reader = null;
private TextView connectStatusTextView;
private TextView textLog;
private TextView lcdLog;
private Button btnGetFirmware;
private Button btnStartSwipe;
private Button btnCancelSwipe;
private Button btnStartEMV;
private Button btnCancelEMV;
private Handler handler = new Handler();
private boolean isReaderConnected = false;
private String info = "";
private String detail = "";
private BluetoothAdapter mBtAdapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
btnStartEMV = (Button)findViewById(R.id.btn_StartEMV);
btnCancelEMV = (Button)findViewById(R.id.btn_CancelEMV);
btnGetFirmware = (Button)findViewById(R.id.btn_getFirmware);
btnStartSwipe = (Button)findViewById(R.id.btn_startSwipe);
btnCancelSwipe = (Button)findViewById(R.id.btn_cancelSwipe);
textLog = (TextView)findViewById(R.id.textLog);
lcdLog = (TextView)findViewById(R.id.lcdLog);
connectStatusTextView = (TextView)findViewById(R.id.status_text);
if(myVP3300Reader!=null){
myVP3300Reader.unregisterListen();
myVP3300Reader.release();
myVP3300Reader = null;
}
myVP3300Reader = new IDT_VP3300(this,this);
myVP3300Reader.device_setDeviceType(DEVICE_TYPE.DEVICE_VP3300_AJ);
myVP3300Reader.registerListen();
}
private Runnable doUpdateLabel = new Runnable()
{
public void run()
{
if(!isReaderConnected){
connectStatusTextView.setText("VP3300 DISCONNECTED");
}
else{
connectStatusTextView.setText("VP3300 CONNECTED");
}
}
};
@Override
public void deviceConnected() {
isReaderConnected = true;
handler.post(doUpdateLabel);
}
@Override
public void deviceDisconnected() {
isReaderConnected = false;
handler.post(doUpdateLabel);
}

-Implement protocol delegate com.idtechproducts.device.OnReceiverListener.swipeMSRData() to receive unsolicited card swipe data.

private Runnable doUpdateStatus = new Runnable()
{
public void run()
{
lcdLog.setText(info);
textLog.setText(detail);
}
};
@Override
public void swipeMSRData(IDTMSRData card) {
if (card.cardData[0] != (byte)0x01 && card.track1Length == 0 && card.track2Length == 0 && card.track3Length == 0)
info = "Swipe/Tap data didn't read correctly";
else
info = "Swipe/Tap Read Successfully";
detail = Common.parse_MSRData(myVP3300Reader.device_getDeviceType(), card);
handler.post(doUpdateStatus);
}
  • Implement protocol delegate com.idtechproducts.device.OnReceiverListener.emvTransactionData() to report EMV transaction results
    public void emvTransactionData(IDTEMVData emvData) {
    detail += Common.emvErrorCodes(emvData.result);
    detail += "\r\n";
    if (emvData.result == IDTEMVData.START_TRANS_SUCCESS)
    detail += "Start transaction response:\r\n";
    else if (emvData.result == IDTEMVData.GO_ONLINE)
    detail += "\r\nAuthentication response:\r\n";
    else
    detail += "\r\nComplete Transaction response:\r\n";
    if (!emvData.unencryptedTags.isEmpty())
    {
    detail += "Unencrypted Tags:\r\n";
    Set<String> keys = emvData.unencryptedTags.keySet();
    for(String key: keys){
    detail += key + ": ";
    byte[] data = emvData.unencryptedTags.get(key);
    detail += Common.getHexStringFromBytes(data) + "\r\n";
    }
    }
    if (!emvData.maskedTags.isEmpty())
    {
    detail += "Masked Tags:\r\n";
    Set<String> keys = emvData.maskedTags.keySet();
    for(String key: keys){
    detail += key + ": ";
    byte[] data = emvData.maskedTags.get(key);
    detail += Common.getHexStringFromBytes(data) + "\r\n";
    }
    }
    if (!emvData.encryptedTags.isEmpty())
    {
    detail += "Encrypted Tags:\r\n";
    Set<String> keys = emvData.encryptedTags.keySet();
    for(String key: keys){
    detail += key + ": ";
    byte[] data = emvData.encryptedTags.get(key);
    detail += Common.getHexStringFromBytes(data) + "\r\n";
    }
    }
    handler.post(doUpdateStatus);
    if (emvData.result == IDTEMVData.GO_ONLINE){
    //Auto Complete
    byte[] response = new byte[]{0x30,0x30};
    myVP3300Reader.emv_completeTransaction(false, response, null, null,null);
    }
    else if (emvData.result == IDTEMVData.START_TRANS_SUCCESS){
    //Auto Authenticate
    myVP3300Reader.emv_authenticateTransaction(null);
    }
    }
  • Implement protocol delegate com.idtechproducts.device.OnReceiverListener.emvTransactionData() to receive LCD messages, and automatically select 1st menu item/language when presented with choices. Normal operation would require a choice be made by card holder.
    public void lcdDisplay(int mode, String[] lines, int timeout) {
    if (mode == 0x01) //Menu Display
    {
    //automatically select 1st application
    myVP3300Reader.emv_lcdControlResponse((byte)mode, (byte)0x01);
    }
    else if (mode == 0x08) //Language Menu Display
    {
    //automatically select first language
    myVP3300Reader.emv_lcdControlResponse((byte)mode, (byte)0x01);
    }
    else{
    ResDataStruct toData = new ResDataStruct();
    info = lines[0];
    handler.post(doUpdateStatus);
    }
    }
  • Implement the button press methods
    btnGetFirmware.setOnClickListener(new Button.OnClickListener(){
    public void onClick(View v) {
    info = "Getting Firmware\n";
    detail = "";
    handler.post(doUpdateStatus);
    StringBuilder sb = new StringBuilder();
    int ret = myVP3300Reader.device_getFirmwareVersion(sb);
    if (ret == ErrorCode.SUCCESS) {
    info += "Firmware Version: " + sb.toString();
    detail = "";
    handler.post(doUpdateStatus);
    }
    else {
    info += "GetFirmwareVersion: Failed\n";
    info += "Status: "+ myVP3300Reader.device_getResponseCodeString(ret)+"";
    detail = "";
    handler.post(doUpdateStatus);
    }
    }
    });
    btnStartEMV.setOnClickListener(new Button.OnClickListener(){
    public void onClick(View v) {;
    detail = "";
    info = "Starting EMV Transaction\n";
    handler.post(doUpdateStatus);
    IDT_VP3300.emv_allowFallback(true);
    myVP3300Reader.emv_startTransaction(1.00, 0.00, 0, 30, null, false);
    }
    });
    btnCancelEMV.setOnClickListener(new Button.OnClickListener(){
    public void onClick(View v) {
    detail = "";
    info = "Canceling EMV Transaction\n";
    handler.post(doUpdateStatus);
    ResDataStruct resData = new ResDataStruct();
    myVP3300Reader.emv_cancelEMVTransaction(resData);
    }
    });
    btnStartSwipe.setOnClickListener(new Button.OnClickListener(){
    public void onClick(View v) {
    detail = "";
    info = "Starting Swipe/Tap Transaction\n";
    handler.post(doUpdateStatus);
    myVP3300Reader.msr_startMSRSwipe();
    }
    });
    btnCancelSwipe.setOnClickListener(new Button.OnClickListener(){
    public void onClick(View v) {
    detail = "";
    info = "Cancelling Swipe/Tap Transaction\n";
    handler.post(doUpdateStatus);
    myVP3300Reader.msr_cancelMSRSwipe();
    }
    });

Complete code listing

package com.example.vp3300_aj_sdk_tutorial;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Set;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnReceiverListener{
// declaring the instance of the VP3300Reader;
private IDT_VP3300 myVP3300Reader = null;
private TextView connectStatusTextView;
private TextView textLog;
private TextView lcdLog;
private Button btnGetFirmware;
private Button btnStartSwipe;
private Button btnCancelSwipe;
private Button btnStartEMV;
private Button btnCancelEMV;
private Handler handler = new Handler();
private boolean isReaderConnected = false;
private String info = "";
private String detail = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
btnStartEMV = (Button)findViewById(R.id.btn_StartEMV);
btnCancelEMV = (Button)findViewById(R.id.btn_CancelEMV);
btnGetFirmware = (Button)findViewById(R.id.btn_getFirmware);
btnStartSwipe = (Button)findViewById(R.id.btn_startSwipe);
btnCancelSwipe = (Button)findViewById(R.id.btn_cancelSwipe);
textLog = (TextView)findViewById(R.id.textLog);
lcdLog = (TextView)findViewById(R.id.lcdLog);
connectStatusTextView = (TextView)findViewById(R.id.status_text);
if(myVP3300Reader!=null){
myVP3300Reader.unregisterListen();
myVP3300Reader.release();
myVP3300Reader = null;
}
myVP3300Reader = new IDT_VP3300(this,this);
myVP3300Reader.device_setDeviceType(DEVICE_TYPE.DEVICE_VP3300_AJ);
myVP3300Reader.registerListen();
loadXMLfile();
btnGetFirmware.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
info = "Getting Firmware\n";
detail = "";
handler.post(doUpdateStatus);
StringBuilder sb = new StringBuilder();
int ret = myVP3300Reader.device_getFirmwareVersion(sb);
if (ret == ErrorCode.SUCCESS) {
info += "Firmware Version: " + sb.toString();
detail = "";
handler.post(doUpdateStatus);
}
else {
info += "GetFirmwareVersion: Failed\n";
info += "Status: "+ myVP3300Reader.device_getResponseCodeString(ret)+"";
detail = "";
handler.post(doUpdateStatus);
}
}
});
btnStartEMV.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {;
detail = "";
info = "Starting EMV Transaction\n";
handler.post(doUpdateStatus);
IDT_VP3300.emv_allowFallback(true);
myVP3300Reader.emv_startTransaction(1.00, 0.00, 0, 30, null, false);
}
});
btnCancelEMV.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
detail = "";
info = "Canceling EMV Transaction\n";
handler.post(doUpdateStatus);
ResDataStruct resData = new ResDataStruct();
myVP3300Reader.emv_cancelEMVTransaction(resData);
}
});
btnStartSwipe.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
detail = "";
info = "Starting Swipe/Tap Transaction\n";
handler.post(doUpdateStatus);
myVP3300Reader.msr_startMSRSwipe();
}
});
btnCancelSwipe.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
detail = "";
info = "Cancelling Swipe/Tap Transaction\n";
handler.post(doUpdateStatus);
myVP3300Reader.msr_cancelMSRSwipe();
}
});
}
@Override
public void ICCNotifyInfo(byte[] arg0, String arg1) {
// TODO Auto-generated method stub
}
@Override
public void LoadXMLConfigFailureInfo(int arg0, String arg1) {
// TODO Auto-generated method stub
}
@Override
public void autoConfigCompleted(StructConfigParameters arg0) {
// TODO Auto-generated method stub
}
@Override
public void autoConfigProgress(int arg0) {
// TODO Auto-generated method stub
}
private Runnable doUpdateLabel = new Runnable()
{
public void run()
{
if(!isReaderConnected){
connectStatusTextView.setText("VP3300 DISCONNECTED");
}
else{
connectStatusTextView.setText("VP3300 CONNECTED");
}
}
};
@Override
public void deviceConnected() {
isReaderConnected = true;
handler.post(doUpdateLabel);
}
@Override
public void deviceDisconnected() {
isReaderConnected = false;
handler.post(doUpdateLabel);
}
private void printTags(IDTEMVData emvData)
{
}
@Override
public void emvTransactionData(IDTEMVData emvData) {
detail += Common.emvErrorCodes(emvData.result);
detail += "\r\n";
if (emvData.result == IDTEMVData.START_TRANS_SUCCESS)
detail += "Start transaction response:\r\n";
else if (emvData.result == IDTEMVData.GO_ONLINE)
detail += "\r\nAuthentication response:\r\n";
else
detail += "\r\nComplete Transaction response:\r\n";
if (!emvData.unencryptedTags.isEmpty())
{
detail += "Unencrypted Tags:\r\n";
Set<String> keys = emvData.unencryptedTags.keySet();
for(String key: keys){
detail += key + ": ";
byte[] data = emvData.unencryptedTags.get(key);
detail += Common.getHexStringFromBytes(data) + "\r\n";
}
}
if (!emvData.maskedTags.isEmpty())
{
detail += "Masked Tags:\r\n";
Set<String> keys = emvData.maskedTags.keySet();
for(String key: keys){
detail += key + ": ";
byte[] data = emvData.maskedTags.get(key);
detail += Common.getHexStringFromBytes(data) + "\r\n";
}
}
if (!emvData.encryptedTags.isEmpty())
{
detail += "Encrypted Tags:\r\n";
Set<String> keys = emvData.encryptedTags.keySet();
for(String key: keys){
detail += key + ": ";
byte[] data = emvData.encryptedTags.get(key);
detail += Common.getHexStringFromBytes(data) + "\r\n";
}
}
handler.post(doUpdateStatus);
if (emvData.result == IDTEMVData.GO_ONLINE){
//Auto Complete
byte[] response = new byte[]{0x30,0x30};
myVP3300Reader.emv_completeTransaction(false, response, null, null,null);
}
else if (emvData.result == IDTEMVData.START_TRANS_SUCCESS){
//Auto Authenticate
myVP3300Reader.emv_authenticateTransaction(null);
}
}
public void lcdDisplay(int mode, String[] lines, int timeout) {
if (mode == 0x01) //Menu Display
{
//automatically select 1st application
myVP3300Reader.emv_lcdControlResponse((byte)mode, (byte)0x01);
}
else if (mode == 0x08) //Language Menu Display
{
//automatically select first language
myVP3300Reader.emv_lcdControlResponse((byte)mode, (byte)0x01);
}
else{
ResDataStruct toData = new ResDataStruct();
info = lines[0];
handler.post(doUpdateStatus);
}
}
@Override
public void msgAudioVolumeAjustFailed() {
// TODO Auto-generated method stub
}
@Override
public void msgRKICompleted(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void msgToConnectDevice() {
// TODO Auto-generated method stub
}
private Runnable doUpdateStatus = new Runnable()
{
public void run()
{
lcdLog.setText(info);
textLog.setText(detail);
}
};
@Override
public void swipeMSRData(IDTMSRData card) {
if (card.cardData[0] != (byte)0x01 && card.track1Length == 0 && card.track2Length == 0 && card.track3Length == 0)
info = "Swipe/Tap data didn't read correctly";
else
info = "Swipe/Tap Read Successfully";
detail = Common.parse_MSRData(myVP3300Reader.device_getDeviceType(), card);
handler.post(doUpdateStatus);
}
@Override
public void timeout(int arg0) {
// TODO Auto-generated method stub
}
private String getXMLFileFromRaw(String fileName ,int res){
//the target filename in the application path
String fileNameWithPath = null;
fileNameWithPath = fileName;
String newFilename = fileName;
try {
InputStream in = getResources().openRawResource(res);
int length = in.available();
byte [] buffer = new byte[length];
in.read(buffer);
in.close();
deleteFile(fileNameWithPath);
FileOutputStream fout = openFileOutput(fileNameWithPath, MODE_PRIVATE);
fout.write(buffer);
fout.close();
// to refer to the application path
File fileDir = this.getFilesDir();
fileNameWithPath = fileDir.getParent() + java.io.File.separator + fileDir.getName();
fileNameWithPath += java.io.File.separator+newFilename;
} catch(Exception e){
e.printStackTrace();
fileNameWithPath = null;
}
return fileNameWithPath;
}
private String getConfigurationFileFromRaw( ){
return getXMLFileFromRaw("idt_unimagcfg_default.xml",R.raw.idt_unimagcfg_default);
}
private boolean isFileExist(String path) {
if(path==null)
return false;
File file = new File(path);
if (!file.exists()) {
return false ;
}
return true;
}
private void loadXMLfile(){
//load the XML configuration file
String fileNameWithPath = getConfigurationFileFromRaw();
if(!isFileExist(fileNameWithPath)) {
fileNameWithPath = null;
}
// Network operation is prohibited in the UI Thread if target API is 11 or above.
// If target API is 11 or above, please use AsyncTask to avoid errors.
myVP3300Reader.config_setXMLFileNameWithPath(fileNameWithPath);
Log.d("Demo Info >>>>>","loadingConfigurationXMLFile begin.");
myVP3300Reader.config_loadingConfigurationXMLFile(true);
}
}