如何使用 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?的主要内容,如果未能解决你的问题,请参考以下文章

MagTek -- uDynamo (DUKPT)

IMX6ULL学习笔记(12)——通过SD卡启动官方SDK程序

IMX6ULL学习笔记(12)——通过SD卡启动官方SDK程序

智能卡读卡器常见使用方法

智能卡读卡器常见使用方法

我想知道如何通过应用程序控制此读卡器设备我可以使用的任何代码或对我有帮助的示例