如何使用 MagTek 读卡器设备的 sdk for android?
Posted
技术标签:
【中文标题】如何使用 MagTek 读卡器设备的 sdk for android?【英文标题】:How to use MagTek card reader device's sdk for android? 【发布时间】:2017-02-04 14:19:26 【问题描述】:我正在使用 magtek 读卡器音频 uDynamo 设备,并且正在将 sdk 与我的 android 应用程序集成。但是当我试图通过 openDevice() 方法打开设备时。申请不幸停止。为什么会这样?
这就是我正在做的事情
m_SCRA.setConnectionType(MTConnectionType.Audio);
m_SCRA.setAddress(m_deviceAddress);
m_connectionState = MTConnectionState.Connected;
// here its stopping
m_SCRA.openDevice();
完整的源代码
public class MainActivity extends AppCompatActivity
private MTSCRA m_SCRA;
private Button btn;
private TextView txt;
private TextView txt1;
private TextView msg;
private TextView msg2;
private boolean m_startTransactionActionPending;
private boolean m_turnOffLEDPending;
private EditText Edit;
private AudioManager m_audioManager;
private int m_audioVolume;
private String m_deviceAddress;
private MTConnectionType m_connectionType;
private MTConnectionState m_connectionState = MTConnectionState.Disconnected;
private Handler m_scraHandler = new Handler(new SCRAHandlerCallback());
private class SCRAHandlerCallback implements Handler.Callback
public boolean handleMessage(Message msg)
try
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert Switch");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int which)
dialog.dismiss();
);
alertDialog.show();
switch (msg.what)
case MTSCRAEvent.OnDeviceConnectionStateChanged:
OnDeviceStateChanged((MTConnectionState) msg.obj);
break;
case MTSCRAEvent.OnCardDataStateChanged:
OnCardDataStateChanged((MTCardDataState) msg.obj);
break;
case MTSCRAEvent.OnDataReceived:
OnCardDataReceived((IMTCardData) msg.obj);
break;
case MTSCRAEvent.OnDeviceResponse:
OnDeviceResponse((String) msg.obj);
break;
case MTEMVEvent.OnTransactionStatus:
OnTransactionStatus((byte[]) msg.obj);
break;
case MTEMVEvent.OnDisplayMessageRequest:
OnDisplayMessageRequest((byte[]) msg.obj);
break;
case MTEMVEvent.OnUserSelectionRequest:
OnUserSelectionRequest((byte[]) msg.obj);
break;
case MTEMVEvent.OnARQCReceived:
OnARQCReceived((byte[]) msg.obj);
break;
case MTEMVEvent.OnTransactionResult:
OnTransactionResult((byte[]) msg.obj);
break;
case MTEMVEvent.OnEMVCommandResult:
OnEMVCommandResult((byte[]) msg.obj);
break;
case MTEMVEvent.OnDeviceExtendedResponse:
OnDeviceExtendedResponse((String) msg.obj);
break;
catch (Exception ex)
return true;
public void OnCardDataReceived(IMTCardData cardData)
txt.setText(m_SCRA.getCardLast4());
protected void OnDeviceStateChanged(MTConnectionState deviceState)
setState(deviceState);
updateDisplay();
invalidateOptionsMenu();
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert ondevice state");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int which)
dialog.dismiss();
);
alertDialog.show();
switch (deviceState)
case Disconnected:
if (m_connectionType == MTConnectionType.Audio)
restoreVolume();
break;
case Connected:
if (m_connectionType == MTConnectionType.Audio)
setVolumeToMax();
clearMessage();
clearMessage2();
break;
case Error:
sendToDisplay("[Device State Error]");
break;
case Connecting:
break;
case Disconnecting:
break;
protected void OnCardDataStateChanged(MTCardDataState cardDataState)
switch (cardDataState)
case DataNotReady:
sendToDisplay("[Card Data Not Ready]");
break;
case DataReady:
sendToDisplay("[Card Data Ready]");
break;
case DataError:
sendToDisplay("[Card Data Error]");
break;
protected void OnDeviceResponse(String data)
sendToDisplay("[Device Response]");
sendToDisplay(data);
if (m_startTransactionActionPending)
m_startTransactionActionPending = false;
startTransaction();
protected void OnTransactionStatus(byte[] data)
sendToDisplay("[Transaction Status]");
//sendToDisplay(TLVParser.getHexString(data));
protected void OnDisplayMessageRequest(byte[] data)
sendToDisplay("[Display Message Request]");
//String message = TLVParser.getTextString(data, 0);
//sendToDisplay(message);
//displayMessage(message);
protected void OnEMVCommandResult(byte[] data)
sendToDisplay("[EMV Command Result]");
//sendToDisplay(TLVParser.getHexString(data));
if (m_turnOffLEDPending)
m_turnOffLEDPending = false;
setLED(false);
protected void OnDeviceExtendedResponse(String data)
sendToDisplay("[Device Extended Response]");
sendToDisplay(data);
protected void OnUserSelectionRequest(byte[] data)
sendToDisplay("[User Selection Request]");
//sendToDisplay(TLVParser.getHexString(data));
//processSelectionRequest(data);
protected void OnARQCReceived(byte[] data)
sendToDisplay("[ARQC Received]");
/*sendToDisplay(TLVParser.getHexString(data));
List<HashMap<String, String>> parsedTLVList = TLVParser.parseEMVData(data, true, "");
if (parsedTLVList != null)
String deviceSNString = TLVParser.getTagValue(parsedTLVList, "DFDF25");
byte[] deviceSN = TLVParser.getByteArrayFromHexString(deviceSNString);
sendToDisplay("SN Bytes=" + deviceSNString);
sendToDisplay("SN String=" + TLVParser.getTextString(deviceSN, 2));
boolean approved = true;
if (mMainMenu != null)
approved = mMainMenu.findItem(R.id.menu_emv_approved).isChecked();
byte[] response = buildAcquirerResponse(deviceSN, approved);
setAcquirerResponse(response);
*/
protected void OnTransactionResult(byte[] data)
sendToDisplay("[Transaction Result]");
//sendToDisplay(TLVParser.getHexString(data));
/*if (data != null)
if (data.length > 0)
boolean signatureRequired = (data[0] != 0);
int lenBatchData = data.length - 3;
if (lenBatchData > 0)
byte[] batchData = new byte[lenBatchData];
System.arraycopy(data, 3, batchData, 0, lenBatchData);
sendToDisplay("(Parsed Batch Data)");
List<HashMap<String, String>> parsedTLVList = TLVParser.parseEMVData(batchData, false, "");
displayParsedTLV(parsedTLVList);
String cidString = TLVParser.getTagValue(parsedTLVList, "9F27");
byte[] cidValue = TLVParser.getByteArrayFromHexString(cidString);
boolean approved = false;
if (cidValue != null)
if (cidValue.length > 0)
if ((cidValue[0] & (byte) 0x40) != 0)
approved = true;
if (approved)
if (signatureRequired)
displayMessage2("( Signature Required )");
else
displayMessage2("( No Signature Required )");
setLED(false);*/
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = ( Button) findViewById(R.id.btn);
txt = (TextView) findViewById(R.id.txt1);
txt1 = (TextView) findViewById(R.id.txt2);
msg = (TextView) findViewById(R.id.msgtext1);
msg2 = (TextView) findViewById(R.id.msgtext2);
Edit = (EditText) findViewById(R.id.editText);
//m_SCRA.setConnectionType(MTConnectionType.Audio);
//if (! m_SCRA.isDeviceConnected())
//
// m_SCRA.openDevice();
//
m_audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
m_SCRA = new MTSCRA(this, m_scraHandler);
btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
m_connectionType = MTConnectionType.Audio;
m_SCRA.setConnectionType(MTConnectionType.Audio);
m_SCRA.setAddress(m_deviceAddress);
m_connectionState = MTConnectionState.Connected;
m_SCRA.openDevice();
);
private void sendToDisplay(final String data)
if (data != null)
runOnUiThread(new Runnable()
@Override
public void run()
Edit.append(data + "\n");
);
private void setState(MTConnectionState deviceState)
m_connectionState = deviceState;
updateDisplay();
invalidateOptionsMenu();
private void updateDisplay()
runOnUiThread(new Runnable()
@Override
public void run()
if (m_connectionState == MTConnectionState.Connected)
updateConnectionState(R.string.connected);
else if (m_connectionState == MTConnectionState.Connecting)
updateConnectionState(R.string.connecting);
else if (m_connectionState == MTConnectionState.Disconnecting)
updateConnectionState(R.string.disconnecting);
else if (m_connectionState == MTConnectionState.Disconnected)
updateConnectionState(R.string.disconnected);
);
private void updateConnectionState(final int resourceId)
runOnUiThread(new Runnable()
@Override
public void run()
txt1.setText(resourceId);
);
private void restoreVolume()
setVolume(m_audioVolume);
private void setVolumeToMax()
saveVolume();
android.app.AlertDialog alertDialog = new android.app.AlertDialog.Builder(MainActivity.this).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Alert volume max");
alertDialog.setButton(android.app.AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int which)
dialog.dismiss();
);
alertDialog.show();
int volume = m_audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
setVolume(volume);
private void setVolume(int volume)
m_audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, AudioManager.FLAG_SHOW_UI);
private void saveVolume()
m_audioVolume = m_audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
private void clearMessage()
runOnUiThread(new Runnable()
@Override
public void run()
msg.setText("");
);
private void clearMessage2()
runOnUiThread(new Runnable()
@Override
public void run()
msg2.setText("");
);
public void startTransaction()
if (m_SCRA != null)
byte timeLimit = 0x3C;
//byte cardType = 0x02; // Chip Only
byte cardType = 0x03; // MSR + Chip
byte option = 0x00;
byte[] amount = new byte[] 0x00, 0x00, 0x00, 0x00, 0x15, 0x00;
byte transactionType = 0x00; // Purchase
byte[] cashBack = new byte[] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00;
byte[] currencyCode = new byte[] 0x08, 0x40;
byte reportingOption = 0x02; // All Status Changes
clearMessage();
clearMessage2();
int result = m_SCRA.startTransaction(timeLimit, cardType, option, amount, transactionType, cashBack, currencyCode, reportingOption);
sendToDisplay("[Start Transaction] (Result=" + result + ")");
public void setLED(boolean on)
if (m_SCRA != null)
if (on)
m_SCRA.sendCommandToDevice(MTDeviceConstants.SCRA_DEVICE_COMMAND_STRING_SET_LED_ON);
else
m_SCRA.sendCommandToDevice(MTDeviceConstants.SCRA_DEVICE_COMMAND_STRING_SET_LED_OFF);
【问题讨论】:
Logcat 显示什么错误? 应用不幸停止工作这个错误.. 不,日志监视器控制台中的错误堆栈跟踪 Logcat 在 java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) at com.android .internal.os.ZygoteInit.main(ZygoteInit.java:618) 致命异常:Magtek 音频阅读器通信线程进程:com.example.karanveer.cardreaderexample,PID:28348 java.lang.IllegalStateException:startRecording() 在未初始化的 AudioRecord 上调用。 【参考方案1】:我遇到了同样的问题。原来我忘记了录音运行时权限。
private void checkRecordPermission()
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(getActivity(), new String[]Manifest.permission.RECORD_AUDIO,
123);
【讨论】:
以上是关于如何使用 MagTek 读卡器设备的 sdk for android?的主要内容,如果未能解决你的问题,请参考以下文章
IMX6ULL学习笔记(12)——通过SD卡启动官方SDK程序