问题
I've been working on Android (v2.3) for a couple of weeks now, and I've stumbled upon some problems with the Unimag Card Swiper from IDTECH.
The unit comes with a scarce documentation and the demo app from the SDK implements the firmware update and a few classes for dialogs and such which really offuscate how to achieve basic functionality (added to the few and not so good comments in the code).
I have implemented the interface in a basic activity and tried to detect when the unit is connected or disconnected but it seems the listener catches both events (connection/disconnection) as "disconnect", let alone trying to read a card.
Has anyone worked with this unit on Android and has some clear examples?
By the way, here is my class:
package com.card.swipe;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import IDTech.MSR.uniMag.uniMagReader;
import IDTech.MSR.uniMag.uniMagReaderMsg;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class CardSwipeTestActivity extends Activity implements uniMagReaderMsg {
private uniMagReader myUniMagReader = null;
private TextView etCardData;
private String _strMSRData = null;
private byte[]_MSRData = null;
private String _strStatus = null;
private int _nGetChallengeResult = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// InitializeUI();
InitializeReader();
String strManufacture = myUniMagReader.getInfoManufacture();
String strModel = myUniMagReader.getInfoModel();
String strSDKVerInfo = myUniMagReader.getSDKVersionInfo();
String strOSVerInfo = android.os.Build.VERSION.RELEASE;
etCardData = (TextView)findViewById(R.id.text_view);
etCardData.setText("Phone: "+strManufacture+"\n"+"Model: "+strModel+"\n"+"SDK Ver: "+strSDKVerInfo+"\nOS Version: "+strOSVerInfo);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
if(myUniMagReader!=null)
{
//you should stop swipe card and unregister when the application go to background
myUniMagReader.stopSwipeCard();
// myUniMagReader.unregisterListen();
// myUniMagReader.release();
}
super.onPause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
// you should register to listen the headset event when the application resumed.
// if(myUniMagReader!=null)
// {
//// myUniMagReader.registerListen();
// if(_bCheckedSaveLogItem==true)
// myUniMagReader.setSaveLogEnable(true);
// else
// myUniMagReader.setSaveLogEnable(false);
// }
// if(itemStartSC!=null)
// itemStartSC.setEnabled(true);
// waitingCommandResult=false;
super.onResume();
}
@Override
protected void onDestroy() {
myUniMagReader.release();
super.onDestroy();
android.os.Process.killProcess(android.os.Process.myPid());
}
//********************************************************************************//
@Override
public boolean getUserGrant(int arg0, String arg1) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onReceiveMsgAutoConfigProgress(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onReceiveMsgCardData(byte arg0, byte[] arg1) {
// TODO Auto-generated method stub
Log.d("SWIPE", "Card swiped!");
Toast.makeText(getApplicationContext(), "Card swiped!", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceiveMsgCommandResult(int arg0, byte[] arg1) {
// TODO Auto-generated method stub
}
@Override
public void onReceiveMsgConnected() {
Log.d("CONNECTION","Swiper Connected");
Toast.makeText(getApplicationContext(), "Swiper Connected!", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceiveMsgDisconnected() {
Log.d("CONNECTION","Swiper Disconnected");
Toast.makeText(getApplicationContext(), "Swiper Disconnected!", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceiveMsgFailureInfo(int arg0, String arg1) {
// TODO Auto-generated method stub
Log.d("CONNECTION","Swiper Failure");
}
@Override
public void onReceiveMsgSDCardDFailed(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onReceiveMsgTimeout(String arg0) {
Log.d("TIMEOUT","Timed out!");
Toast.makeText(getApplicationContext(), "Timed out!", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceiveMsgToConnect() {
Log.d("CONNECTION","Swiper Powered Up");
Toast.makeText(getApplicationContext(), "Swiper Powered Up", Toast.LENGTH_SHORT).show();
}
@Override
public void onReceiveMsgToSwipeCard() {
Log.d("SWIPE","Ready to swipe!");
Toast.makeText(getApplicationContext(), "Ready to swipe!", Toast.LENGTH_SHORT).show();
}
//********************************************************************************//
private void InitializeReader()
{
if(myUniMagReader==null)
myUniMagReader = new uniMagReader(this,this);
myUniMagReader.setVerboseLoggingEnable(true);
myUniMagReader.registerListen();
//load the XML configuratin file
String fileNameWithPath = getXMLFileFromRaw();
if(!isFileExist(fileNameWithPath)) { fileNameWithPath = null; }
myUniMagReader.setXMLFileNameWithPath(fileNameWithPath);
myUniMagReader.loadingConfigurationXMLFile(true);
myUniMagReader.setTimeoutOfSwipeCard(5);
}
private boolean isFileExist(String path) {
if(path==null)
return false;
File file = new File(path);
if (!file.exists()) {
return false ;
}
return true;
}
private String getXMLFileFromRaw( ){
//the target filename in the application path
String fileNameWithPath = null;
fileNameWithPath = "idt_unimagcfg_default.xml";
try{
InputStream in = getResources().openRawResource(R.raw.idt_unimagcfg_default);
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 = fileNameWithPath+java.io.File.separator+"idt_unimagcfg_default.xml";
}
catch(Exception e){
e.printStackTrace();
fileNameWithPath = null;
}
return fileNameWithPath;
}
public void swipe(View v)
{
if(myUniMagReader!=null)
{
myUniMagReader.startSwipeCard();
}
if(myUniMagReader.isSwipeCardRunning()==true)
{
Log.d("SWIPE","Swipe Card Running!");
}
}
private String getHexStringFromBytes(byte []data)
{
if(data.length<=0) return null;
StringBuffer hexString = new StringBuffer();
String fix = null;
for (int i = 0; i < data.length; i++) {
fix = Integer.toHexString(0xFF & data[i]);
if(fix.length()==1)
fix = "0"+fix;
hexString.append(fix);
}
fix = null;
fix = hexString.toString();
return fix;
}
public byte[] getBytesFromHexString(String strHexData)
{
if (1==strHexData.length()%2) {
return null;
}
byte[] bytes = new byte[strHexData.length()/2];
for (int i=0;i<strHexData.length()/2;i++) {
bytes[i] = (byte) Integer.parseInt(strHexData.substring(i*2, (i+1)*2) , 16);
}
return bytes;
}
}
(There are some unimplemented methods there as well)
回答1:
Here's what I used with the UniMag. Using a handler to output the swiped data, and a 'Swipe' button to start the swiping. To improve, one should wait until the card reader reports it is connected / ready to swipe, then enable the button, disable while waiting for swipe, and re-enable after receiving data.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import IDTech.MSR.XMLManager.StructConfigParameters;
import IDTech.MSR.uniMag.uniMagReader;
import IDTech.MSR.uniMag.uniMagReaderMsg;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements uniMagReaderMsg {
private uniMagReader myUniMagReader = null;
private Button btnSwipe;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(myUniMagReader == null) {
myUniMagReader = new uniMagReader(this,this);
myUniMagReader.setSaveLogEnable(false);
myUniMagReader.setXMLFileNameWithPath(null);
myUniMagReader.loadingConfigurationXMLFile(true);
//myUniMagReader.setVerboseLoggingEnable(true);
myUniMagReader.registerListen();
}
btnSwipe = (Button) findViewById(R.id.button1);
btnSwipe.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
myUniMagReader.startSwipeCard();
}
});
}
@Override
public void onDestroy() {
myUniMagReader.stopSwipeCard();
myUniMagReader.unregisterListen();
myUniMagReader.release();
super.onDestroy();
}
@Override
public boolean getUserGrant(int arg0, String arg1) {
Log.d("UniMag", "getUserGrant -- " + arg1);
return true;
}
@Override
public void onReceiveMsgAutoConfigProgress(int arg0) {
// TODO Auto-generated method stub
Log.d("UniMag", "onReceiveMsgAutoConfigProgress");
}
@Override
public void onReceiveMsgCardData(byte arg0, byte[] arg1) {
Log.d("UniMag", "onReceiveMsgCardData");
Log.d("UniMag", "Successful swipe!");
String strData = new String(arg1);
Log.d("UniMag", "SWIPE - " + strData);
if(myUniMagReader.isSwipeCardRunning()) {
myUniMagReader.stopSwipeCard();
}
// Match the data we want.
String pattern = "%B(\\d+)\\^([^\\^]+)\\^(\\d{4})";
Log.d("UniMag", pattern);
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(strData);
String card = "";
String name = "";
String exp = "";
String data = "";
if(m.find()) {
for(int a = 0; a < m.groupCount(); ++a) {
Log.d("UniMag", a + " - "+m.group(a));
}
card = m.group(1);
name = m.group(2);
exp = m.group(3);
data = "Data: " + name + " -- " + card + " -- " + exp;
Log.d("UniMag", data);
Message msg = new Message();
msg.obj = data;
swipeHandler.sendMessage(msg);
}
}
final Handler swipeHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
TextView dataView = (TextView) findViewById(R.id.text_view);
dataView.setText(text);
}
};
@Override
public void onReceiveMsgCommandResult(int arg0, byte[] arg1) {
Log.d("UniMag", "onReceiveMsgCommandResult");
}
@Override
public void onReceiveMsgConnected() {
Log.d("UniMag", "onReceiveMsgConnected");
Log.d("UniMag", "Card reader is connected.");
}
@Override
public void onReceiveMsgDisconnected() {
Log.d("UniMag", "onReceiveMsgDisconnected");
if(myUniMagReader.isSwipeCardRunning()) {
myUniMagReader.stopSwipeCard();
}
myUniMagReader.release();
}
@Override
public void onReceiveMsgFailureInfo(int arg0, String arg1) {
Log.d("UniMag","onReceiveMsgFailureInfo -- " + arg1);
}
@Override
public void onReceiveMsgSDCardDFailed(String arg0) {
Log.d("UniMag", "onReceiveMsgSDCardDFailed -- " + arg0);
}
@Override
public void onReceiveMsgTimeout(String arg0) {
Log.d("UniMag", "onReceiveMsgTimeout -- " + arg0);
Log.d("UniMag","Timed out!");
}
@Override
public void onReceiveMsgToConnect() {
Log.d("UniMag","Swiper Powered Up");
}
@Override
public void onReceiveMsgToSwipeCard() {
Log.d("UniMag","onReceiveMsgToSwipeCard");
}
@Override
public void onReceiveMsgAutoConfigCompleted(StructConfigParameters arg0) {
Log.d("UniMag", "onReceiveMsgAutoConfigCompleted");
}
}
回答2:
I found that the 3.8 demo app they ship with the SDK has a bug where it will not connect to an Android gt-p3113 tablet unless you go into settings on the app on the phone and turn off 'Command To Connect'.
来源:https://stackoverflow.com/questions/12079050/idtech-unimag-card-swiper-on-android