Android 上的 IDTech Unimag 刷卡器
Posted
技术标签:
【中文标题】Android 上的 IDTech Unimag 刷卡器【英文标题】:IDTech Unimag Card Swiper on Android 【发布时间】:2012-08-18 05:26:03 【问题描述】:我已经在 Android (v2.3) 上工作了几个星期了,我偶然发现了 IDTECH 的 Unimag Card Swiper 的一些问题.
该单元带有一个稀缺的文档,来自 SDK 的演示应用程序实现了固件更新和一些用于对话框的类等,这确实混淆了如何实现基本功能(添加到代码中的少数而不那么好的 cmets )。
我已经在一个基本活动中实现了接口,并试图检测单元何时连接或断开,但似乎侦听器将这两个事件(连接/断开)都捕获为“断开”,更不用说尝试读取卡了。
有人在 Android 上使用过这个单元并有一些明确的例子吗?
顺便说一下,这是我的课:
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;
(也有一些未实现的方法)
【问题讨论】:
是的,我做到了,请查看下面关于解决方案的评论。我早就解决了,但忘了回来,卓尔的解决方案无论如何都是正确的。 SDK 是从哪里下载的?我一直试图找到它,但无济于事。 嘿阿瑞斯,当我的客户购买阅读器时,我直接从 IDTech 得到它。但是,我在电子邮件中找到了 SDK,我将它与发行说明和手册一起上传到这里:tempsend.com/EA3D8889C9 - 请注意,它是 2012 年的旧版本 (v2.8)。希望对您有所帮助! 大家好,我知道这是一篇旧帖子,但我现在开始与 Unimag 合作,老实说,我完全不知道如何开始。我收到了 SDK 和手册,但它似乎不是一个好的开始方式,我的意思是,他们的演示代码有超过 4k 的代码行,我正在尝试从基础开始。您在哪里找到有关 Unimag 开发的信息?除了示例代码还有什么?有人找到其他示例代码吗?非常感谢!! 嘿,我已经很久没有研究这个了,我几乎不记得了,但如果我没记错的话,文档非常稀缺。我在网上找不到任何东西,所有文档都必须直接向他们索取,但无非就是手册和 SDK。 SO中还有一些其他的Unimag问题,您也许可以找到更多的东西。 【参考方案1】:这是我与 UniMag 一起使用的。使用处理程序输出刷过的数据,并使用“刷卡”按钮开始刷卡。为了改进,应该等到读卡器报告它已连接/准备刷卡,然后启用按钮,等待刷卡时禁用,并在收到数据后重新启用。
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+)\\^([^\\^]+)\\^(\\d4)";
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");
【讨论】:
嗨@drowe。我有一个 UniMag 阅读器,但我没有最新的 SDK……你知道我是否在没有这些行的情况下运行项目:myUniMagReader.setXMLFileNameWithPath(null);和 myUniMagReader.loadingConfigurationXMLFile(true);会变得不可能让它工作吗?我试过了,尽管 myUniMagReader.getIsToSwipeCard() 为“true”,但当我刷卡时处理程序没有收到任何数据……阅读器与 UniMagIIDemo 应用程序完美配合。 上面的代码能用吗?实际上,我正在开发一个使用 Unimag 2 作为刷卡器的项目。我有它的 SDK 和演示,但如您所知,演示应用程序非常复杂。最主要的是客户还没有给我发送 unimag swiper。他要求制作一个没有 swiper 的演示。这就是为什么我需要一个 Unimag 2 阅读器的简单工作示例。有什么帮助吗? 示例正在运行,pin 码和加密和解密的东西呢?你知道如何实现这些东西吗...??? 我不知道 PIN 是否可以访问 - 可能是?我没有努力获取该信息,我只是想将姓名附在卡片上。 哇,很抱歉迟到了,迟到的回复!我很久以前解决了这个问题,忘了回来发布答案,以为没有人在使用 Unimag。我将卓尔的解决方案标记为正确,因为它非常准确,并且通过阅读它几乎与我当时所做的相同。 @KhawarRaza 您对加密/解密有什么问题?当用户手动介绍他的信用卡信息时,我还必须手动“模拟”设备的加密/解密过程。我可以查看该代码并分享它。【参考方案2】:我发现他们与 SDK 一起提供的 3.8 演示应用程序存在一个错误,即它无法连接到 Android gt-p3113 平板电脑,除非您进入手机应用程序的设置并关闭“连接命令”。
【讨论】:
是的,Unimag 的 SDK 到处都有一些错误,必须小心谨慎。以上是关于Android 上的 IDTech Unimag 刷卡器的主要内容,如果未能解决你的问题,请参考以下文章
如何在 IOS 中使用 IDTECH 刷卡器读取信用卡信息?